blob: d8eea59976e8c682839a7f9beb6cba3ea971ad15 [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"
Martin Radev14a26ae2017-07-24 15:56:29 +030011#include "test_utils/ANGLETest.h"
12#include "test_utils/gl_raii.h"
13
14using namespace angle;
15
Martin Radev61bd9992017-08-11 13:10:55 +030016namespace
17{
Martin Radevced5c862017-08-17 16:05:29 +030018GLuint CreateSimplePassthroughProgram(int numViews)
Martin Radev61bd9992017-08-11 13:10:55 +030019{
20 const std::string vsSource =
21 "#version 300 es\n"
22 "#extension GL_OVR_multiview : require\n"
Martin Radevced5c862017-08-17 16:05:29 +030023 "layout(num_views = " +
24 ToString(numViews) +
25 ") in;\n"
Martin Radev61bd9992017-08-11 13:10:55 +030026 "layout(location=0) in vec2 vPosition;\n"
27 "void main()\n"
28 "{\n"
Martin Radevced5c862017-08-17 16:05:29 +030029 " gl_PointSize = 1.;\n"
Martin Radev61bd9992017-08-11 13:10:55 +030030 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
31 "}\n";
32
33 const std::string fsSource =
34 "#version 300 es\n"
35 "#extension GL_OVR_multiview : require\n"
36 "precision mediump float;\n"
37 "out vec4 col;\n"
38 "void main()\n"
39 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +030040 " col = vec4(0,1,0,1);\n"
Martin Radev61bd9992017-08-11 13:10:55 +030041 "}\n";
42 return CompileProgram(vsSource, fsSource);
43}
44
45std::vector<Vector2> ConvertPixelCoordinatesToClipSpace(const std::vector<Vector2I> &pixels,
46 int width,
47 int height)
48{
49 std::vector<Vector2> result(pixels.size());
50 for (size_t i = 0; i < pixels.size(); ++i)
51 {
52 const auto &pixel = pixels[i];
53 float pixelCenterRelativeX = (static_cast<float>(pixel.x()) + .5f) / width;
54 float pixelCenterRelativeY = (static_cast<float>(pixel.y()) + .5f) / height;
55 float xInClipSpace = 2.f * pixelCenterRelativeX - 1.f;
56 float yInClipSpace = 2.f * pixelCenterRelativeY - 1.f;
57 result[i] = Vector2(xInClipSpace, yInClipSpace);
58 }
59 return result;
60}
61} // namespace
62
Martin Radevc1d4e552017-08-21 12:01:10 +030063struct MultiviewImplementationParams : public PlatformParameters
Martin Radev3c25ad02017-08-22 17:36:53 +030064{
Martin Radevc1d4e552017-08-21 12:01:10 +030065 MultiviewImplementationParams(bool forceUseGeometryShaderOnD3D,
66 const EGLPlatformParameters &eglPlatformParameters)
67 : PlatformParameters(3, 0, eglPlatformParameters),
68 mForceUseGeometryShaderOnD3D(forceUseGeometryShaderOnD3D)
69 {
70 }
71 bool mForceUseGeometryShaderOnD3D;
72};
73
74std::ostream &operator<<(std::ostream &os, const MultiviewImplementationParams &params)
75{
76 const PlatformParameters &base = static_cast<const PlatformParameters &>(params);
77 os << base;
78 if (params.mForceUseGeometryShaderOnD3D)
79 {
80 os << "_force_geom_shader";
81 }
82 else
83 {
84 os << "_vertex_shader";
85 }
86 return os;
87}
88
89struct MultiviewTestParams final : public MultiviewImplementationParams
90{
91 MultiviewTestParams(GLenum multiviewLayout,
92 const MultiviewImplementationParams &implementationParams)
93 : MultiviewImplementationParams(implementationParams), mMultiviewLayout(multiviewLayout)
Martin Radev3c25ad02017-08-22 17:36:53 +030094 {
95 ASSERT(multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE ||
96 multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
97 }
98 GLenum mMultiviewLayout;
99};
100
101std::ostream &operator<<(std::ostream &os, const MultiviewTestParams &params)
102{
Martin Radevc1d4e552017-08-21 12:01:10 +0300103 const MultiviewImplementationParams &base =
104 static_cast<const MultiviewImplementationParams &>(params);
Martin Radev3c25ad02017-08-22 17:36:53 +0300105 os << base;
106 switch (params.mMultiviewLayout)
107 {
108 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
109 os << "_layered";
110 break;
111 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
112 os << "_side_by_side";
113 break;
114 default:
115 UNREACHABLE();
116 }
117 return os;
118}
119
120class MultiviewDrawTest : public ANGLETestBase
Martin Radev14a26ae2017-07-24 15:56:29 +0300121{
122 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300123 MultiviewDrawTest(const PlatformParameters &params) : ANGLETestBase(params)
Martin Radev14a26ae2017-07-24 15:56:29 +0300124 {
125 setWindowWidth(128);
126 setWindowHeight(128);
127 setWebGLCompatibilityEnabled(true);
128 }
Martin Radev7cf61662017-07-26 17:10:53 +0300129 virtual ~MultiviewDrawTest() {}
Martin Radev14a26ae2017-07-24 15:56:29 +0300130
Martin Radev3c25ad02017-08-22 17:36:53 +0300131 void DrawTestSetUp()
Martin Radev14a26ae2017-07-24 15:56:29 +0300132 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300133 ANGLETestBase::ANGLETestSetUp();
Martin Radev14a26ae2017-07-24 15:56:29 +0300134
135 glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
136 eglGetProcAddress("glRequestExtensionANGLE"));
137 }
138
139 // Requests the ANGLE_multiview extension and returns true if the operation succeeds.
140 bool requestMultiviewExtension()
141 {
142 if (extensionRequestable("GL_ANGLE_multiview"))
143 {
144 glRequestExtensionANGLE("GL_ANGLE_multiview");
145 }
146
147 if (!extensionEnabled("GL_ANGLE_multiview"))
148 {
149 std::cout << "Test skipped due to missing GL_ANGLE_multiview." << std::endl;
150 return false;
151 }
152 return true;
153 }
154
155 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
156};
157
Martin Radev3c25ad02017-08-22 17:36:53 +0300158class MultiviewDrawValidationTest : public MultiviewDrawTest,
159 public ::testing::TestWithParam<PlatformParameters>
Martin Radev7cf61662017-07-26 17:10:53 +0300160{
161 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300162 MultiviewDrawValidationTest() : MultiviewDrawTest(GetParam()) {}
Martin Radev7cf61662017-07-26 17:10:53 +0300163
164 void SetUp() override
165 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300166 MultiviewDrawTest::DrawTestSetUp();
Martin Radev7cf61662017-07-26 17:10:53 +0300167
168 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
169
170 glBindTexture(GL_TEXTURE_2D, mTex2d);
171 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
172
173 glBindVertexArray(mVao);
174
175 const float kVertexData[3] = {0.0f};
176 glBindBuffer(GL_ARRAY_BUFFER, mVbo);
177 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3u, &kVertexData[0], GL_STATIC_DRAW);
178
179 const unsigned int kIndices[3] = {0u, 1u, 2u};
180 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIbo);
181 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, &kIndices[0],
182 GL_STATIC_DRAW);
183 ASSERT_GL_NO_ERROR();
184 }
185
186 GLTexture mTex2d;
187 GLVertexArray mVao;
188 GLBuffer mVbo;
189 GLBuffer mIbo;
190 GLFramebuffer mFramebuffer;
191};
192
Martin Radev3c25ad02017-08-22 17:36:53 +0300193class MultiviewRenderTestBase : public MultiviewDrawTest
Martin Radev8f276e22017-05-30 12:05:52 +0300194{
195 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300196 MultiviewRenderTestBase(const PlatformParameters &params, GLenum multiviewLayout)
197 : MultiviewDrawTest(params),
198 mMultiviewLayout(multiviewLayout),
199 mViewWidth(0),
200 mViewHeight(0),
201 mNumViews(0)
Martin Radev8f276e22017-05-30 12:05:52 +0300202 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300203 }
204 void RenderTestSetUp() { MultiviewDrawTest::DrawTestSetUp(); }
Martin Radev72b4e1e2017-08-31 15:42:56 +0300205 void createFBO(int viewWidth, int height, int numViews, int numLayers, int baseViewIndex)
Martin Radev3c25ad02017-08-22 17:36:53 +0300206 {
Martin Radev72b4e1e2017-08-31 15:42:56 +0300207 ASSERT(numViews + baseViewIndex <= numLayers);
208
Martin Radev3c25ad02017-08-22 17:36:53 +0300209 mViewWidth = viewWidth;
210 mViewHeight = height;
211 mNumViews = numViews;
Martin Radev8f276e22017-05-30 12:05:52 +0300212
Martin Radev0abb7a22017-08-28 15:34:45 +0300213 mColorTexture.reset();
214 mDepthTexture.reset();
215 mDrawFramebuffer.reset();
216 mReadFramebuffer.clear();
217
Martin Radev8f276e22017-05-30 12:05:52 +0300218 // Create color and depth textures.
Martin Radev3c25ad02017-08-22 17:36:53 +0300219 switch (mMultiviewLayout)
Martin Radev8f276e22017-05-30 12:05:52 +0300220 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300221 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
222 {
223 int textureWidth = viewWidth * numViews;
224 glBindTexture(GL_TEXTURE_2D, mColorTexture);
225 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, height, 0, GL_RGBA,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500226 GL_UNSIGNED_BYTE, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
229
230 glBindTexture(GL_TEXTURE_2D, mDepthTexture);
231 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, textureWidth, height, 0,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500232 GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300233 glBindTexture(GL_TEXTURE_2D, 0);
234 break;
235 }
236 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
237 glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTexture);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300238 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, viewWidth, height, numLayers, 0,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500239 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300240 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
241 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
242
243 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTexture);
244 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, viewWidth, height,
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500245 numLayers, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
Martin Radev3c25ad02017-08-22 17:36:53 +0300246 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
247 break;
248 default:
249 UNREACHABLE();
Martin Radev8f276e22017-05-30 12:05:52 +0300250 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300251 ASSERT_GL_NO_ERROR();
252
253 // Create draw framebuffer to be used for multiview rendering.
254 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
255 switch (mMultiviewLayout)
256 {
257 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
258 {
259 std::vector<GLint> viewportOffsets(numViews * 2);
260 for (int i = 0u; i < numViews; ++i)
261 {
262 viewportOffsets[i * 2] = i * viewWidth;
263 viewportOffsets[i * 2 + 1] = 0;
264 }
265 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER,
266 GL_COLOR_ATTACHMENT0, mColorTexture, 0,
267 numViews, &viewportOffsets[0]);
268 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER,
269 GL_DEPTH_ATTACHMENT, mDepthTexture, 0,
270 numViews, &viewportOffsets[0]);
271 break;
272 }
273 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
274 glFramebufferTextureMultiviewLayeredANGLE(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
Martin Radev72b4e1e2017-08-31 15:42:56 +0300275 mColorTexture, 0, baseViewIndex,
276 numViews);
Martin Radev3c25ad02017-08-22 17:36:53 +0300277 glFramebufferTextureMultiviewLayeredANGLE(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
Martin Radev72b4e1e2017-08-31 15:42:56 +0300278 mDepthTexture, 0, baseViewIndex,
279 numViews);
Martin Radev3c25ad02017-08-22 17:36:53 +0300280 break;
281 default:
282 UNREACHABLE();
283 }
Martin Radev8f276e22017-05-30 12:05:52 +0300284
285 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
286 glDrawBuffers(1, DrawBuffers);
287 ASSERT_GL_NO_ERROR();
288 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
289
290 // Create read framebuffer to be used to retrieve the pixel information for testing
291 // purposes.
Martin Radev3c25ad02017-08-22 17:36:53 +0300292 switch (mMultiviewLayout)
293 {
294 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
295 mReadFramebuffer.resize(1);
296 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[0]);
297 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
298 mColorTexture, 0);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300299 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
300 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300301 break;
302 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev72b4e1e2017-08-31 15:42:56 +0300303 mReadFramebuffer.resize(numLayers);
304 for (int i = 0; i < numLayers; ++i)
Martin Radev3c25ad02017-08-22 17:36:53 +0300305 {
Martin Radev72b4e1e2017-08-31 15:42:56 +0300306 glBindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer[i]);
307 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture,
308 0, i);
309 glClearColor(0, 0, 0, 0);
310 glClear(GL_COLOR_BUFFER_BIT);
311 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
312 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300313 }
Martin Radev72b4e1e2017-08-31 15:42:56 +0300314 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
Martin Radev3c25ad02017-08-22 17:36:53 +0300315 break;
316 default:
317 UNREACHABLE();
318 }
Martin Radev8f276e22017-05-30 12:05:52 +0300319
320 // Clear the buffers.
Martin Radev3c25ad02017-08-22 17:36:53 +0300321 glViewport(0, 0, viewWidth, height);
322 if (mMultiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
323 {
324 // Enable the scissor test only for side-by-side framebuffers.
325 glEnable(GL_SCISSOR_TEST);
326 glScissor(0, 0, viewWidth, height);
327 }
Martin Radev61bd9992017-08-11 13:10:55 +0300328 glClearColor(0, 0, 0, 1);
Martin Radev8f276e22017-05-30 12:05:52 +0300329 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev3c25ad02017-08-22 17:36:53 +0300330 }
Martin Radev8f276e22017-05-30 12:05:52 +0300331
Martin Radev72b4e1e2017-08-31 15:42:56 +0300332 void createFBO(int viewWidth, int height, int numViews)
333 {
334 createFBO(viewWidth, height, numViews, numViews, 0);
335 }
336
Martin Radev3c25ad02017-08-22 17:36:53 +0300337 GLColor GetViewColor(int x, int y, int view)
338 {
339 switch (mMultiviewLayout)
340 {
341 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
342 return ReadColor(view * mViewWidth + x, y);
343 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
344 ASSERT(static_cast<size_t>(view) < mReadFramebuffer.size());
345 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[view]);
346 return ReadColor(x, y);
347 default:
348 UNREACHABLE();
349 }
350 return GLColor(0, 0, 0, 0);
Martin Radev8f276e22017-05-30 12:05:52 +0300351 }
352
353 GLTexture mColorTexture;
354 GLTexture mDepthTexture;
355 GLFramebuffer mDrawFramebuffer;
Martin Radev3c25ad02017-08-22 17:36:53 +0300356 std::vector<GLFramebuffer> mReadFramebuffer;
357 GLenum mMultiviewLayout;
358 int mViewWidth;
359 int mViewHeight;
360 int mNumViews;
Martin Radev8f276e22017-05-30 12:05:52 +0300361};
362
Martin Radev3c25ad02017-08-22 17:36:53 +0300363class MultiviewRenderTest : public MultiviewRenderTestBase,
364 public ::testing::TestWithParam<MultiviewTestParams>
Martin Radev8f276e22017-05-30 12:05:52 +0300365{
366 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300367 MultiviewRenderTest() : MultiviewRenderTestBase(GetParam(), GetParam().mMultiviewLayout) {}
368 void SetUp() override { MultiviewRenderTestBase::RenderTestSetUp(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300369
370 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
371 {
372 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
373 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300374};
375
376class MultiviewRenderDualViewTest : public MultiviewRenderTest
377{
378 protected:
379 MultiviewRenderDualViewTest() : mProgram(0u) {}
380 ~MultiviewRenderDualViewTest()
Martin Radev8f276e22017-05-30 12:05:52 +0300381 {
382 if (mProgram != 0u)
383 {
384 glDeleteProgram(mProgram);
385 }
386 }
387
388 void SetUp() override
389 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300390 MultiviewRenderTest::SetUp();
Martin Radev8f276e22017-05-30 12:05:52 +0300391
392 if (!requestMultiviewExtension())
393 {
394 return;
395 }
396
397 const std::string vsSource =
398 "#version 300 es\n"
399 "#extension GL_OVR_multiview : require\n"
400 "layout(num_views = 2) in;\n"
401 "in vec4 vPosition;\n"
402 "void main()\n"
403 "{\n"
404 " gl_Position.x = (gl_ViewID_OVR == 0u ? vPosition.x*0.5 + 0.5 : vPosition.x*0.5);\n"
405 " gl_Position.yzw = vPosition.yzw;\n"
406 "}\n";
407
408 const std::string fsSource =
409 "#version 300 es\n"
410 "#extension GL_OVR_multiview : require\n"
411 "precision mediump float;\n"
412 "out vec4 col;\n"
413 "void main()\n"
414 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300415 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300416 "}\n";
417
Martin Radev3c25ad02017-08-22 17:36:53 +0300418 createFBO(2, 1, 2);
Martin Radev61bd9992017-08-11 13:10:55 +0300419 mProgram = CompileProgram(vsSource, fsSource);
420 ASSERT_NE(mProgram, 0u);
Martin Radev8f276e22017-05-30 12:05:52 +0300421 glUseProgram(mProgram);
422 ASSERT_GL_NO_ERROR();
423 }
424
425 void checkOutput()
426 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300427 EXPECT_EQ(GLColor::black, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +0300428 EXPECT_EQ(GLColor::green, GetViewColor(1, 0, 0));
429 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev3c25ad02017-08-22 17:36:53 +0300430 EXPECT_EQ(GLColor::black, GetViewColor(1, 0, 1));
Martin Radev8f276e22017-05-30 12:05:52 +0300431 }
432
433 GLuint mProgram;
434};
435
Martin Radev3c25ad02017-08-22 17:36:53 +0300436class MultiviewOcclusionQueryTest : public MultiviewRenderTest
Martin Radev0d671c92017-08-10 16:41:52 +0300437{
438 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300439 MultiviewOcclusionQueryTest() {}
Martin Radev0d671c92017-08-10 16:41:52 +0300440
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400441 bool requestOcclusionQueryExtension()
442 {
443 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
444 {
445 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
446 }
447
448 if (!extensionEnabled("GL_EXT_occlusion_query_boolean"))
449 {
450 std::cout << "Test skipped due to missing GL_EXT_occlusion_query_boolean." << std::endl;
451 return false;
452 }
453 return true;
454 }
455
Martin Radev0d671c92017-08-10 16:41:52 +0300456 GLuint drawAndRetrieveOcclusionQueryResult(GLuint program)
457 {
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400458 GLQueryEXT query;
459 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED, query);
Martin Radev0d671c92017-08-10 16:41:52 +0300460 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
461 glEndQueryEXT(GL_ANY_SAMPLES_PASSED);
462
463 GLuint result = GL_TRUE;
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400464 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT, &result);
Martin Radev0d671c92017-08-10 16:41:52 +0300465 return result;
466 }
467};
468
Martin Radev3c25ad02017-08-22 17:36:53 +0300469class MultiviewProgramGenerationTest : public MultiviewRenderTest
Martin Radev41ac68e2017-06-06 12:16:58 +0300470{
471 protected:
472 MultiviewProgramGenerationTest() {}
473};
474
Martin Radev3c25ad02017-08-22 17:36:53 +0300475class MultiviewRenderPrimitiveTest : public MultiviewRenderTest
Martin Radev61bd9992017-08-11 13:10:55 +0300476{
477 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300478 MultiviewRenderPrimitiveTest() {}
Martin Radev61bd9992017-08-11 13:10:55 +0300479
480 void setupGeometry(const std::vector<Vector2> &vertexData)
481 {
Martin Radev61bd9992017-08-11 13:10:55 +0300482 glBindBuffer(GL_ARRAY_BUFFER, mVBO);
483 glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vector2), vertexData.data(),
484 GL_STATIC_DRAW);
485 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500486 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +0300487 }
488
Martin Radev67a8a012017-09-08 13:03:52 +0300489 void checkGreenChannel(const GLubyte expectedGreenChannelData[])
Martin Radev61bd9992017-08-11 13:10:55 +0300490 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300491 for (int view = 0; view < mNumViews; ++view)
Martin Radev61bd9992017-08-11 13:10:55 +0300492 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300493 for (int w = 0; w < mViewWidth; ++w)
Martin Radev61bd9992017-08-11 13:10:55 +0300494 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300495 for (int h = 0; h < mViewHeight; ++h)
496 {
497 size_t flatIndex =
498 static_cast<size_t>(view * mViewWidth * mViewHeight + mViewWidth * h + w);
Martin Radev67a8a012017-09-08 13:03:52 +0300499 EXPECT_EQ(GLColor(0, expectedGreenChannelData[flatIndex], 0, 255),
Martin Radev3c25ad02017-08-22 17:36:53 +0300500 GetViewColor(w, h, view));
501 }
Martin Radev61bd9992017-08-11 13:10:55 +0300502 }
503 }
504 }
Martin Radev61bd9992017-08-11 13:10:55 +0300505 GLBuffer mVBO;
506};
507
Martin Radev3c25ad02017-08-22 17:36:53 +0300508class MultiviewSideBySideRenderTest : public MultiviewRenderTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300509 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev3c25ad02017-08-22 17:36:53 +0300510{
511 protected:
512 MultiviewSideBySideRenderTest()
513 : MultiviewRenderTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
514 {
515 }
516 void SetUp() override { MultiviewRenderTestBase::RenderTestSetUp(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300517 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
518 {
519 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
520 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300521};
522
Martin Radev72b4e1e2017-08-31 15:42:56 +0300523class MultiviewLayeredRenderTest : public MultiviewRenderTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300524 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev72b4e1e2017-08-31 15:42:56 +0300525{
526 protected:
527 MultiviewLayeredRenderTest()
528 : MultiviewRenderTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE)
529 {
530 }
531 void SetUp() override { MultiviewRenderTestBase::RenderTestSetUp(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300532 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
533 {
534 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
535 }
Martin Radev72b4e1e2017-08-31 15:42:56 +0300536};
537
Martin Radev14a26ae2017-07-24 15:56:29 +0300538// The test verifies that glDraw*Indirect:
539// 1) generates an INVALID_OPERATION error if the number of views in the draw framebuffer is greater
540// than 1.
541// 2) does not generate any error if the draw framebuffer has exactly 1 view.
Martin Radev7cf61662017-07-26 17:10:53 +0300542TEST_P(MultiviewDrawValidationTest, IndirectDraw)
Martin Radev14a26ae2017-07-24 15:56:29 +0300543{
544 if (!requestMultiviewExtension())
545 {
546 return;
547 }
548
Martin Radev14a26ae2017-07-24 15:56:29 +0300549 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Martin Radev14a26ae2017-07-24 15:56:29 +0300550
551 const std::string fsSource =
552 "#version 300 es\n"
553 "#extension GL_OVR_multiview : require\n"
554 "precision mediump float;\n"
555 "void main()\n"
556 "{}\n";
557
Martin Radev14a26ae2017-07-24 15:56:29 +0300558 GLBuffer commandBuffer;
559 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, commandBuffer);
560 const GLuint commandData[] = {1u, 1u, 0u, 0u, 0u};
561 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(GLuint) * 5u, &commandData[0], GL_STATIC_DRAW);
562 ASSERT_GL_NO_ERROR();
563
Martin Radev14a26ae2017-07-24 15:56:29 +0300564 // Check for a GL_INVALID_OPERATION error with the framebuffer having 2 views.
565 {
566 const std::string &vsSource =
567 "#version 300 es\n"
568 "#extension GL_OVR_multiview : require\n"
569 "layout(num_views = 2) in;\n"
570 "void main()\n"
571 "{}\n";
572 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
573 glUseProgram(program);
574
Martin Radev7cf61662017-07-26 17:10:53 +0300575 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
576 0, 2, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300577
578 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
579 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
580
581 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
582 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
583 }
584
585 // Check that no errors are generated if the number of views is 1.
586 {
587 const std::string &vsSource =
588 "#version 300 es\n"
589 "#extension GL_OVR_multiview : require\n"
590 "layout(num_views = 1) in;\n"
591 "void main()\n"
592 "{}\n";
593 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
594 glUseProgram(program);
595
Martin Radev7cf61662017-07-26 17:10:53 +0300596 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
597 0, 1, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300598
599 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
600 EXPECT_GL_NO_ERROR();
601
602 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
603 EXPECT_GL_NO_ERROR();
604 }
605}
606
Martin Radev7cf61662017-07-26 17:10:53 +0300607// The test verifies that glDraw*:
608// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and
609// program differs.
610// 2) does not generate any error if the number of views is the same.
Martin Radev7cf61662017-07-26 17:10:53 +0300611TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
612{
613 if (!requestMultiviewExtension())
614 {
615 return;
616 }
617
618 const GLint viewportOffsets[4] = {0, 0, 2, 0};
619
620 const std::string &vsSource =
621 "#version 300 es\n"
622 "#extension GL_OVR_multiview : require\n"
623 "layout(num_views = 2) in;\n"
624 "void main()\n"
625 "{}\n";
626 const std::string &fsSource =
627 "#version 300 es\n"
628 "#extension GL_OVR_multiview : require\n"
629 "precision mediump float;\n"
630 "void main()\n"
631 "{}\n";
632 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
633 glUseProgram(program);
634
635 // Check for a GL_INVALID_OPERATION error with the framebuffer and program having different
636 // number of views.
637 {
638 // The framebuffer has only 1 view.
639 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
640 0, 1, &viewportOffsets[0]);
641
642 glDrawArrays(GL_TRIANGLES, 0, 3);
643 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
644
645 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
646 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
647 }
648
649 // Check that no errors are generated if the number of views in both program and draw
650 // framebuffer matches.
651 {
652 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
653 0, 2, &viewportOffsets[0]);
654
655 glDrawArrays(GL_TRIANGLES, 0, 3);
656 EXPECT_GL_NO_ERROR();
657
658 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
659 EXPECT_GL_NO_ERROR();
660 }
Martin Radevda8e2572017-09-12 17:21:16 +0300661}
Martin Radev7cf61662017-07-26 17:10:53 +0300662
Martin Radevda8e2572017-09-12 17:21:16 +0300663// The test verifies that glDraw* generates an INVALID_OPERATION error if the program does not use
664// the multiview extension, but the active draw framebuffer has more than one view.
665TEST_P(MultiviewDrawValidationTest, NumViewsMismatchForNonMultiviewProgram)
666{
667 if (!requestMultiviewExtension())
Martin Radev7cf61662017-07-26 17:10:53 +0300668 {
Martin Radevda8e2572017-09-12 17:21:16 +0300669 return;
Martin Radev7cf61662017-07-26 17:10:53 +0300670 }
Martin Radevda8e2572017-09-12 17:21:16 +0300671
672 const std::string &vsSourceNoMultiview =
673 "#version 300 es\n"
674 "void main()\n"
675 "{}\n";
676 const std::string &fsSourceNoMultiview =
677 "#version 300 es\n"
678 "precision mediump float;\n"
679 "void main()\n"
680 "{}\n";
681 ANGLE_GL_PROGRAM(programNoMultiview, vsSourceNoMultiview, fsSourceNoMultiview);
682 glUseProgram(programNoMultiview);
683
684 const GLint viewportOffsets[4] = {0, 0, 2, 0};
685 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d, 0, 2,
686 &viewportOffsets[0]);
687
688 glDrawArrays(GL_TRIANGLES, 0, 3);
689 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
690
691 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
692 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radev7cf61662017-07-26 17:10:53 +0300693}
694
Martin Radev7e69f762017-07-27 14:54:13 +0300695// The test verifies that glDraw*:
696// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
697// greater than 1 and there is an active transform feedback object.
698// 2) does not generate any error if the number of views in the draw framebuffer is 1.
699TEST_P(MultiviewDrawValidationTest, ActiveTransformFeedback)
700{
701 if (!requestMultiviewExtension())
702 {
703 return;
704 }
705
706 const GLint viewportOffsets[4] = {0, 0, 2, 0};
707
708 const std::string &vsSource =
Olli Etuaho3755c482017-10-13 15:40:26 +0300709 R"(#version 300 es
710 out float tfVarying;
711 void main()
712 {
713 tfVarying = 1.0;
714 })";
Martin Radev7e69f762017-07-27 14:54:13 +0300715 const std::string &fsSource =
Olli Etuaho3755c482017-10-13 15:40:26 +0300716 R"(#version 300 es
717 precision mediump float;
718 void main()
719 {})";
720 std::vector<std::string> tfVaryings;
721 tfVaryings.push_back(std::string("tfVarying"));
722 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, vsSource, fsSource, tfVaryings,
723 GL_SEPARATE_ATTRIBS);
Martin Radev7e69f762017-07-27 14:54:13 +0300724 glUseProgram(program);
725
726 GLBuffer tbo;
727 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);
728 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 4u, nullptr, GL_STATIC_DRAW);
729
730 GLTransformFeedback transformFeedback;
731 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
Olli Etuaho3755c482017-10-13 15:40:26 +0300732
733 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
734
Martin Radev7e69f762017-07-27 14:54:13 +0300735 glBeginTransformFeedback(GL_TRIANGLES);
736 ASSERT_GL_NO_ERROR();
737
738 // Check that drawArrays generates an error when there is an active transform feedback object
739 // and the number of views in the draw framebuffer is greater than 1.
740 {
741 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
742 0, 2, &viewportOffsets[0]);
743 glDrawArrays(GL_TRIANGLES, 0, 3);
744 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
745 }
746
747 // Check that drawArrays does not generate an error when the number of views in the draw
748 // framebuffer is 1.
749 {
750 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
751 0, 1, &viewportOffsets[0]);
752 glDrawArrays(GL_TRIANGLES, 0, 3);
753 EXPECT_GL_NO_ERROR();
754 }
755
756 glEndTransformFeedback();
757}
758
Martin Radevffe754b2017-07-31 10:38:07 +0300759// The test verifies that glDraw*:
760// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
761// greater than 1 and there is an active query for target GL_TIME_ELAPSED_EXT.
762// 2) does not generate any error if the number of views in the draw framebuffer is 1.
763TEST_P(MultiviewDrawValidationTest, ActiveTimeElapsedQuery)
764{
Yunchao He9550c602018-02-13 14:47:05 +0800765 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevffe754b2017-07-31 10:38:07 +0300766
Olli Etuaho94c91a92018-07-19 15:10:24 +0300767 if (extensionRequestable("GL_EXT_disjoint_timer_query"))
768 {
769 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
770 }
771
Yunchao He9550c602018-02-13 14:47:05 +0800772 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_disjoint_timer_query"));
Martin Radevffe754b2017-07-31 10:38:07 +0300773
774 const GLint viewportOffsets[4] = {0, 0, 2, 0};
775 const std::string &vsSource =
776 "#version 300 es\n"
777 "void main()\n"
778 "{}\n";
779 const std::string &fsSource =
780 "#version 300 es\n"
781 "precision mediump float;\n"
782 "void main()\n"
783 "{}\n";
784 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
785 glUseProgram(program);
786
787 GLuint query = 0u;
788 glGenQueriesEXT(1, &query);
789 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
790
791 // Check first case.
792 {
793 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
794 0, 2, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300795 glClear(GL_COLOR_BUFFER_BIT);
796 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radevffe754b2017-07-31 10:38:07 +0300797 glDrawArrays(GL_TRIANGLES, 0, 3);
798 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
799 }
800
801 // Check second case.
802 {
803 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTex2d,
804 0, 1, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300805 glClear(GL_COLOR_BUFFER_BIT);
806 EXPECT_GL_NO_ERROR();
Martin Radevffe754b2017-07-31 10:38:07 +0300807 glDrawArrays(GL_TRIANGLES, 0, 3);
808 EXPECT_GL_NO_ERROR();
809 }
810
811 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
812 glDeleteQueries(1, &query);
813}
814
Martin Radev8f276e22017-05-30 12:05:52 +0300815// The test checks that glDrawArrays can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300816TEST_P(MultiviewRenderDualViewTest, DrawArrays)
Martin Radev8f276e22017-05-30 12:05:52 +0300817{
818 if (!requestMultiviewExtension())
819 {
820 return;
821 }
822 drawQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
823 ASSERT_GL_NO_ERROR();
824
825 checkOutput();
826}
827
828// The test checks that glDrawElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300829TEST_P(MultiviewRenderDualViewTest, DrawElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300830{
831 if (!requestMultiviewExtension())
832 {
833 return;
834 }
835 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
836 ASSERT_GL_NO_ERROR();
837
838 checkOutput();
839}
840
841// The test checks that glDrawRangeElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300842TEST_P(MultiviewRenderDualViewTest, DrawRangeElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300843{
844 if (!requestMultiviewExtension())
845 {
846 return;
847 }
848 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true, true);
849 ASSERT_GL_NO_ERROR();
850
851 checkOutput();
852}
853
854// The test checks that glDrawArrays can be used to render into four views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300855TEST_P(MultiviewRenderTest, DrawArraysFourViews)
Martin Radev8f276e22017-05-30 12:05:52 +0300856{
857 if (!requestMultiviewExtension())
858 {
859 return;
860 }
861
862 const std::string vsSource =
863 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300864 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300865 "layout(num_views = 4) in;\n"
866 "in vec4 vPosition;\n"
867 "void main()\n"
868 "{\n"
869 " if (gl_ViewID_OVR == 0u) {\n"
870 " gl_Position.x = vPosition.x*0.25 - 0.75;\n"
871 " } else if (gl_ViewID_OVR == 1u) {\n"
872 " gl_Position.x = vPosition.x*0.25 - 0.25;\n"
873 " } else if (gl_ViewID_OVR == 2u) {\n"
874 " gl_Position.x = vPosition.x*0.25 + 0.25;\n"
875 " } else {\n"
876 " gl_Position.x = vPosition.x*0.25 + 0.75;\n"
877 " }"
878 " gl_Position.yzw = vPosition.yzw;\n"
879 "}\n";
880
881 const std::string fsSource =
882 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300883 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300884 "precision mediump float;\n"
885 "out vec4 col;\n"
886 "void main()\n"
887 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300888 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300889 "}\n";
890
Martin Radev3c25ad02017-08-22 17:36:53 +0300891 createFBO(4, 1, 4);
Martin Radev8f276e22017-05-30 12:05:52 +0300892 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev8f276e22017-05-30 12:05:52 +0300893
894 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
895 ASSERT_GL_NO_ERROR();
896
897 for (int i = 0; i < 4; ++i)
898 {
899 for (int j = 0; j < 4; ++j)
900 {
Martin Radev8f276e22017-05-30 12:05:52 +0300901 if (i == j)
902 {
Martin Radev67a8a012017-09-08 13:03:52 +0300903 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300904 }
905 else
906 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300907 EXPECT_EQ(GLColor::black, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300908 }
909 }
910 }
911 EXPECT_GL_NO_ERROR();
912}
913
914// The test checks that glDrawArraysInstanced can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300915TEST_P(MultiviewRenderTest, DrawArraysInstanced)
Martin Radev8f276e22017-05-30 12:05:52 +0300916{
917 if (!requestMultiviewExtension())
918 {
919 return;
920 }
921
922 const std::string vsSource =
923 "#version 300 es\n"
924 "#extension GL_OVR_multiview : require\n"
925 "layout(num_views = 2) in;\n"
926 "in vec4 vPosition;\n"
927 "void main()\n"
928 "{\n"
929 " vec4 p = vPosition;\n"
930 " if (gl_InstanceID == 1){\n"
931 " p.y = .5*p.y + .5;\n"
932 " } else {\n"
933 " p.y = p.y*.5;\n"
934 " }\n"
935 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x*0.5 + 0.5 : p.x*0.5);\n"
936 " gl_Position.yzw = p.yzw;\n"
937 "}\n";
938
939 const std::string fsSource =
940 "#version 300 es\n"
941 "#extension GL_OVR_multiview : require\n"
942 "precision mediump float;\n"
943 "out vec4 col;\n"
944 "void main()\n"
945 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300946 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300947 "}\n";
948
Martin Radev3c25ad02017-08-22 17:36:53 +0300949 const int kViewWidth = 2;
950 const int kViewHeight = 2;
951 const int kNumViews = 2;
952 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev8f276e22017-05-30 12:05:52 +0300953 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev8f276e22017-05-30 12:05:52 +0300954
Martin Radev67a8a012017-09-08 13:03:52 +0300955 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 2u);
Martin Radev8f276e22017-05-30 12:05:52 +0300956 ASSERT_GL_NO_ERROR();
957
Martin Radev67a8a012017-09-08 13:03:52 +0300958 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {{{0, 255}, {0, 255}},
959 {{255, 0}, {255, 0}}};
Martin Radev3c25ad02017-08-22 17:36:53 +0300960
961 for (int view = 0; view < 2; ++view)
Martin Radev8f276e22017-05-30 12:05:52 +0300962 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300963 for (int y = 0; y < 2; ++y)
Martin Radev8f276e22017-05-30 12:05:52 +0300964 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300965 for (int x = 0; x < 2; ++x)
966 {
Martin Radev67a8a012017-09-08 13:03:52 +0300967 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][y][x], 0, 255),
Martin Radev3c25ad02017-08-22 17:36:53 +0300968 GetViewColor(x, y, view));
969 }
Martin Radev8f276e22017-05-30 12:05:52 +0300970 }
971 }
972}
973
Martin Radev553590a2017-07-31 16:40:39 +0300974// The test verifies that the attribute divisor is correctly adjusted when drawing with a multi-view
975// program. The test draws 4 instances of a quad each of which covers a single pixel. The x and y
976// offset of each quad are passed as separate attributes which are indexed based on the
977// corresponding attribute divisors. A divisor of 1 is used for the y offset to have all quads
978// drawn vertically next to each other. A divisor of 3 is used for the x offset to have the last
979// quad offsetted by one pixel to the right. Note that the number of views is divisible by 1, but
980// not by 3.
Martin Radev3c25ad02017-08-22 17:36:53 +0300981TEST_P(MultiviewRenderTest, AttribDivisor)
Martin Radev553590a2017-07-31 16:40:39 +0300982{
983 if (!requestMultiviewExtension())
984 {
985 return;
986 }
987
988 const std::string &vsSource =
989 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300990 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +0300991 "layout(num_views = 2) in;\n"
992 "in vec3 vPosition;\n"
993 "in float offsetX;\n"
994 "in float offsetY;\n"
995 "void main()\n"
996 "{\n"
997 " vec4 p = vec4(vPosition, 1.);\n"
Martin Radev0abb7a22017-08-28 15:34:45 +0300998 " p.xy = p.xy * 0.25 - vec2(0.75) + vec2(offsetX, offsetY);\n"
Martin Radev553590a2017-07-31 16:40:39 +0300999 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x : p.x + 1.0);\n"
1000 " gl_Position.yzw = p.yzw;\n"
1001 "}\n";
1002
1003 const std::string &fsSource =
1004 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001005 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001006 "precision mediump float;\n"
1007 "out vec4 col;\n"
1008 "void main()\n"
1009 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001010 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001011 "}\n";
Martin Radev3c25ad02017-08-22 17:36:53 +03001012
1013 const int kViewWidth = 4;
1014 const int kViewHeight = 4;
1015 const int kNumViews = 2;
1016 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev553590a2017-07-31 16:40:39 +03001017 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev553590a2017-07-31 16:40:39 +03001018
1019 GLBuffer xOffsetVBO;
1020 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1021 const GLfloat xOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.0f};
1022 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, xOffsetData, GL_STATIC_DRAW);
1023 GLint xOffsetLoc = glGetAttribLocation(program, "offsetX");
1024 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1025 glVertexAttribDivisor(xOffsetLoc, 3);
1026 glEnableVertexAttribArray(xOffsetLoc);
1027
1028 GLBuffer yOffsetVBO;
1029 glBindBuffer(GL_ARRAY_BUFFER, yOffsetVBO);
1030 const GLfloat yOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1031 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, yOffsetData, GL_STATIC_DRAW);
1032 GLint yOffsetLoc = glGetAttribLocation(program, "offsetY");
1033 glVertexAttribDivisor(yOffsetLoc, 1);
1034 glVertexAttribPointer(yOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1035 glEnableVertexAttribArray(yOffsetLoc);
1036
Martin Radev67a8a012017-09-08 13:03:52 +03001037 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev553590a2017-07-31 16:40:39 +03001038 ASSERT_GL_NO_ERROR();
1039
Martin Radev67a8a012017-09-08 13:03:52 +03001040 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001041 {{255, 0, 0, 0}, {255, 0, 0, 0}, {255, 0, 0, 0}, {0, 255, 0, 0}},
1042 {{0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 0, 255}}};
1043 for (int view = 0; view < 2; ++view)
Martin Radev553590a2017-07-31 16:40:39 +03001044 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001045 for (int row = 0; row < 4; ++row)
Martin Radev553590a2017-07-31 16:40:39 +03001046 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001047 for (int col = 0; col < 4; ++col)
1048 {
Martin Radev67a8a012017-09-08 13:03:52 +03001049 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][row][col], 0, 255),
Martin Radev3c25ad02017-08-22 17:36:53 +03001050 GetViewColor(col, row, view));
1051 }
Martin Radev553590a2017-07-31 16:40:39 +03001052 }
1053 }
1054}
1055
1056// Test that different sequences of vertexAttribDivisor, useProgram and bindVertexArray in a
1057// multi-view context propagate the correct divisor to the driver.
Martin Radev3c25ad02017-08-22 17:36:53 +03001058TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
Martin Radev553590a2017-07-31 16:40:39 +03001059{
1060 if (!requestMultiviewExtension())
1061 {
1062 return;
1063 }
1064
Martin Radev3c25ad02017-08-22 17:36:53 +03001065 createFBO(1, 1, 2);
Martin Radev553590a2017-07-31 16:40:39 +03001066
1067 // Create multiview program.
1068 const std::string &vs =
1069 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001070 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001071 "layout(num_views = 2) in;\n"
1072 "layout(location = 0) in vec2 vPosition;\n"
1073 "layout(location = 1) in float offsetX;\n"
1074 "void main()\n"
1075 "{\n"
1076 " vec4 p = vec4(vPosition, 0.0, 1.0);\n"
1077 " p.x += offsetX;\n"
1078 " gl_Position = p;\n"
1079 "}\n";
1080
1081 const std::string &fs =
1082 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001083 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001084 "precision mediump float;\n"
1085 "out vec4 col;\n"
1086 "void main()\n"
1087 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001088 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001089 "}\n";
1090
1091 ANGLE_GL_PROGRAM(program, vs, fs);
1092
1093 const std::string &dummyVS =
1094 "#version 300 es\n"
1095 "layout(location = 0) in vec2 vPosition;\n"
1096 "layout(location = 1) in float offsetX;\n"
1097 "void main()\n"
1098 "{\n"
1099 " gl_Position = vec4(vPosition, 0.0, 1.0);\n"
1100 "}\n";
1101
1102 const std::string &dummyFS =
1103 "#version 300 es\n"
1104 "precision mediump float;\n"
1105 "out vec4 col;\n"
1106 "void main()\n"
1107 "{\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001108 " col = vec4(0,0,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001109 "}\n";
1110
1111 ANGLE_GL_PROGRAM(dummyProgram, dummyVS, dummyFS);
1112
1113 GLBuffer xOffsetVBO;
1114 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1115 const GLfloat xOffsetData[12] = {0.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f,
1116 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f};
1117 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 12, xOffsetData, GL_STATIC_DRAW);
1118
1119 GLBuffer vertexVBO;
1120 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1121 Vector2 kQuadVertices[6] = {Vector2(-1.f, -1.f), Vector2(1.f, -1.f), Vector2(1.f, 1.f),
1122 Vector2(-1.f, -1.f), Vector2(1.f, 1.f), Vector2(-1.f, 1.f)};
1123 glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
1124
1125 GLVertexArray vao[2];
1126 for (size_t i = 0u; i < 2u; ++i)
1127 {
1128 glBindVertexArray(vao[i]);
1129
1130 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1131 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
1132 glEnableVertexAttribArray(0);
1133
1134 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1135 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
1136 glEnableVertexAttribArray(1);
1137 }
1138 ASSERT_GL_NO_ERROR();
1139
1140 glViewport(0, 0, 1, 1);
1141 glScissor(0, 0, 1, 1);
Martin Radeveef80e42017-08-11 14:44:57 +03001142 glEnable(GL_SCISSOR_TEST);
Martin Radev61bd9992017-08-11 13:10:55 +03001143 glClearColor(0, 0, 0, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001144
1145 // Clear the buffers, propagate divisor to the driver, bind the vao and keep it active.
1146 // It is necessary to call draw, so that the divisor is propagated and to guarantee that dirty
1147 // bits are cleared.
1148 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001149 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1150 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001151 glBindVertexArray(vao[0]);
1152 glVertexAttribDivisor(1, 0);
1153 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1154 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001155 ASSERT_GL_NO_ERROR();
1156
1157 // Check that vertexAttribDivisor uses the number of views to update the divisor.
Martin Radevda8e2572017-09-12 17:21:16 +03001158 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
1159 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001160 glUseProgram(program);
1161 glVertexAttribDivisor(1, 1);
1162 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev67a8a012017-09-08 13:03:52 +03001163 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1164 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001165
1166 // Clear the buffers and propagate divisor to the driver.
1167 // We keep the vao active and propagate the divisor to guarantee that there are no unresolved
1168 // dirty bits when useProgram is called.
1169 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001170 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1171 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001172 glVertexAttribDivisor(1, 1);
1173 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1174 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001175 ASSERT_GL_NO_ERROR();
1176
1177 // Check that useProgram uses the number of views to update the divisor.
Martin Radevda8e2572017-09-12 17:21:16 +03001178 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
1179 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001180 glUseProgram(program);
1181 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev67a8a012017-09-08 13:03:52 +03001182 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1183 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001184
1185 // We go through similar steps as before.
1186 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001187 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1188 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001189 glVertexAttribDivisor(1, 1);
1190 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1191 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001192 ASSERT_GL_NO_ERROR();
1193
1194 // Check that bindVertexArray uses the number of views to update the divisor.
1195 {
1196 // Call useProgram with vao[1] being active to guarantee that useProgram will adjust the
1197 // divisor for vao[1] only.
Martin Radevda8e2572017-09-12 17:21:16 +03001198 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
1199 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001200 glBindVertexArray(vao[1]);
1201 glUseProgram(program);
1202 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001203 glBindVertexArray(0);
1204 ASSERT_GL_NO_ERROR();
1205 }
1206 // Bind vao[0] after useProgram is called to ensure that bindVertexArray is the call which
1207 // adjusts the divisor.
Martin Radevda8e2572017-09-12 17:21:16 +03001208 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001209 glBindVertexArray(vao[0]);
1210 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev67a8a012017-09-08 13:03:52 +03001211 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1212 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001213}
1214
Martin Radev0d671c92017-08-10 16:41:52 +03001215// Test that no fragments pass the occlusion query for a multi-view vertex shader which always
1216// transforms geometry to be outside of the clip region.
Martin Radev3c25ad02017-08-22 17:36:53 +03001217TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryNothingVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001218{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001219 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1220 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001221
1222 const std::string vsSource =
1223 "#version 300 es\n"
1224 "#extension GL_OVR_multiview : require\n"
1225 "layout(num_views = 2) in;\n"
1226 "in vec3 vPosition;\n"
1227 "void main()\n"
1228 "{\n"
1229 " gl_Position.x = 2.0;\n"
1230 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1231 "}\n";
1232
1233 const std::string fsSource =
1234 "#version 300 es\n"
1235 "#extension GL_OVR_multiview : require\n"
1236 "precision mediump float;\n"
1237 "out vec4 col;\n"
1238 "void main()\n"
1239 "{\n"
1240 " col = vec4(1,0,0,0);\n"
1241 "}\n";
1242 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev3c25ad02017-08-22 17:36:53 +03001243 createFBO(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001244
1245 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1246 ASSERT_GL_NO_ERROR();
1247 EXPECT_GL_FALSE(result);
1248}
1249
1250// Test that there are fragments passing the occlusion query if only view 0 can produce
1251// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001252TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyLeftVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001253{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001254 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1255 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001256
1257 const std::string vsSource =
1258 "#version 300 es\n"
1259 "#extension GL_OVR_multiview : require\n"
1260 "layout(num_views = 2) in;\n"
1261 "in vec3 vPosition;\n"
1262 "void main()\n"
1263 "{\n"
1264 " gl_Position.x = gl_ViewID_OVR == 0u ? vPosition.x : 2.0;\n"
1265 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1266 "}\n";
1267
1268 const std::string fsSource =
1269 "#version 300 es\n"
1270 "#extension GL_OVR_multiview : require\n"
1271 "precision mediump float;\n"
1272 "out vec4 col;\n"
1273 "void main()\n"
1274 "{\n"
1275 " col = vec4(1,0,0,0);\n"
1276 "}\n";
1277 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev3c25ad02017-08-22 17:36:53 +03001278 createFBO(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001279
1280 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1281 ASSERT_GL_NO_ERROR();
1282 EXPECT_GL_TRUE(result);
1283}
1284
1285// Test that there are fragments passing the occlusion query if only view 1 can produce
1286// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001287TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyRightVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001288{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001289 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1290 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001291
1292 const std::string vsSource =
1293 "#version 300 es\n"
1294 "#extension GL_OVR_multiview : require\n"
1295 "layout(num_views = 2) in;\n"
1296 "in vec3 vPosition;\n"
1297 "void main()\n"
1298 "{\n"
1299 " gl_Position.x = gl_ViewID_OVR == 1u ? vPosition.x : 2.0;\n"
1300 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1301 "}\n";
1302
1303 const std::string fsSource =
1304 "#version 300 es\n"
1305 "#extension GL_OVR_multiview : require\n"
1306 "precision mediump float;\n"
1307 "out vec4 col;\n"
1308 "void main()\n"
1309 "{\n"
1310 " col = vec4(1,0,0,0);\n"
1311 "}\n";
1312 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev3c25ad02017-08-22 17:36:53 +03001313 createFBO(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001314
1315 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1316 ASSERT_GL_NO_ERROR();
1317 EXPECT_GL_TRUE(result);
1318}
1319
Martin Radev41ac68e2017-06-06 12:16:58 +03001320// Test that a simple multi-view program which doesn't use gl_ViewID_OVR in neither VS nor FS
1321// compiles and links without an error.
1322TEST_P(MultiviewProgramGenerationTest, SimpleProgram)
1323{
1324 if (!requestMultiviewExtension())
1325 {
1326 return;
1327 }
1328
1329 const std::string vsSource =
1330 "#version 300 es\n"
1331 "#extension GL_OVR_multiview : require\n"
1332 "layout(num_views = 2) in;\n"
1333 "void main()\n"
1334 "{\n"
1335 "}\n";
1336
1337 const std::string fsSource =
1338 "#version 300 es\n"
1339 "#extension GL_OVR_multiview : require\n"
1340 "precision mediump float;\n"
1341 "void main()\n"
1342 "{\n"
1343 "}\n";
1344
1345 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1346 glUseProgram(program);
1347
1348 EXPECT_GL_NO_ERROR();
1349}
1350
1351// Test that a simple multi-view program which uses gl_ViewID_OVR only in VS compiles and links
1352// without an error.
1353TEST_P(MultiviewProgramGenerationTest, UseViewIDInVertexShader)
1354{
1355 if (!requestMultiviewExtension())
1356 {
1357 return;
1358 }
1359
1360 const std::string vsSource =
1361 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001362 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001363 "layout(num_views = 2) in;\n"
1364 "void main()\n"
1365 "{\n"
1366 " if (gl_ViewID_OVR == 0u) {\n"
1367 " gl_Position = vec4(1,0,0,1);\n"
1368 " } else {\n"
1369 " gl_Position = vec4(-1,0,0,1);\n"
1370 " }\n"
1371 "}\n";
1372
1373 const std::string fsSource =
1374 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001375 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001376 "precision mediump float;\n"
1377 "void main()\n"
1378 "{\n"
1379 "}\n";
1380
1381 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1382 glUseProgram(program);
1383
1384 EXPECT_GL_NO_ERROR();
1385}
1386
1387// Test that a simple multi-view program which uses gl_ViewID_OVR only in FS compiles and links
1388// without an error.
1389TEST_P(MultiviewProgramGenerationTest, UseViewIDInFragmentShader)
1390{
1391 if (!requestMultiviewExtension())
1392 {
1393 return;
1394 }
1395
1396 const std::string vsSource =
1397 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001398 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001399 "layout(num_views = 2) in;\n"
1400 "void main()\n"
1401 "{\n"
1402 "}\n";
1403
1404 const std::string fsSource =
1405 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001406 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001407 "precision mediump float;\n"
1408 "out vec4 col;\n"
1409 "void main()\n"
1410 "{\n"
1411 " if (gl_ViewID_OVR == 0u) {\n"
1412 " col = vec4(1,0,0,1);\n"
1413 " } else {\n"
1414 " col = vec4(-1,0,0,1);\n"
1415 " }\n"
1416 "}\n";
1417
1418 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1419 glUseProgram(program);
1420
1421 EXPECT_GL_NO_ERROR();
1422}
1423
Martin Radev61bd9992017-08-11 13:10:55 +03001424// The test checks that GL_POINTS is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001425TEST_P(MultiviewRenderPrimitiveTest, Points)
Martin Radev61bd9992017-08-11 13:10:55 +03001426{
1427 if (!requestMultiviewExtension())
1428 {
1429 return;
1430 }
1431
Geoff Lang25858162017-11-06 11:25:58 -05001432 // Test failing on P400 graphics card (anglebug.com/2228)
1433 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1434
Martin Radev61bd9992017-08-11 13:10:55 +03001435 const std::string vsSource =
1436 "#version 300 es\n"
1437 "#extension GL_OVR_multiview : require\n"
1438 "layout(num_views = 2) in;\n"
1439 "layout(location=0) in vec2 vPosition;\n"
1440 "void main()\n"
1441 "{\n"
1442 " gl_PointSize = 1.0;\n"
1443 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1444 "}\n";
1445
1446 const std::string fsSource =
1447 "#version 300 es\n"
1448 "#extension GL_OVR_multiview : require\n"
1449 "precision mediump float;\n"
1450 "out vec4 col;\n"
1451 "void main()\n"
1452 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001453 " col = vec4(0,1,0,1);\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001454 "}\n";
1455 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1456 glUseProgram(program);
1457
Martin Radev3c25ad02017-08-22 17:36:53 +03001458 const int kViewWidth = 4;
1459 const int kViewHeight = 2;
1460 const int kNumViews = 2;
1461 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001462
1463 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 1)};
1464 std::vector<Vector2> vertexDataInClipSpace =
1465 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1466 setupGeometry(vertexDataInClipSpace);
1467
1468 glDrawArrays(GL_POINTS, 0, 2);
1469
Martin Radev67a8a012017-09-08 13:03:52 +03001470 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001471 {{255, 0, 0, 0}, {0, 0, 0, 255}}, {{255, 0, 0, 0}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001472 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001473}
1474
1475// The test checks that GL_LINES is correctly rendered.
1476// The behavior of this test is not guaranteed by the spec:
1477// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1478// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1479// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1480// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001481TEST_P(MultiviewRenderPrimitiveTest, Lines)
Martin Radev61bd9992017-08-11 13:10:55 +03001482{
1483 if (!requestMultiviewExtension())
1484 {
1485 return;
1486 }
1487
Martin Radevced5c862017-08-17 16:05:29 +03001488 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001489 ASSERT_NE(program, 0u);
1490 glUseProgram(program);
1491 ASSERT_GL_NO_ERROR();
1492
Martin Radev3c25ad02017-08-22 17:36:53 +03001493 const int kViewWidth = 4;
1494 const int kViewHeight = 2;
1495 const int kNumViews = 2;
1496 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001497
1498 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(4, 0)};
1499 std::vector<Vector2> vertexDataInClipSpace =
1500 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1501 setupGeometry(vertexDataInClipSpace);
1502
1503 glDrawArrays(GL_LINES, 0, 2);
1504
Martin Radev67a8a012017-09-08 13:03:52 +03001505 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001506 {{255, 255, 255, 255}, {0, 0, 0, 0}}, {{255, 255, 255, 255}, {0, 0, 0, 0}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001507 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001508
1509 glDeleteProgram(program);
1510}
1511
1512// The test checks that GL_LINE_STRIP is correctly rendered.
1513// The behavior of this test is not guaranteed by the spec:
1514// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1515// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1516// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1517// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001518TEST_P(MultiviewRenderPrimitiveTest, LineStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001519{
1520 if (!requestMultiviewExtension())
1521 {
1522 return;
1523 }
1524
Martin Radevced5c862017-08-17 16:05:29 +03001525 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001526 ASSERT_NE(program, 0u);
1527 glUseProgram(program);
1528 ASSERT_GL_NO_ERROR();
1529
Martin Radev3c25ad02017-08-22 17:36:53 +03001530 const int kViewWidth = 4;
1531 const int kViewHeight = 2;
1532 const int kNumViews = 2;
1533 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001534
1535 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 2)};
1536 std::vector<Vector2> vertexDataInClipSpace =
1537 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1538 setupGeometry(vertexDataInClipSpace);
1539
1540 glDrawArrays(GL_LINE_STRIP, 0, 3);
1541
Martin Radev67a8a012017-09-08 13:03:52 +03001542 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001543 {{255, 255, 255, 255}, {0, 0, 0, 255}}, {{255, 255, 255, 255}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001544 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001545
1546 glDeleteProgram(program);
1547}
1548
1549// The test checks that GL_LINE_LOOP is correctly rendered.
1550// The behavior of this test is not guaranteed by the spec:
1551// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1552// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1553// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1554// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001555TEST_P(MultiviewRenderPrimitiveTest, LineLoop)
Martin Radev61bd9992017-08-11 13:10:55 +03001556{
1557 if (!requestMultiviewExtension())
1558 {
1559 return;
1560 }
1561
Martin Radevced5c862017-08-17 16:05:29 +03001562 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001563 ASSERT_NE(program, 0u);
1564 glUseProgram(program);
1565 ASSERT_GL_NO_ERROR();
1566
Martin Radev3c25ad02017-08-22 17:36:53 +03001567 const int kViewWidth = 4;
1568 const int kViewHeight = 4;
1569 const int kNumViews = 2;
1570 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001571
1572 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 3),
1573 Vector2I(0, 3)};
1574 std::vector<Vector2> vertexDataInClipSpace =
1575 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 4);
1576 setupGeometry(vertexDataInClipSpace);
1577
1578 glDrawArrays(GL_LINE_LOOP, 0, 4);
1579
Martin Radev67a8a012017-09-08 13:03:52 +03001580 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001581 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}},
1582 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001583 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001584
1585 glDeleteProgram(program);
1586}
1587
1588// The test checks that GL_TRIANGLE_STRIP is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001589TEST_P(MultiviewRenderPrimitiveTest, TriangleStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001590{
1591 if (!requestMultiviewExtension())
1592 {
1593 return;
1594 }
1595
Martin Radevced5c862017-08-17 16:05:29 +03001596 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001597 ASSERT_NE(program, 0u);
1598 glUseProgram(program);
1599 ASSERT_GL_NO_ERROR();
1600
1601 std::vector<Vector2> vertexDataInClipSpace = {Vector2(1.0f, 0.0f), Vector2(0.0f, 0.0f),
1602 Vector2(1.0f, 1.0f), Vector2(0.0f, 1.0f)};
1603 setupGeometry(vertexDataInClipSpace);
1604
Martin Radev3c25ad02017-08-22 17:36:53 +03001605 const int kViewWidth = 2;
1606 const int kViewHeight = 2;
1607 const int kNumViews = 2;
1608 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001609
1610 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1611
Martin Radev67a8a012017-09-08 13:03:52 +03001612 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1613 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1614 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001615
1616 glDeleteProgram(program);
1617}
1618
1619// The test checks that GL_TRIANGLE_FAN is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001620TEST_P(MultiviewRenderPrimitiveTest, TriangleFan)
Martin Radev61bd9992017-08-11 13:10:55 +03001621{
1622 if (!requestMultiviewExtension())
1623 {
1624 return;
1625 }
1626
Martin Radevced5c862017-08-17 16:05:29 +03001627 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001628 ASSERT_NE(program, 0u);
1629 glUseProgram(program);
1630 ASSERT_GL_NO_ERROR();
1631
1632 std::vector<Vector2> vertexDataInClipSpace = {Vector2(0.0f, 0.0f), Vector2(0.0f, 1.0f),
1633 Vector2(1.0f, 1.0f), Vector2(1.0f, 0.0f)};
1634 setupGeometry(vertexDataInClipSpace);
1635
Martin Radev3c25ad02017-08-22 17:36:53 +03001636 const int kViewWidth = 2;
1637 const int kViewHeight = 2;
1638 const int kNumViews = 2;
1639 createFBO(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001640
1641 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1642
Martin Radev67a8a012017-09-08 13:03:52 +03001643 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1644 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1645 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001646
1647 glDeleteProgram(program);
1648}
1649
1650// Test that rendering enlarged points and lines does not leak fragments outside of the views'
1651// bounds. The test does not rely on the actual line width being greater than 1.0.
Martin Radev3c25ad02017-08-22 17:36:53 +03001652TEST_P(MultiviewSideBySideRenderTest, NoLeakingFragments)
Martin Radev61bd9992017-08-11 13:10:55 +03001653{
Luc Ferronaf7dc012018-06-26 07:56:49 -04001654 // TODO(oetuaho): Diagnose and fix http://anglebug.com/2687
1655 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
1656
Martin Radev61bd9992017-08-11 13:10:55 +03001657 if (!requestMultiviewExtension())
1658 {
1659 return;
1660 }
1661
Martin Radev3c25ad02017-08-22 17:36:53 +03001662 createFBO(2, 1, 2);
Martin Radev61bd9992017-08-11 13:10:55 +03001663
1664 GLint viewportOffsets[4] = {1, 0, 3, 0};
1665 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1666 mColorTexture, 0, 2, &viewportOffsets[0]);
1667 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
1668 mDepthTexture, 0, 2, &viewportOffsets[0]);
1669
1670 glViewport(0, 0, 1, 1);
1671 glScissor(0, 0, 1, 1);
1672 glEnable(GL_SCISSOR_TEST);
1673
1674 const std::string vsSource =
1675 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001676 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001677 "layout(num_views = 2) in;\n"
1678 "layout(location=0) in vec2 vPosition;\n"
1679 "void main()\n"
1680 "{\n"
1681 " gl_PointSize = 10.0;\n"
1682 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1683 "}\n";
1684
1685 const std::string fsSource =
1686 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001687 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001688 "precision mediump float;\n"
1689 "out vec4 col;\n"
1690 "void main()\n"
1691 "{\n"
1692 " if (gl_ViewID_OVR == 0u) {\n"
1693 " col = vec4(1,0,0,1);\n"
1694 " } else {\n"
1695 " col = vec4(0,1,0,1);\n"
1696 " }\n"
1697 "}\n";
1698 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1699 glUseProgram(program);
1700
1701 const std::vector<Vector2I> &windowCoordinates = {Vector2I(0, 0), Vector2I(2, 0)};
1702 const std::vector<Vector2> &vertexDataInClipSpace =
1703 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 1, 1);
Martin Radev3c25ad02017-08-22 17:36:53 +03001704
1705 GLBuffer vbo;
1706 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1707 glBufferData(GL_ARRAY_BUFFER, vertexDataInClipSpace.size() * sizeof(Vector2),
1708 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
1709 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -05001710 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +03001711
1712 // Test rendering points.
1713 {
1714 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1715 glDrawArrays(GL_POINTS, 0, 2);
1716 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1717 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
1718 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::black);
1719 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1720 }
1721
1722 // Test rendering lines.
1723 {
1724 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1725 glLineWidth(10.f);
1726 glDrawArrays(GL_LINES, 0, 2);
1727 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1728 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
1729 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::black);
1730 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1731 }
1732}
1733
Martin Radev0abb7a22017-08-28 15:34:45 +03001734// Verify that re-linking a program adjusts the attribute divisor.
1735// The test uses instacing to draw for each view a strips of two red quads and two blue quads next
1736// to each other. The quads' position and color depend on the corresponding attribute divisors.
1737TEST_P(MultiviewRenderTest, ProgramRelinkUpdatesAttribDivisor)
1738{
1739 if (!requestMultiviewExtension())
1740 {
1741 return;
1742 }
1743
1744 const int kViewWidth = 4;
1745 const int kViewHeight = 1;
1746 const int kNumViews = 2;
1747
1748 const std::string &fsSource =
1749 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001750 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001751 "precision mediump float;\n"
1752 "in vec4 oColor;\n"
1753 "out vec4 col;\n"
1754 "void main()\n"
1755 "{\n"
1756 " col = oColor;\n"
1757 "}\n";
1758
1759 auto generateVertexShaderSource = [](int numViews) -> std::string {
1760 std::string source =
1761 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001762 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001763 "layout(num_views = " +
1764 ToString(numViews) +
1765 ") in;\n"
1766 "in vec3 vPosition;\n"
1767 "in float vOffsetX;\n"
1768 "in vec4 vColor;\n"
1769 "out vec4 oColor;\n"
1770 "void main()\n"
1771 "{\n"
1772 " vec4 p = vec4(vPosition, 1.);\n"
1773 " p.x = p.x * 0.25 - 0.75 + vOffsetX;\n"
1774 " oColor = vColor;\n"
1775 " gl_Position = p;\n"
1776 "}\n";
1777 return source;
1778 };
1779
1780 std::string vsSource = generateVertexShaderSource(kNumViews);
1781 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
1782 glUseProgram(program);
1783
1784 GLint positionLoc;
1785 GLBuffer xOffsetVBO;
1786 GLint xOffsetLoc;
1787 GLBuffer colorVBO;
1788 GLint colorLoc;
1789
1790 {
1791 // Initialize buffers and setup attributes.
1792 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1793 const GLfloat kXOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1794 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, kXOffsetData, GL_STATIC_DRAW);
1795 xOffsetLoc = glGetAttribLocation(program, "vOffsetX");
1796 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1797 glVertexAttribDivisor(xOffsetLoc, 1);
1798 glEnableVertexAttribArray(xOffsetLoc);
1799
1800 glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
1801 const GLColor kColors[2] = {GLColor::red, GLColor::blue};
1802 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 2, kColors, GL_STATIC_DRAW);
1803 colorLoc = glGetAttribLocation(program, "vColor");
1804 glVertexAttribDivisor(colorLoc, 2);
1805 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1806 glEnableVertexAttribArray(colorLoc);
1807
1808 positionLoc = glGetAttribLocation(program, "vPosition");
1809 }
1810
1811 {
1812 createFBO(kViewWidth, kViewHeight, kNumViews);
1813
Martin Radev67a8a012017-09-08 13:03:52 +03001814 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001815 ASSERT_GL_NO_ERROR();
1816
1817 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
1818 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, 0));
1819 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, 0));
1820 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, 0));
1821 }
1822
1823 {
1824 const int kNewNumViews = 3;
1825 vsSource = generateVertexShaderSource(kNewNumViews);
1826 createFBO(kViewWidth, kViewHeight, kNewNumViews);
1827
1828 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
1829 ASSERT_NE(0u, vs);
1830 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
1831 ASSERT_NE(0u, fs);
1832
1833 GLint numAttachedShaders = 0;
1834 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
1835
1836 GLuint attachedShaders[2] = {0u};
1837 glGetAttachedShaders(program, numAttachedShaders, nullptr, attachedShaders);
1838 for (int i = 0; i < 2; ++i)
1839 {
1840 glDetachShader(program, attachedShaders[i]);
1841 }
1842
1843 glAttachShader(program, vs);
1844 glDeleteShader(vs);
1845
1846 glAttachShader(program, fs);
1847 glDeleteShader(fs);
1848
1849 glBindAttribLocation(program, positionLoc, "vPosition");
1850 glBindAttribLocation(program, xOffsetLoc, "vOffsetX");
1851 glBindAttribLocation(program, colorLoc, "vColor");
1852
1853 glLinkProgram(program);
1854
Martin Radev67a8a012017-09-08 13:03:52 +03001855 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001856 ASSERT_GL_NO_ERROR();
1857
1858 for (int i = 0; i < kNewNumViews; ++i)
1859 {
1860 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, i));
1861 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, i));
1862 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, i));
1863 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, i));
1864 }
1865 }
1866}
1867
Martin Radevced5c862017-08-17 16:05:29 +03001868// Test that useProgram applies the number of views in computing the final value of the attribute
1869// divisor.
1870TEST_P(MultiviewRenderTest, DivisorUpdatedOnProgramChange)
1871{
1872 if (!requestMultiviewExtension())
1873 {
1874 return;
1875 }
1876
Geoff Lang25858162017-11-06 11:25:58 -05001877 // Test failing on P400 graphics card (anglebug.com/2228)
1878 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1879
Martin Radevced5c862017-08-17 16:05:29 +03001880 GLVertexArray vao;
1881 glBindVertexArray(vao);
1882 GLBuffer vbo;
1883 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1884 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(1, 0), Vector2I(2, 0),
1885 Vector2I(3, 0)};
1886 std::vector<Vector2> vertexDataInClipSpace =
1887 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 1);
1888 // Fill with x positions so that the resulting clip space coordinate fails the clip test.
1889 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2) * vertexDataInClipSpace.size(),
1890 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
1891 glEnableVertexAttribArray(0);
1892 glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, nullptr);
1893 glVertexAttribDivisor(0, 1);
1894 ASSERT_GL_NO_ERROR();
1895
1896 // Create a program and fbo with N views and draw N instances of a point horizontally.
1897 for (int numViews = 2; numViews <= 4; ++numViews)
1898 {
1899 createFBO(4, 1, numViews);
1900 ASSERT_GL_NO_ERROR();
1901
1902 GLuint program = CreateSimplePassthroughProgram(numViews);
1903 ASSERT_NE(program, 0u);
1904 glUseProgram(program);
1905 ASSERT_GL_NO_ERROR();
1906
1907 glDrawArraysInstanced(GL_POINTS, 0, 1, numViews);
1908
1909 for (int view = 0; view < numViews; ++view)
1910 {
1911 for (int j = 0; j < numViews; ++j)
1912 {
Martin Radev67a8a012017-09-08 13:03:52 +03001913 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03001914 }
1915 for (int j = numViews; j < 4; ++j)
1916 {
1917 EXPECT_EQ(GLColor::black, GetViewColor(j, 0, view));
1918 }
1919 }
1920
1921 glDeleteProgram(program);
1922 }
1923}
1924
Martin Radev72b4e1e2017-08-31 15:42:56 +03001925// The test checks that gl_ViewID_OVR is correctly propagated to the fragment shader.
1926TEST_P(MultiviewRenderTest, SelectColorBasedOnViewIDOVR)
1927{
1928 if (!requestMultiviewExtension())
1929 {
1930 return;
1931 }
1932
1933 const std::string vsSource =
1934 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001935 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03001936 "layout(num_views = 3) in;\n"
1937 "in vec3 vPosition;\n"
1938 "void main()\n"
1939 "{\n"
1940 " gl_Position = vec4(vPosition, 1.);\n"
1941 "}\n";
1942
1943 const std::string fsSource =
1944 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001945 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03001946 "precision mediump float;\n"
1947 "out vec4 col;\n"
1948 "void main()\n"
1949 "{\n"
1950 " if (gl_ViewID_OVR == 0u) {\n"
1951 " col = vec4(1,0,0,1);\n"
1952 " } else if (gl_ViewID_OVR == 1u) {\n"
1953 " col = vec4(0,1,0,1);\n"
1954 " } else if (gl_ViewID_OVR == 2u) {\n"
1955 " col = vec4(0,0,1,1);\n"
1956 " } else {\n"
1957 " col = vec4(0,0,0,0);\n"
1958 " }\n"
1959 "}\n";
1960
1961 createFBO(1, 1, 3);
1962 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev72b4e1e2017-08-31 15:42:56 +03001963
1964 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
1965 ASSERT_GL_NO_ERROR();
1966
1967 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
1968 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
1969 EXPECT_EQ(GLColor::blue, GetViewColor(0, 0, 2));
1970}
1971
1972// The test checks that the inactive layers of a 2D texture array are not written to by a
1973// multi-view program.
1974TEST_P(MultiviewLayeredRenderTest, RenderToSubrageOfLayers)
1975{
1976 if (!requestMultiviewExtension())
1977 {
1978 return;
1979 }
1980
1981 const std::string vsSource =
1982 "#version 300 es\n"
1983 "#extension GL_OVR_multiview : require\n"
1984 "layout(num_views = 2) in;\n"
1985 "in vec3 vPosition;\n"
1986 "void main()\n"
1987 "{\n"
1988 " gl_Position = vec4(vPosition, 1.);\n"
1989 "}\n";
1990
1991 const std::string fsSource =
1992 "#version 300 es\n"
1993 "#extension GL_OVR_multiview : require\n"
1994 "precision mediump float;\n"
1995 "out vec4 col;\n"
1996 "void main()\n"
1997 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001998 " col = vec4(0,1,0,1);\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03001999 "}\n";
2000
2001 createFBO(1, 1, 2, 4, 1);
2002 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
Martin Radev72b4e1e2017-08-31 15:42:56 +03002003
2004 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2005 ASSERT_GL_NO_ERROR();
2006
2007 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +03002008 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2009 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 2));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002010 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 3));
2011}
2012
Martin Radevc1d4e552017-08-21 12:01:10 +03002013// The D3D11 renderer uses a GS whenever the varyings are flat interpolated which can cause
2014// potential bugs if the view is selected in the VS. The test contains a program in which the
2015// gl_InstanceID is passed as a flat varying to the fragment shader where it is used to discard the
2016// fragment if its value is negative. The gl_InstanceID should never be negative and that branch is
2017// never taken. One quad is drawn and the color is selected based on the ViewID - red for view 0 and
2018// green for view 1.
2019TEST_P(MultiviewRenderTest, FlatInterpolation)
Martin Radev3c25ad02017-08-22 17:36:53 +03002020{
Martin Radevc1d4e552017-08-21 12:01:10 +03002021 if (!requestMultiviewExtension())
2022 {
2023 return;
2024 }
2025
2026 const std::string vsSource =
2027 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002028 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002029 "layout(num_views = 2) in;\n"
2030 "in vec3 vPosition;\n"
2031 "flat out int oInstanceID;\n"
2032 "void main()\n"
2033 "{\n"
2034 " gl_Position = vec4(vPosition, 1.);\n"
2035 " oInstanceID = gl_InstanceID;\n"
2036 "}\n";
2037
2038 const std::string fsSource =
2039 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002040 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002041 "precision mediump float;\n"
2042 "flat in int oInstanceID;\n"
2043 "out vec4 col;\n"
2044 "void main()\n"
2045 "{\n"
2046 " if (oInstanceID < 0) {\n"
2047 " discard;\n"
2048 " }\n"
2049 " if (gl_ViewID_OVR == 0u) {\n"
2050 " col = vec4(1,0,0,1);\n"
2051 " } else {\n"
2052 " col = vec4(0,1,0,1);\n"
2053 " }\n"
2054 "}\n";
2055
2056 createFBO(1, 1, 2);
2057 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
2058
2059 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2060 ASSERT_GL_NO_ERROR();
2061
2062 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2063 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev3c25ad02017-08-22 17:36:53 +03002064}
2065
Olli Etuaho604d8732018-07-20 11:02:43 +03002066// This test assigns gl_ViewID_OVR to a flat int varying and then sets the color based on that
2067// varying in the fragment shader.
2068TEST_P(MultiviewRenderTest, FlatInterpolation2)
2069{
2070 if (!requestMultiviewExtension())
2071 {
2072 return;
2073 }
2074
2075 const std::string vsSource =
2076 "#version 300 es\n"
2077 "#extension GL_OVR_multiview : require\n"
2078 "layout(num_views = 2) in;\n"
2079 "in vec3 vPosition;\n"
2080 "flat out int flatVarying;\n"
2081 "void main()\n"
2082 "{\n"
2083 " gl_Position = vec4(vPosition, 1.);\n"
2084 " flatVarying = int(gl_ViewID_OVR);\n"
2085 "}\n";
2086
2087 const std::string fsSource =
2088 "#version 300 es\n"
2089 "#extension GL_OVR_multiview : require\n"
2090 "precision mediump float;\n"
2091 "flat in int flatVarying;\n"
2092 "out vec4 col;\n"
2093 "void main()\n"
2094 "{\n"
2095 " if (flatVarying == 0) {\n"
2096 " col = vec4(1,0,0,1);\n"
2097 " } else {\n"
2098 " col = vec4(0,1,0,1);\n"
2099 " }\n"
2100 "}\n";
2101
2102 createFBO(1, 1, 2);
2103 ANGLE_GL_PROGRAM(program, vsSource, fsSource);
2104
2105 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2106 ASSERT_GL_NO_ERROR();
2107
2108 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2109 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2110}
2111
Martin Radev265a6d42017-09-12 16:51:37 +03002112// The test is added to cover a bug which resulted in the viewport/scissor and viewport offsets not
2113// being correctly applied.
2114TEST_P(MultiviewSideBySideRenderTest, ViewportOffsetsAppliedBugCoverage)
2115{
2116 if (!requestMultiviewExtension())
2117 {
2118 return;
2119 }
2120
2121 createFBO(1, 1, 2);
2122
2123 // Create multiview program.
2124 const std::string &vs =
2125 "#version 300 es\n"
2126 "#extension GL_OVR_multiview : require\n"
2127 "layout(num_views = 2) in;\n"
2128 "layout(location = 0) in vec3 vPosition;\n"
2129 "void main()\n"
2130 "{\n"
2131 " gl_Position = vec4(vPosition, 1.0);\n"
2132 "}\n";
2133
2134 const std::string &fs =
2135 "#version 300 es\n"
2136 "#extension GL_OVR_multiview : require\n"
2137 "precision mediump float;\n"
2138 "out vec4 col;\n"
2139 "void main()\n"
2140 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002141 " col = vec4(0,1,0,1);\n"
Martin Radev265a6d42017-09-12 16:51:37 +03002142 "}\n";
2143
2144 ANGLE_GL_PROGRAM(program, vs, fs);
2145
2146 glViewport(0, 0, 1, 1);
2147 glScissor(0, 0, 1, 1);
2148 glEnable(GL_SCISSOR_TEST);
2149 glClearColor(0, 0, 0, 1);
2150
2151 // Bind the default FBO and make sure that the state is synchronized.
2152 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2153 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2154 ASSERT_GL_NO_ERROR();
2155
2156 // Draw and check that both views are rendered to.
2157 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
2158 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev67a8a012017-09-08 13:03:52 +03002159
Martin Radev265a6d42017-09-12 16:51:37 +03002160 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
Martin Radev67a8a012017-09-08 13:03:52 +03002161 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
2162 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev265a6d42017-09-12 16:51:37 +03002163}
2164
Martin Radevc1d4e552017-08-21 12:01:10 +03002165MultiviewImplementationParams VertexShaderOpenGL()
Martin Radev3c25ad02017-08-22 17:36:53 +03002166{
Martin Radevc1d4e552017-08-21 12:01:10 +03002167 return MultiviewImplementationParams(false, egl_platform::OPENGL());
Martin Radev3c25ad02017-08-22 17:36:53 +03002168}
2169
Martin Radevc1d4e552017-08-21 12:01:10 +03002170MultiviewImplementationParams VertexShaderD3D11()
Martin Radev3c25ad02017-08-22 17:36:53 +03002171{
Martin Radevc1d4e552017-08-21 12:01:10 +03002172 return MultiviewImplementationParams(false, egl_platform::D3D11());
Martin Radev3c25ad02017-08-22 17:36:53 +03002173}
2174
Martin Radevc1d4e552017-08-21 12:01:10 +03002175MultiviewImplementationParams GeomShaderD3D11()
Martin Radev72b4e1e2017-08-31 15:42:56 +03002176{
Martin Radevc1d4e552017-08-21 12:01:10 +03002177 return MultiviewImplementationParams(true, egl_platform::D3D11());
2178}
2179
2180MultiviewTestParams SideBySideVertexShaderOpenGL()
2181{
2182 return MultiviewTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, VertexShaderOpenGL());
2183}
2184
2185MultiviewTestParams LayeredVertexShaderOpenGL()
2186{
2187 return MultiviewTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, VertexShaderOpenGL());
2188}
2189
2190MultiviewTestParams SideBySideGeomShaderD3D11()
2191{
2192 return MultiviewTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, GeomShaderD3D11());
2193}
2194
2195MultiviewTestParams LayeredGeomShaderD3D11()
2196{
2197 return MultiviewTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, GeomShaderD3D11());
2198}
2199
2200MultiviewTestParams SideBySideVertexShaderD3D11()
2201{
2202 return MultiviewTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, VertexShaderD3D11());
2203}
2204
2205MultiviewTestParams LayeredVertexShaderD3D11()
2206{
2207 return MultiviewTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, VertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002208}
2209
Martin Radev8f276e22017-05-30 12:05:52 +03002210ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest, ES31_OPENGL());
Martin Radevced5c862017-08-17 16:05:29 +03002211ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002212 SideBySideVertexShaderOpenGL(),
2213 LayeredVertexShaderOpenGL(),
2214 SideBySideGeomShaderD3D11(),
2215 SideBySideVertexShaderD3D11(),
2216 LayeredGeomShaderD3D11(),
2217 LayeredVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002218ANGLE_INSTANTIATE_TEST(MultiviewRenderTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002219 SideBySideVertexShaderOpenGL(),
2220 LayeredVertexShaderOpenGL(),
2221 SideBySideGeomShaderD3D11(),
2222 SideBySideVertexShaderD3D11(),
2223 LayeredGeomShaderD3D11(),
2224 LayeredVertexShaderD3D11());
Martin Radevced5c862017-08-17 16:05:29 +03002225ANGLE_INSTANTIATE_TEST(MultiviewOcclusionQueryTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002226 SideBySideVertexShaderOpenGL(),
2227 LayeredVertexShaderOpenGL(),
2228 SideBySideGeomShaderD3D11(),
2229 SideBySideVertexShaderD3D11(),
2230 LayeredGeomShaderD3D11(),
2231 LayeredVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002232ANGLE_INSTANTIATE_TEST(MultiviewProgramGenerationTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002233 SideBySideVertexShaderOpenGL(),
2234 LayeredVertexShaderOpenGL(),
2235 SideBySideGeomShaderD3D11(),
2236 SideBySideVertexShaderD3D11(),
2237 LayeredGeomShaderD3D11(),
2238 LayeredVertexShaderD3D11());
Martin Radevced5c862017-08-17 16:05:29 +03002239ANGLE_INSTANTIATE_TEST(MultiviewRenderPrimitiveTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002240 SideBySideVertexShaderOpenGL(),
2241 LayeredVertexShaderOpenGL(),
2242 SideBySideGeomShaderD3D11(),
2243 SideBySideVertexShaderD3D11(),
2244 LayeredGeomShaderD3D11(),
2245 LayeredVertexShaderD3D11());
2246ANGLE_INSTANTIATE_TEST(MultiviewSideBySideRenderTest, VertexShaderOpenGL(), GeomShaderD3D11());
2247ANGLE_INSTANTIATE_TEST(MultiviewLayeredRenderTest, VertexShaderOpenGL(), GeomShaderD3D11());