blob: 489e1e3906e2c644a1fbd949447b5d65b122875f [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,
Olli Etuaho2c8f0842018-09-12 14:44:55 +030040 int samples,
Olli Etuahof26b27e2018-08-17 11:01:19 +030041 const MultiviewImplementationParams &implementationParams)
Olli Etuaho2c8f0842018-09-12 14:44:55 +030042 : MultiviewImplementationParams(implementationParams),
43 mMultiviewLayout(multiviewLayout),
44 mSamples(samples)
Martin Radev3c25ad02017-08-22 17:36:53 +030045 {
Jamie Madillba319ba2018-12-29 10:29:33 -050046 EXPECT_TRUE(multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE ||
47 multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Martin Radev3c25ad02017-08-22 17:36:53 +030048 }
49 GLenum mMultiviewLayout;
Olli Etuaho2c8f0842018-09-12 14:44:55 +030050 int mSamples;
Martin Radev3c25ad02017-08-22 17:36:53 +030051};
52
Olli Etuahof26b27e2018-08-17 11:01:19 +030053std::ostream &operator<<(std::ostream &os, const MultiviewRenderTestParams &params)
Martin Radev3c25ad02017-08-22 17:36:53 +030054{
Martin Radevc1d4e552017-08-21 12:01:10 +030055 const MultiviewImplementationParams &base =
56 static_cast<const MultiviewImplementationParams &>(params);
Martin Radev3c25ad02017-08-22 17:36:53 +030057 os << base;
58 switch (params.mMultiviewLayout)
59 {
60 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
61 os << "_layered";
62 break;
63 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
64 os << "_side_by_side";
65 break;
66 default:
Jamie Madillba319ba2018-12-29 10:29:33 -050067 os << "_error";
68 break;
Martin Radev3c25ad02017-08-22 17:36:53 +030069 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +030070 if (params.mSamples > 0)
71 {
72 os << "_samples_" << params.mSamples;
73 }
Martin Radev3c25ad02017-08-22 17:36:53 +030074 return os;
75}
76
Olli Etuaho4836acc2018-08-20 15:23:18 +030077class MultiviewFramebufferTestBase : public MultiviewTestBase
Martin Radev8f276e22017-05-30 12:05:52 +030078{
79 protected:
Olli Etuaho2c8f0842018-09-12 14:44:55 +030080 MultiviewFramebufferTestBase(const PlatformParameters &params,
81 GLenum multiviewLayout,
82 int samples)
Olli Etuahof26b27e2018-08-17 11:01:19 +030083 : MultiviewTestBase(params),
Martin Radev3c25ad02017-08-22 17:36:53 +030084 mViewWidth(0),
85 mViewHeight(0),
Olli Etuaho4836acc2018-08-20 15:23:18 +030086 mNumViews(0),
Olli Etuaho44ae8992018-08-20 15:37:09 +030087 mColorTexture(0u),
88 mDepthTexture(0u),
89 mDrawFramebuffer(0u),
Olli Etuaho2c8f0842018-09-12 14:44:55 +030090 mMultiviewLayout(multiviewLayout),
91 mSamples(samples),
92 mResolveTexture(0u)
Jamie Madillb980c562018-11-27 11:34:27 -050093 {}
Olli Etuaho44ae8992018-08-20 15:37:09 +030094
Olli Etuaho4836acc2018-08-20 15:23:18 +030095 void FramebufferTestSetUp() { MultiviewTestBase::MultiviewTestBaseSetUp(); }
Olli Etuaho44ae8992018-08-20 15:37:09 +030096
97 void FramebufferTestTearDown()
98 {
99 freeFBOs();
100 MultiviewTestBase::MultiviewTestBaseTearDown();
101 }
102
Olli Etuaho4836acc2018-08-20 15:23:18 +0300103 void updateFBOs(int viewWidth, int height, int numViews, int numLayers, int baseViewIndex)
Martin Radev3c25ad02017-08-22 17:36:53 +0300104 {
Jamie Madillba319ba2018-12-29 10:29:33 -0500105 ASSERT_TRUE(numViews + baseViewIndex <= numLayers);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300106
Olli Etuaho44ae8992018-08-20 15:37:09 +0300107 freeFBOs();
108
Martin Radev3c25ad02017-08-22 17:36:53 +0300109 mViewWidth = viewWidth;
110 mViewHeight = height;
111 mNumViews = numViews;
Martin Radev8f276e22017-05-30 12:05:52 +0300112
Olli Etuaho44ae8992018-08-20 15:37:09 +0300113 glGenTextures(1, &mColorTexture);
114 glGenTextures(1, &mDepthTexture);
Martin Radev0abb7a22017-08-28 15:34:45 +0300115
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300116 CreateMultiviewBackingTextures(mMultiviewLayout, mSamples, viewWidth, height, numLayers,
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300117 mColorTexture, mDepthTexture, 0u);
Martin Radev3c25ad02017-08-22 17:36:53 +0300118
Olli Etuaho44ae8992018-08-20 15:37:09 +0300119 glGenFramebuffers(1, &mDrawFramebuffer);
120
Martin Radev3c25ad02017-08-22 17:36:53 +0300121 // Create draw framebuffer to be used for multiview rendering.
122 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300123 AttachMultiviewTextures(GL_DRAW_FRAMEBUFFER, mMultiviewLayout, viewWidth, numViews,
124 baseViewIndex, mColorTexture, mDepthTexture, 0u);
Martin Radev8f276e22017-05-30 12:05:52 +0300125
Martin Radev8f276e22017-05-30 12:05:52 +0300126 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
127
128 // Create read framebuffer to be used to retrieve the pixel information for testing
129 // purposes.
Martin Radev3c25ad02017-08-22 17:36:53 +0300130 switch (mMultiviewLayout)
131 {
132 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
133 mReadFramebuffer.resize(1);
Olli Etuaho44ae8992018-08-20 15:37:09 +0300134 glGenFramebuffers(1, mReadFramebuffer.data());
Martin Radev3c25ad02017-08-22 17:36:53 +0300135 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[0]);
136 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
137 mColorTexture, 0);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300138 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
139 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300140 break;
141 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev72b4e1e2017-08-31 15:42:56 +0300142 mReadFramebuffer.resize(numLayers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400143 glGenFramebuffers(static_cast<GLsizei>(mReadFramebuffer.size()),
144 mReadFramebuffer.data());
Martin Radev72b4e1e2017-08-31 15:42:56 +0300145 for (int i = 0; i < numLayers; ++i)
Martin Radev3c25ad02017-08-22 17:36:53 +0300146 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300147 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[i]);
148 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
149 mColorTexture, 0, i);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300150 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
151 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300152 }
153 break;
154 default:
Jamie Madillba319ba2018-12-29 10:29:33 -0500155 ASSERT_TRUE(false);
Martin Radev3c25ad02017-08-22 17:36:53 +0300156 }
Martin Radev8f276e22017-05-30 12:05:52 +0300157
158 // Clear the buffers.
Martin Radev3c25ad02017-08-22 17:36:53 +0300159 glViewport(0, 0, viewWidth, height);
160 if (mMultiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
161 {
162 // Enable the scissor test only for side-by-side framebuffers.
163 glEnable(GL_SCISSOR_TEST);
164 glScissor(0, 0, viewWidth, height);
165 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300166 }
Martin Radev8f276e22017-05-30 12:05:52 +0300167
Olli Etuaho4836acc2018-08-20 15:23:18 +0300168 void updateFBOs(int viewWidth, int height, int numViews)
Martin Radev72b4e1e2017-08-31 15:42:56 +0300169 {
Olli Etuaho4836acc2018-08-20 15:23:18 +0300170 updateFBOs(viewWidth, height, numViews, numViews, 0);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300171 }
172
Olli Etuaho4836acc2018-08-20 15:23:18 +0300173 void bindMemberDrawFramebuffer() { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer); }
174
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300175 // In case we have a multisampled framebuffer, creates and binds a resolve framebuffer as the
176 // draw framebuffer, and resolves the read framebuffer to it.
177 void resolveMultisampledFBO()
178 {
179 if (mSamples == 0)
180 {
181 return;
182 }
183 int numLayers = mReadFramebuffer.size();
184 if (mResolveFramebuffer.empty())
185 {
Jamie Madillba319ba2018-12-29 10:29:33 -0500186 ASSERT_TRUE(mResolveTexture == 0u);
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300187 glGenTextures(1, &mResolveTexture);
188 CreateMultiviewBackingTextures(mMultiviewLayout, 0, mViewWidth, mViewHeight, numLayers,
189 mResolveTexture, 0u, 0u);
190
191 mResolveFramebuffer.resize(numLayers);
192 glGenFramebuffers(static_cast<GLsizei>(mResolveFramebuffer.size()),
193 mResolveFramebuffer.data());
194 for (int i = 0; i < numLayers; ++i)
195 {
196 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFramebuffer[i]);
197 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
198 mResolveTexture, 0, i);
199 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
200 glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
201 }
202 }
203 for (int i = 0; i < numLayers; ++i)
204 {
205 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[i]);
206 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFramebuffer[i]);
207 glBlitFramebuffer(0, 0, mViewWidth, mViewHeight, 0, 0, mViewWidth, mViewHeight,
208 GL_COLOR_BUFFER_BIT, GL_NEAREST);
209 }
210 }
211
Martin Radev3c25ad02017-08-22 17:36:53 +0300212 GLColor GetViewColor(int x, int y, int view)
213 {
214 switch (mMultiviewLayout)
215 {
216 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300217 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[0]);
Martin Radev3c25ad02017-08-22 17:36:53 +0300218 return ReadColor(view * mViewWidth + x, y);
219 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Jamie Madillba319ba2018-12-29 10:29:33 -0500220 EXPECT_TRUE(static_cast<size_t>(view) < mReadFramebuffer.size());
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300221 if (mSamples > 0)
222 {
Jamie Madillba319ba2018-12-29 10:29:33 -0500223 EXPECT_TRUE(static_cast<size_t>(view) < mResolveFramebuffer.size());
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300224 glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFramebuffer[view]);
225 }
226 else
227 {
228 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[view]);
229 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300230 return ReadColor(x, y);
231 default:
Jamie Madillba319ba2018-12-29 10:29:33 -0500232 EXPECT_TRUE(false);
Martin Radev3c25ad02017-08-22 17:36:53 +0300233 }
234 return GLColor(0, 0, 0, 0);
Martin Radev8f276e22017-05-30 12:05:52 +0300235 }
236
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300237 bool isMultisampled() { return mSamples > 0; }
238
Martin Radev3c25ad02017-08-22 17:36:53 +0300239 int mViewWidth;
240 int mViewHeight;
241 int mNumViews;
Olli Etuaho4836acc2018-08-20 15:23:18 +0300242
Olli Etuaho44ae8992018-08-20 15:37:09 +0300243 GLuint mColorTexture;
244 GLuint mDepthTexture;
245
Olli Etuaho4836acc2018-08-20 15:23:18 +0300246 private:
Olli Etuaho44ae8992018-08-20 15:37:09 +0300247 GLuint mDrawFramebuffer;
248 std::vector<GLuint> mReadFramebuffer;
Olli Etuaho4836acc2018-08-20 15:23:18 +0300249 GLenum mMultiviewLayout;
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300250 int mSamples;
251
252 // For reading back multisampled framebuffer.
253 std::vector<GLuint> mResolveFramebuffer;
254 GLuint mResolveTexture;
Olli Etuaho44ae8992018-08-20 15:37:09 +0300255
256 void freeFBOs()
257 {
258 if (mDrawFramebuffer)
259 {
260 glDeleteFramebuffers(1, &mDrawFramebuffer);
261 mDrawFramebuffer = 0;
262 }
263 if (!mReadFramebuffer.empty())
264 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400265 GLsizei framebufferCount = static_cast<GLsizei>(mReadFramebuffer.size());
266 glDeleteFramebuffers(framebufferCount, mReadFramebuffer.data());
Olli Etuaho44ae8992018-08-20 15:37:09 +0300267 mReadFramebuffer.clear();
268 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300269 if (!mResolveFramebuffer.empty())
270 {
271 GLsizei framebufferCount = static_cast<GLsizei>(mResolveFramebuffer.size());
272 glDeleteFramebuffers(framebufferCount, mResolveFramebuffer.data());
273 mResolveFramebuffer.clear();
274 }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300275 if (mDepthTexture)
276 {
277 glDeleteTextures(1, &mDepthTexture);
278 mDepthTexture = 0;
279 }
280 if (mColorTexture)
281 {
282 glDeleteTextures(1, &mColorTexture);
283 mColorTexture = 0;
284 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300285 if (mResolveTexture)
286 {
287 glDeleteTextures(1, &mResolveTexture);
288 mResolveTexture = 0;
289 }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300290 }
Martin Radev8f276e22017-05-30 12:05:52 +0300291};
292
Olli Etuaho4836acc2018-08-20 15:23:18 +0300293class MultiviewRenderTest : public MultiviewFramebufferTestBase,
Olli Etuahof26b27e2018-08-17 11:01:19 +0300294 public ::testing::TestWithParam<MultiviewRenderTestParams>
Martin Radev8f276e22017-05-30 12:05:52 +0300295{
296 protected:
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300297 MultiviewRenderTest()
298 : MultiviewFramebufferTestBase(GetParam(), GetParam().mMultiviewLayout, GetParam().mSamples)
Jamie Madillb980c562018-11-27 11:34:27 -0500299 {}
Olli Etuaho4836acc2018-08-20 15:23:18 +0300300 void SetUp() override { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300301 void TearDown() override { MultiviewFramebufferTestBase::FramebufferTestTearDown(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300302
303 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
304 {
305 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
306 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300307};
308
Jamie Madill04c084d2018-08-08 15:49:28 -0400309constexpr char kDualViewVSSource[] = R"(#version 300 es
310#extension GL_OVR_multiview : require
311layout(num_views = 2) in;
312in vec4 vPosition;
313void main()
314{
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300315 gl_Position.x = (gl_ViewID_OVR == 0u ? vPosition.x * 0.5 + 0.5 : vPosition.x * 0.5 - 0.5);
Jamie Madill04c084d2018-08-08 15:49:28 -0400316 gl_Position.yzw = vPosition.yzw;
317})";
318
319constexpr char kDualViewFSSource[] = R"(#version 300 es
320#extension GL_OVR_multiview : require
321precision mediump float;
322out vec4 col;
323void main()
324{
325 col = vec4(0,1,0,1);
326})";
327
Martin Radev3c25ad02017-08-22 17:36:53 +0300328class MultiviewRenderDualViewTest : public MultiviewRenderTest
329{
330 protected:
331 MultiviewRenderDualViewTest() : mProgram(0u) {}
Martin Radev8f276e22017-05-30 12:05:52 +0300332
333 void SetUp() override
334 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300335 MultiviewRenderTest::SetUp();
Martin Radev8f276e22017-05-30 12:05:52 +0300336
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300337 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev8f276e22017-05-30 12:05:52 +0300338 {
339 return;
340 }
341
Olli Etuaho4836acc2018-08-20 15:23:18 +0300342 updateFBOs(2, 1, 2);
Jamie Madill04c084d2018-08-08 15:49:28 -0400343 mProgram = CompileProgram(kDualViewVSSource, kDualViewFSSource);
Martin Radev61bd9992017-08-11 13:10:55 +0300344 ASSERT_NE(mProgram, 0u);
Martin Radev8f276e22017-05-30 12:05:52 +0300345 glUseProgram(mProgram);
346 ASSERT_GL_NO_ERROR();
347 }
348
Olli Etuaho44ae8992018-08-20 15:37:09 +0300349 void TearDown() override
350 {
351 if (mProgram != 0u)
352 {
353 glDeleteProgram(mProgram);
354 mProgram = 0u;
355 }
356
357 MultiviewRenderTest::TearDown();
358 }
359
Martin Radev8f276e22017-05-30 12:05:52 +0300360 void checkOutput()
361 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300362 resolveMultisampledFBO();
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300363 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +0300364 EXPECT_EQ(GLColor::green, GetViewColor(1, 0, 0));
365 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300366 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(1, 0, 1));
Martin Radev8f276e22017-05-30 12:05:52 +0300367 }
368
369 GLuint mProgram;
370};
371
Olli Etuaho44ae8992018-08-20 15:37:09 +0300372// Base class for tests that care mostly about draw call validity and not rendering results.
373class MultiviewDrawValidationTest : public MultiviewTest
Jamie Madill04c084d2018-08-08 15:49:28 -0400374{
375 protected:
Olli Etuaho44ae8992018-08-20 15:37:09 +0300376 MultiviewDrawValidationTest() : MultiviewTest() {}
Jamie Madill04c084d2018-08-08 15:49:28 -0400377
Olli Etuaho44ae8992018-08-20 15:37:09 +0300378 void initOnePixelColorTexture2D(GLuint texId)
Jamie Madill04c084d2018-08-08 15:49:28 -0400379 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300380 glBindTexture(GL_TEXTURE_2D, texId);
Jamie Madill04c084d2018-08-08 15:49:28 -0400381 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Olli Etuaho44ae8992018-08-20 15:37:09 +0300382 }
Jamie Madill04c084d2018-08-08 15:49:28 -0400383
Olli Etuaho44ae8992018-08-20 15:37:09 +0300384 // This initializes a simple VAO with a valid vertex buffer and index buffer with three
385 // vertices.
386 void initVAO(GLuint vao, GLuint vertexBuffer, GLuint indexBuffer)
387 {
388 glBindVertexArray(vao);
Jamie Madill04c084d2018-08-08 15:49:28 -0400389
390 const float kVertexData[3] = {0.0f};
Olli Etuaho44ae8992018-08-20 15:37:09 +0300391 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
Jamie Madill04c084d2018-08-08 15:49:28 -0400392 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3u, &kVertexData[0], GL_STATIC_DRAW);
393
394 const unsigned int kIndices[3] = {0u, 1u, 2u};
Olli Etuaho44ae8992018-08-20 15:37:09 +0300395 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
Jamie Madill04c084d2018-08-08 15:49:28 -0400396 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, &kIndices[0],
397 GL_STATIC_DRAW);
398 ASSERT_GL_NO_ERROR();
399 }
Jamie Madill04c084d2018-08-08 15:49:28 -0400400};
401
Martin Radev3c25ad02017-08-22 17:36:53 +0300402class MultiviewOcclusionQueryTest : public MultiviewRenderTest
Martin Radev0d671c92017-08-10 16:41:52 +0300403{
404 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300405 MultiviewOcclusionQueryTest() {}
Martin Radev0d671c92017-08-10 16:41:52 +0300406
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400407 bool requestOcclusionQueryExtension()
408 {
409 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
410 {
411 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
412 }
413
414 if (!extensionEnabled("GL_EXT_occlusion_query_boolean"))
415 {
416 std::cout << "Test skipped due to missing GL_EXT_occlusion_query_boolean." << std::endl;
417 return false;
418 }
419 return true;
420 }
421
Martin Radev0d671c92017-08-10 16:41:52 +0300422 GLuint drawAndRetrieveOcclusionQueryResult(GLuint program)
423 {
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400424 GLQueryEXT query;
425 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED, query);
Martin Radev0d671c92017-08-10 16:41:52 +0300426 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
427 glEndQueryEXT(GL_ANY_SAMPLES_PASSED);
428
429 GLuint result = GL_TRUE;
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400430 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT, &result);
Martin Radev0d671c92017-08-10 16:41:52 +0300431 return result;
432 }
433};
434
Olli Etuaho4bcaf992018-08-17 17:18:28 +0300435class MultiviewProgramGenerationTest : public MultiviewTest
Martin Radev41ac68e2017-06-06 12:16:58 +0300436{
437 protected:
438 MultiviewProgramGenerationTest() {}
439};
440
Martin Radev3c25ad02017-08-22 17:36:53 +0300441class MultiviewRenderPrimitiveTest : public MultiviewRenderTest
Martin Radev61bd9992017-08-11 13:10:55 +0300442{
443 protected:
Olli Etuaho44ae8992018-08-20 15:37:09 +0300444 MultiviewRenderPrimitiveTest() : mVBO(0u) {}
445
446 void SetUp() override
447 {
448 MultiviewRenderTest::SetUp();
449 glGenBuffers(1, &mVBO);
450 }
451
452 void TearDown() override
453 {
454 if (mVBO)
455 {
456 glDeleteBuffers(1, &mVBO);
457 mVBO = 0u;
458 }
459 MultiviewRenderTest::TearDown();
460 }
Martin Radev61bd9992017-08-11 13:10:55 +0300461
462 void setupGeometry(const std::vector<Vector2> &vertexData)
463 {
Martin Radev61bd9992017-08-11 13:10:55 +0300464 glBindBuffer(GL_ARRAY_BUFFER, mVBO);
465 glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vector2), vertexData.data(),
466 GL_STATIC_DRAW);
467 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500468 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +0300469 }
470
Martin Radev67a8a012017-09-08 13:03:52 +0300471 void checkGreenChannel(const GLubyte expectedGreenChannelData[])
Martin Radev61bd9992017-08-11 13:10:55 +0300472 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300473 for (int view = 0; view < mNumViews; ++view)
Martin Radev61bd9992017-08-11 13:10:55 +0300474 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300475 for (int w = 0; w < mViewWidth; ++w)
Martin Radev61bd9992017-08-11 13:10:55 +0300476 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300477 for (int h = 0; h < mViewHeight; ++h)
478 {
479 size_t flatIndex =
480 static_cast<size_t>(view * mViewWidth * mViewHeight + mViewWidth * h + w);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300481 EXPECT_EQ(GLColor(0, expectedGreenChannelData[flatIndex], 0,
482 expectedGreenChannelData[flatIndex]),
Martin Radev3c25ad02017-08-22 17:36:53 +0300483 GetViewColor(w, h, view));
484 }
Martin Radev61bd9992017-08-11 13:10:55 +0300485 }
486 }
487 }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300488 GLuint mVBO;
Martin Radev61bd9992017-08-11 13:10:55 +0300489};
490
Olli Etuaho4836acc2018-08-20 15:23:18 +0300491class MultiviewSideBySideRenderTest : public MultiviewFramebufferTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300492 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev3c25ad02017-08-22 17:36:53 +0300493{
494 protected:
495 MultiviewSideBySideRenderTest()
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300496 : MultiviewFramebufferTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0)
Jamie Madillb980c562018-11-27 11:34:27 -0500497 {}
Olli Etuaho44ae8992018-08-20 15:37:09 +0300498
499 void SetUp() final { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
500 void TearDown() final { MultiviewFramebufferTestBase::FramebufferTestTearDown(); }
501 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) final
Martin Radevc1d4e552017-08-21 12:01:10 +0300502 {
503 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
504 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300505};
506
Olli Etuaho4836acc2018-08-20 15:23:18 +0300507class MultiviewLayeredRenderTest : public MultiviewFramebufferTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300508 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev72b4e1e2017-08-31 15:42:56 +0300509{
510 protected:
511 MultiviewLayeredRenderTest()
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300512 : MultiviewFramebufferTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0)
Jamie Madillb980c562018-11-27 11:34:27 -0500513 {}
Olli Etuaho44ae8992018-08-20 15:37:09 +0300514 void SetUp() final { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
515 void TearDown() final { MultiviewFramebufferTestBase::FramebufferTestTearDown(); }
516 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) final
Martin Radevc1d4e552017-08-21 12:01:10 +0300517 {
518 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
519 }
Martin Radev72b4e1e2017-08-31 15:42:56 +0300520};
521
Martin Radev14a26ae2017-07-24 15:56:29 +0300522// The test verifies that glDraw*Indirect:
523// 1) generates an INVALID_OPERATION error if the number of views in the draw framebuffer is greater
524// than 1.
525// 2) does not generate any error if the draw framebuffer has exactly 1 view.
Martin Radev7cf61662017-07-26 17:10:53 +0300526TEST_P(MultiviewDrawValidationTest, IndirectDraw)
Martin Radev14a26ae2017-07-24 15:56:29 +0300527{
Jamie Madill3a256222018-12-08 09:56:39 -0500528 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14a26ae2017-07-24 15:56:29 +0300529
Martin Radev14a26ae2017-07-24 15:56:29 +0300530 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Martin Radev14a26ae2017-07-24 15:56:29 +0300531
Jamie Madill35cd7332018-12-02 12:03:33 -0500532 constexpr char kFS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300533 "#version 300 es\n"
534 "#extension GL_OVR_multiview : require\n"
535 "precision mediump float;\n"
536 "void main()\n"
537 "{}\n";
538
Olli Etuaho44ae8992018-08-20 15:37:09 +0300539 GLVertexArray vao;
540 GLBuffer vertexBuffer;
541 GLBuffer indexBuffer;
542 initVAO(vao, vertexBuffer, indexBuffer);
543
544 GLFramebuffer fbo;
545 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
546
Martin Radev14a26ae2017-07-24 15:56:29 +0300547 GLBuffer commandBuffer;
548 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, commandBuffer);
549 const GLuint commandData[] = {1u, 1u, 0u, 0u, 0u};
550 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(GLuint) * 5u, &commandData[0], GL_STATIC_DRAW);
551 ASSERT_GL_NO_ERROR();
552
Olli Etuaho44ae8992018-08-20 15:37:09 +0300553 GLTexture tex2D;
554 initOnePixelColorTexture2D(tex2D);
555
Martin Radev14a26ae2017-07-24 15:56:29 +0300556 // Check for a GL_INVALID_OPERATION error with the framebuffer having 2 views.
557 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500558 constexpr char kVS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300559 "#version 300 es\n"
560 "#extension GL_OVR_multiview : require\n"
561 "layout(num_views = 2) in;\n"
562 "void main()\n"
563 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500564 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev14a26ae2017-07-24 15:56:29 +0300565 glUseProgram(program);
566
Olli Etuaho44ae8992018-08-20 15:37:09 +0300567 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
568 2, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300569
570 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
571 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
572
573 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
574 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
575 }
576
577 // Check that no errors are generated if the number of views is 1.
578 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500579 constexpr char kVS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300580 "#version 300 es\n"
581 "#extension GL_OVR_multiview : require\n"
582 "layout(num_views = 1) in;\n"
583 "void main()\n"
584 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500585 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev14a26ae2017-07-24 15:56:29 +0300586 glUseProgram(program);
587
Olli Etuaho44ae8992018-08-20 15:37:09 +0300588 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
589 1, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300590
591 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
592 EXPECT_GL_NO_ERROR();
593
594 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
595 EXPECT_GL_NO_ERROR();
596 }
597}
598
Martin Radev7cf61662017-07-26 17:10:53 +0300599// The test verifies that glDraw*:
600// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and
601// program differs.
602// 2) does not generate any error if the number of views is the same.
Martin Radev7cf61662017-07-26 17:10:53 +0300603TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
604{
Jamie Madill3a256222018-12-08 09:56:39 -0500605 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev7cf61662017-07-26 17:10:53 +0300606
607 const GLint viewportOffsets[4] = {0, 0, 2, 0};
608
Jamie Madill35cd7332018-12-02 12:03:33 -0500609 constexpr char kVS[] =
Martin Radev7cf61662017-07-26 17:10:53 +0300610 "#version 300 es\n"
611 "#extension GL_OVR_multiview : require\n"
612 "layout(num_views = 2) in;\n"
613 "void main()\n"
614 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500615 constexpr char kFS[] =
Martin Radev7cf61662017-07-26 17:10:53 +0300616 "#version 300 es\n"
617 "#extension GL_OVR_multiview : require\n"
618 "precision mediump float;\n"
619 "void main()\n"
620 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500621 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev7cf61662017-07-26 17:10:53 +0300622 glUseProgram(program);
623
Olli Etuaho44ae8992018-08-20 15:37:09 +0300624 GLVertexArray vao;
625 GLBuffer vertexBuffer;
626 GLBuffer indexBuffer;
627 initVAO(vao, vertexBuffer, indexBuffer);
628
629 GLFramebuffer fbo;
630 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
631
632 GLTexture tex2D;
633 initOnePixelColorTexture2D(tex2D);
634
Martin Radev7cf61662017-07-26 17:10:53 +0300635 // 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.
Olli Etuaho44ae8992018-08-20 15:37:09 +0300639 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
640 1, &viewportOffsets[0]);
Martin Radev7cf61662017-07-26 17:10:53 +0300641
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 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300652 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
653 2, &viewportOffsets[0]);
Martin Radev7cf61662017-07-26 17:10:53 +0300654
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
Jamie Madill35cd7332018-12-02 12:03:33 -0500672 constexpr char kVS[] =
Martin Radevda8e2572017-09-12 17:21:16 +0300673 "#version 300 es\n"
674 "void main()\n"
675 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500676 constexpr char kFS[] =
Martin Radevda8e2572017-09-12 17:21:16 +0300677 "#version 300 es\n"
678 "precision mediump float;\n"
679 "void main()\n"
680 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500681 ANGLE_GL_PROGRAM(programNoMultiview, kVS, kFS);
Martin Radevda8e2572017-09-12 17:21:16 +0300682 glUseProgram(programNoMultiview);
683
Olli Etuaho44ae8992018-08-20 15:37:09 +0300684 GLVertexArray vao;
685 GLBuffer vertexBuffer;
686 GLBuffer indexBuffer;
687 initVAO(vao, vertexBuffer, indexBuffer);
688
689 GLFramebuffer fbo;
690 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
691
692 GLTexture tex2D;
693 initOnePixelColorTexture2D(tex2D);
694
Martin Radevda8e2572017-09-12 17:21:16 +0300695 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Olli Etuaho44ae8992018-08-20 15:37:09 +0300696 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0, 2,
Martin Radevda8e2572017-09-12 17:21:16 +0300697 &viewportOffsets[0]);
698
699 glDrawArrays(GL_TRIANGLES, 0, 3);
700 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
701
702 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
703 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radev7cf61662017-07-26 17:10:53 +0300704}
705
Martin Radev7e69f762017-07-27 14:54:13 +0300706// The test verifies that glDraw*:
707// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
Jamie Madill3a256222018-12-08 09:56:39 -0500708// greater than 1 and there is an active not paused transform feedback object.
Martin Radev7e69f762017-07-27 14:54:13 +0300709// 2) does not generate any error if the number of views in the draw framebuffer is 1.
710TEST_P(MultiviewDrawValidationTest, ActiveTransformFeedback)
711{
Jamie Madill3a256222018-12-08 09:56:39 -0500712 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev7e69f762017-07-27 14:54:13 +0300713
714 const GLint viewportOffsets[4] = {0, 0, 2, 0};
715
Jamie Madill35cd7332018-12-02 12:03:33 -0500716 constexpr char kVS[] = R"(#version 300 es
717out float tfVarying;
718void main()
719{
720 tfVarying = 1.0;
721})";
722
723 constexpr char kFS[] = R"(#version 300 es
724precision mediump float;
725void main()
726{})";
Jamie Madill04c084d2018-08-08 15:49:28 -0400727
Olli Etuaho3755c482017-10-13 15:40:26 +0300728 std::vector<std::string> tfVaryings;
Jamie Madill04c084d2018-08-08 15:49:28 -0400729 tfVaryings.emplace_back("tfVarying");
Jamie Madill35cd7332018-12-02 12:03:33 -0500730 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(singleViewProgram, kVS, kFS, tfVaryings,
Olli Etuaho3755c482017-10-13 15:40:26 +0300731 GL_SEPARATE_ATTRIBS);
Jamie Madill04c084d2018-08-08 15:49:28 -0400732
733 std::vector<std::string> dualViewTFVaryings;
734 dualViewTFVaryings.emplace_back("gl_Position");
735 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(dualViewProgram, kDualViewVSSource, kDualViewFSSource,
736 dualViewTFVaryings, GL_SEPARATE_ATTRIBS);
Martin Radev7e69f762017-07-27 14:54:13 +0300737
Olli Etuaho44ae8992018-08-20 15:37:09 +0300738 GLVertexArray vao;
739 GLBuffer vertexBuffer;
740 GLBuffer indexBuffer;
741 initVAO(vao, vertexBuffer, indexBuffer);
742
Martin Radev7e69f762017-07-27 14:54:13 +0300743 GLBuffer tbo;
744 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);
Jamie Madill04c084d2018-08-08 15:49:28 -0400745 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 16u, nullptr, GL_STATIC_DRAW);
Martin Radev7e69f762017-07-27 14:54:13 +0300746
747 GLTransformFeedback transformFeedback;
748 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
Olli Etuaho3755c482017-10-13 15:40:26 +0300749
750 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
751
Jamie Madill04c084d2018-08-08 15:49:28 -0400752 glUseProgram(dualViewProgram);
Martin Radev7e69f762017-07-27 14:54:13 +0300753 glBeginTransformFeedback(GL_TRIANGLES);
754 ASSERT_GL_NO_ERROR();
755
Olli Etuaho44ae8992018-08-20 15:37:09 +0300756 GLFramebuffer fbo;
757 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
758
759 GLTexture tex2D;
760 initOnePixelColorTexture2D(tex2D);
761
Martin Radev7e69f762017-07-27 14:54:13 +0300762 // Check that drawArrays generates an error when there is an active transform feedback object
763 // and the number of views in the draw framebuffer is greater than 1.
764 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300765 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
766 2, &viewportOffsets[0]);
Martin Radev7e69f762017-07-27 14:54:13 +0300767 glDrawArrays(GL_TRIANGLES, 0, 3);
768 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
769 }
770
Jamie Madill04c084d2018-08-08 15:49:28 -0400771 glEndTransformFeedback();
772
773 // Ending transform feedback should allow the draw to succeed.
774 {
775 glDrawArrays(GL_TRIANGLES, 0, 3);
776 EXPECT_GL_NO_ERROR();
777 }
778
Jamie Madill3a256222018-12-08 09:56:39 -0500779 // A paused transform feedback should not trigger an error.
Jamie Madill04c084d2018-08-08 15:49:28 -0400780 glBeginTransformFeedback(GL_TRIANGLES);
781 glPauseTransformFeedback();
782 ASSERT_GL_NO_ERROR();
783
784 glDrawArrays(GL_TRIANGLES, 0, 3);
Jamie Madill3a256222018-12-08 09:56:39 -0500785 ASSERT_GL_NO_ERROR();
Jamie Madill04c084d2018-08-08 15:49:28 -0400786
787 // Unbind transform feedback - should succeed.
788 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
789 glDrawArrays(GL_TRIANGLES, 0, 3);
790 ASSERT_GL_NO_ERROR();
791
Jamie Madill3a256222018-12-08 09:56:39 -0500792 // Rebind paused transform feedback - should succeed.
Jamie Madill04c084d2018-08-08 15:49:28 -0400793 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
794 glDrawArrays(GL_TRIANGLES, 0, 3);
Jamie Madill3a256222018-12-08 09:56:39 -0500795 ASSERT_GL_NO_ERROR();
Jamie Madill04c084d2018-08-08 15:49:28 -0400796
797 glResumeTransformFeedback();
798 glEndTransformFeedback();
799
800 glUseProgram(singleViewProgram);
801 glBeginTransformFeedback(GL_TRIANGLES);
802 ASSERT_GL_NO_ERROR();
803
Martin Radev7e69f762017-07-27 14:54:13 +0300804 // Check that drawArrays does not generate an error when the number of views in the draw
805 // framebuffer is 1.
806 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300807 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
808 1, &viewportOffsets[0]);
Martin Radev7e69f762017-07-27 14:54:13 +0300809 glDrawArrays(GL_TRIANGLES, 0, 3);
810 EXPECT_GL_NO_ERROR();
811 }
812
813 glEndTransformFeedback();
814}
815
Martin Radevffe754b2017-07-31 10:38:07 +0300816// The test verifies that glDraw*:
817// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
818// greater than 1 and there is an active query for target GL_TIME_ELAPSED_EXT.
819// 2) does not generate any error if the number of views in the draw framebuffer is 1.
820TEST_P(MultiviewDrawValidationTest, ActiveTimeElapsedQuery)
821{
Yunchao He9550c602018-02-13 14:47:05 +0800822 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Jamie Madill3a256222018-12-08 09:56:39 -0500823 ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_EXT_disjoint_timer_query"));
Martin Radevffe754b2017-07-31 10:38:07 +0300824
Olli Etuaho44ae8992018-08-20 15:37:09 +0300825 ANGLE_GL_PROGRAM(dualViewProgram, kDualViewVSSource, kDualViewFSSource);
826
Martin Radevffe754b2017-07-31 10:38:07 +0300827 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Jamie Madill35cd7332018-12-02 12:03:33 -0500828 constexpr char kVS[] =
Martin Radevffe754b2017-07-31 10:38:07 +0300829 "#version 300 es\n"
830 "void main()\n"
831 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500832 constexpr char kFS[] =
Martin Radevffe754b2017-07-31 10:38:07 +0300833 "#version 300 es\n"
834 "precision mediump float;\n"
835 "void main()\n"
836 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500837 ANGLE_GL_PROGRAM(singleViewProgram, kVS, kFS);
Jamie Madill04c084d2018-08-08 15:49:28 -0400838 glUseProgram(singleViewProgram);
Martin Radevffe754b2017-07-31 10:38:07 +0300839
Olli Etuaho44ae8992018-08-20 15:37:09 +0300840 GLVertexArray vao;
841 GLBuffer vertexBuffer;
842 GLBuffer indexBuffer;
843 initVAO(vao, vertexBuffer, indexBuffer);
844
Martin Radevffe754b2017-07-31 10:38:07 +0300845 GLuint query = 0u;
846 glGenQueriesEXT(1, &query);
847 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
848
Olli Etuaho44ae8992018-08-20 15:37:09 +0300849 GLFramebuffer fbo;
850 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
851
852 GLTexture tex2D;
853 initOnePixelColorTexture2D(tex2D);
854
Martin Radevffe754b2017-07-31 10:38:07 +0300855 // Check first case.
856 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300857 glUseProgram(dualViewProgram);
858 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
859 2, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300860 glClear(GL_COLOR_BUFFER_BIT);
861 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radevffe754b2017-07-31 10:38:07 +0300862 glDrawArrays(GL_TRIANGLES, 0, 3);
863 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
864 }
865
866 // Check second case.
867 {
Jamie Madill04c084d2018-08-08 15:49:28 -0400868 glUseProgram(singleViewProgram);
Olli Etuaho44ae8992018-08-20 15:37:09 +0300869 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
870 1, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300871 glClear(GL_COLOR_BUFFER_BIT);
872 EXPECT_GL_NO_ERROR();
Martin Radevffe754b2017-07-31 10:38:07 +0300873 glDrawArrays(GL_TRIANGLES, 0, 3);
874 EXPECT_GL_NO_ERROR();
875 }
876
877 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
878 glDeleteQueries(1, &query);
Jamie Madill04c084d2018-08-08 15:49:28 -0400879
880 // Check starting a query after a successful draw.
881 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300882 glUseProgram(dualViewProgram);
883 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
884 2, &viewportOffsets[0]);
Jamie Madill04c084d2018-08-08 15:49:28 -0400885 glClear(GL_COLOR_BUFFER_BIT);
886 EXPECT_GL_NO_ERROR();
887 glDrawArrays(GL_TRIANGLES, 0, 3);
888 EXPECT_GL_NO_ERROR();
889
890 glGenQueriesEXT(1, &query);
891 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
892
893 glDrawArrays(GL_TRIANGLES, 0, 3);
894 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
895
896 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
897 glDrawArrays(GL_TRIANGLES, 0, 3);
898 EXPECT_GL_NO_ERROR();
899
900 glDeleteQueries(1, &query);
901 }
Martin Radevffe754b2017-07-31 10:38:07 +0300902}
903
Martin Radev8f276e22017-05-30 12:05:52 +0300904// The test checks that glDrawArrays can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300905TEST_P(MultiviewRenderDualViewTest, DrawArrays)
Martin Radev8f276e22017-05-30 12:05:52 +0300906{
Jamie Madill3a256222018-12-08 09:56:39 -0500907 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
908
Martin Radev8f276e22017-05-30 12:05:52 +0300909 drawQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
910 ASSERT_GL_NO_ERROR();
911
912 checkOutput();
913}
914
915// The test checks that glDrawElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300916TEST_P(MultiviewRenderDualViewTest, DrawElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300917{
Jamie Madill3a256222018-12-08 09:56:39 -0500918 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
919
Martin Radev8f276e22017-05-30 12:05:52 +0300920 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
921 ASSERT_GL_NO_ERROR();
922
923 checkOutput();
924}
925
926// The test checks that glDrawRangeElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300927TEST_P(MultiviewRenderDualViewTest, DrawRangeElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300928{
Jamie Madill3a256222018-12-08 09:56:39 -0500929 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
930
Martin Radev8f276e22017-05-30 12:05:52 +0300931 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true, true);
932 ASSERT_GL_NO_ERROR();
933
934 checkOutput();
935}
936
937// The test checks that glDrawArrays can be used to render into four views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300938TEST_P(MultiviewRenderTest, DrawArraysFourViews)
Martin Radev8f276e22017-05-30 12:05:52 +0300939{
Jamie Madill3a256222018-12-08 09:56:39 -0500940 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev8f276e22017-05-30 12:05:52 +0300941
Jamie Madill35cd7332018-12-02 12:03:33 -0500942 constexpr char kVS[] =
Martin Radev8f276e22017-05-30 12:05:52 +0300943 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300944 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300945 "layout(num_views = 4) in;\n"
946 "in vec4 vPosition;\n"
947 "void main()\n"
948 "{\n"
949 " if (gl_ViewID_OVR == 0u) {\n"
950 " gl_Position.x = vPosition.x*0.25 - 0.75;\n"
951 " } else if (gl_ViewID_OVR == 1u) {\n"
952 " gl_Position.x = vPosition.x*0.25 - 0.25;\n"
953 " } else if (gl_ViewID_OVR == 2u) {\n"
954 " gl_Position.x = vPosition.x*0.25 + 0.25;\n"
955 " } else {\n"
956 " gl_Position.x = vPosition.x*0.25 + 0.75;\n"
957 " }"
958 " gl_Position.yzw = vPosition.yzw;\n"
959 "}\n";
960
Jamie Madill35cd7332018-12-02 12:03:33 -0500961 constexpr char kFS[] =
Martin Radev8f276e22017-05-30 12:05:52 +0300962 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300963 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300964 "precision mediump float;\n"
965 "out vec4 col;\n"
966 "void main()\n"
967 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300968 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300969 "}\n";
970
Olli Etuaho4836acc2018-08-20 15:23:18 +0300971 updateFBOs(4, 1, 4);
Jamie Madill35cd7332018-12-02 12:03:33 -0500972 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev8f276e22017-05-30 12:05:52 +0300973
974 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
975 ASSERT_GL_NO_ERROR();
976
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300977 resolveMultisampledFBO();
Martin Radev8f276e22017-05-30 12:05:52 +0300978 for (int i = 0; i < 4; ++i)
979 {
980 for (int j = 0; j < 4; ++j)
981 {
Martin Radev8f276e22017-05-30 12:05:52 +0300982 if (i == j)
983 {
Martin Radev67a8a012017-09-08 13:03:52 +0300984 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300985 }
986 else
987 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300988 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300989 }
990 }
991 }
992 EXPECT_GL_NO_ERROR();
993}
994
995// The test checks that glDrawArraysInstanced can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300996TEST_P(MultiviewRenderTest, DrawArraysInstanced)
Martin Radev8f276e22017-05-30 12:05:52 +0300997{
Jamie Madill3a256222018-12-08 09:56:39 -0500998 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev8f276e22017-05-30 12:05:52 +0300999
Jamie Madill35cd7332018-12-02 12:03:33 -05001000 constexpr char kVS[] =
Martin Radev8f276e22017-05-30 12:05:52 +03001001 "#version 300 es\n"
1002 "#extension GL_OVR_multiview : require\n"
1003 "layout(num_views = 2) in;\n"
1004 "in vec4 vPosition;\n"
1005 "void main()\n"
1006 "{\n"
1007 " vec4 p = vPosition;\n"
1008 " if (gl_InstanceID == 1){\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001009 " p.y = p.y * 0.5 + 0.5;\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001010 " } else {\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001011 " p.y = p.y * 0.5 - 0.5;\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001012 " }\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001013 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x * 0.5 + 0.5 : p.x * 0.5 - 0.5);\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001014 " gl_Position.yzw = p.yzw;\n"
1015 "}\n";
1016
Jamie Madill35cd7332018-12-02 12:03:33 -05001017 constexpr char kFS[] =
Martin Radev8f276e22017-05-30 12:05:52 +03001018 "#version 300 es\n"
1019 "#extension GL_OVR_multiview : require\n"
1020 "precision mediump float;\n"
1021 "out vec4 col;\n"
1022 "void main()\n"
1023 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001024 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001025 "}\n";
1026
Martin Radev3c25ad02017-08-22 17:36:53 +03001027 const int kViewWidth = 2;
1028 const int kViewHeight = 2;
1029 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001030 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001031 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev8f276e22017-05-30 12:05:52 +03001032
Martin Radev67a8a012017-09-08 13:03:52 +03001033 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 2u);
Martin Radev8f276e22017-05-30 12:05:52 +03001034 ASSERT_GL_NO_ERROR();
1035
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001036 resolveMultisampledFBO();
1037
Martin Radev67a8a012017-09-08 13:03:52 +03001038 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {{{0, 255}, {0, 255}},
1039 {{255, 0}, {255, 0}}};
Martin Radev3c25ad02017-08-22 17:36:53 +03001040
1041 for (int view = 0; view < 2; ++view)
Martin Radev8f276e22017-05-30 12:05:52 +03001042 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001043 for (int y = 0; y < 2; ++y)
Martin Radev8f276e22017-05-30 12:05:52 +03001044 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001045 for (int x = 0; x < 2; ++x)
1046 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001047 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][y][x], 0,
1048 expectedGreenChannel[view][y][x]),
Martin Radev3c25ad02017-08-22 17:36:53 +03001049 GetViewColor(x, y, view));
1050 }
Martin Radev8f276e22017-05-30 12:05:52 +03001051 }
1052 }
1053}
1054
Martin Radev553590a2017-07-31 16:40:39 +03001055// The test verifies that the attribute divisor is correctly adjusted when drawing with a multi-view
1056// program. The test draws 4 instances of a quad each of which covers a single pixel. The x and y
1057// offset of each quad are passed as separate attributes which are indexed based on the
1058// corresponding attribute divisors. A divisor of 1 is used for the y offset to have all quads
1059// drawn vertically next to each other. A divisor of 3 is used for the x offset to have the last
1060// quad offsetted by one pixel to the right. Note that the number of views is divisible by 1, but
1061// not by 3.
Martin Radev3c25ad02017-08-22 17:36:53 +03001062TEST_P(MultiviewRenderTest, AttribDivisor)
Martin Radev553590a2017-07-31 16:40:39 +03001063{
Jamie Madill3a256222018-12-08 09:56:39 -05001064 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev553590a2017-07-31 16:40:39 +03001065
Corentin Wallez02cd1522018-08-22 13:46:21 +02001066 // Looks like an incorrect D3D debug layer message is generated on Windows AMD and NVIDIA.
Olli Etuaho44ae8992018-08-20 15:37:09 +03001067 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001068 if (IsWindows() && IsD3D11())
1069 {
1070 ignoreD3D11SDKLayersWarnings();
1071 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001072
Jamie Madill35cd7332018-12-02 12:03:33 -05001073 constexpr char kVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001074 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001075 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001076 "layout(num_views = 2) in;\n"
1077 "in vec3 vPosition;\n"
1078 "in float offsetX;\n"
1079 "in float offsetY;\n"
1080 "void main()\n"
1081 "{\n"
1082 " vec4 p = vec4(vPosition, 1.);\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001083 " p.xy = p.xy * 0.25 - vec2(0.75) + vec2(offsetX, offsetY);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001084 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x : p.x + 1.0);\n"
1085 " gl_Position.yzw = p.yzw;\n"
1086 "}\n";
1087
Jamie Madill35cd7332018-12-02 12:03:33 -05001088 constexpr char kFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001089 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001090 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001091 "precision mediump float;\n"
1092 "out vec4 col;\n"
1093 "void main()\n"
1094 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001095 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001096 "}\n";
Martin Radev3c25ad02017-08-22 17:36:53 +03001097
1098 const int kViewWidth = 4;
1099 const int kViewHeight = 4;
1100 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001101 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001102 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev553590a2017-07-31 16:40:39 +03001103
1104 GLBuffer xOffsetVBO;
1105 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1106 const GLfloat xOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.0f};
1107 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, xOffsetData, GL_STATIC_DRAW);
1108 GLint xOffsetLoc = glGetAttribLocation(program, "offsetX");
1109 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1110 glVertexAttribDivisor(xOffsetLoc, 3);
1111 glEnableVertexAttribArray(xOffsetLoc);
1112
1113 GLBuffer yOffsetVBO;
1114 glBindBuffer(GL_ARRAY_BUFFER, yOffsetVBO);
1115 const GLfloat yOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1116 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, yOffsetData, GL_STATIC_DRAW);
1117 GLint yOffsetLoc = glGetAttribLocation(program, "offsetY");
1118 glVertexAttribDivisor(yOffsetLoc, 1);
1119 glVertexAttribPointer(yOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1120 glEnableVertexAttribArray(yOffsetLoc);
1121
Martin Radev67a8a012017-09-08 13:03:52 +03001122 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev553590a2017-07-31 16:40:39 +03001123 ASSERT_GL_NO_ERROR();
1124
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001125 resolveMultisampledFBO();
1126
Martin Radev67a8a012017-09-08 13:03:52 +03001127 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001128 {{255, 0, 0, 0}, {255, 0, 0, 0}, {255, 0, 0, 0}, {0, 255, 0, 0}},
1129 {{0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 0, 255}}};
1130 for (int view = 0; view < 2; ++view)
Martin Radev553590a2017-07-31 16:40:39 +03001131 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001132 for (int row = 0; row < 4; ++row)
Martin Radev553590a2017-07-31 16:40:39 +03001133 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001134 for (int col = 0; col < 4; ++col)
1135 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001136 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][row][col], 0,
1137 expectedGreenChannel[view][row][col]),
Martin Radev3c25ad02017-08-22 17:36:53 +03001138 GetViewColor(col, row, view));
1139 }
Martin Radev553590a2017-07-31 16:40:39 +03001140 }
1141 }
1142}
1143
1144// Test that different sequences of vertexAttribDivisor, useProgram and bindVertexArray in a
1145// multi-view context propagate the correct divisor to the driver.
Martin Radev3c25ad02017-08-22 17:36:53 +03001146TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
Martin Radev553590a2017-07-31 16:40:39 +03001147{
Jamie Madill3a256222018-12-08 09:56:39 -05001148 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev553590a2017-07-31 16:40:39 +03001149
Olli Etuaho4836acc2018-08-20 15:23:18 +03001150 updateFBOs(1, 1, 2);
Martin Radev553590a2017-07-31 16:40:39 +03001151
1152 // Create multiview program.
Jamie Madill35cd7332018-12-02 12:03:33 -05001153 constexpr char kVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001154 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001155 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001156 "layout(num_views = 2) in;\n"
1157 "layout(location = 0) in vec2 vPosition;\n"
1158 "layout(location = 1) in float offsetX;\n"
1159 "void main()\n"
1160 "{\n"
1161 " vec4 p = vec4(vPosition, 0.0, 1.0);\n"
1162 " p.x += offsetX;\n"
1163 " gl_Position = p;\n"
1164 "}\n";
1165
Jamie Madill35cd7332018-12-02 12:03:33 -05001166 constexpr char kFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001167 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001168 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001169 "precision mediump float;\n"
1170 "out vec4 col;\n"
1171 "void main()\n"
1172 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001173 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001174 "}\n";
1175
Jamie Madill35cd7332018-12-02 12:03:33 -05001176 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev553590a2017-07-31 16:40:39 +03001177
Jamie Madill35cd7332018-12-02 12:03:33 -05001178 constexpr char kDummyVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001179 "#version 300 es\n"
1180 "layout(location = 0) in vec2 vPosition;\n"
1181 "layout(location = 1) in float offsetX;\n"
1182 "void main()\n"
1183 "{\n"
1184 " gl_Position = vec4(vPosition, 0.0, 1.0);\n"
1185 "}\n";
1186
Jamie Madill35cd7332018-12-02 12:03:33 -05001187 constexpr char kDummyFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001188 "#version 300 es\n"
1189 "precision mediump float;\n"
1190 "out vec4 col;\n"
1191 "void main()\n"
1192 "{\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001193 " col = vec4(0,0,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001194 "}\n";
1195
Jamie Madill35cd7332018-12-02 12:03:33 -05001196 ANGLE_GL_PROGRAM(dummyProgram, kDummyVS, kDummyFS);
Martin Radev553590a2017-07-31 16:40:39 +03001197
1198 GLBuffer xOffsetVBO;
1199 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1200 const GLfloat xOffsetData[12] = {0.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f,
1201 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f};
1202 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 12, xOffsetData, GL_STATIC_DRAW);
1203
1204 GLBuffer vertexVBO;
1205 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1206 Vector2 kQuadVertices[6] = {Vector2(-1.f, -1.f), Vector2(1.f, -1.f), Vector2(1.f, 1.f),
1207 Vector2(-1.f, -1.f), Vector2(1.f, 1.f), Vector2(-1.f, 1.f)};
1208 glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
1209
1210 GLVertexArray vao[2];
1211 for (size_t i = 0u; i < 2u; ++i)
1212 {
1213 glBindVertexArray(vao[i]);
1214
1215 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1216 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
1217 glEnableVertexAttribArray(0);
1218
1219 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1220 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
1221 glEnableVertexAttribArray(1);
1222 }
1223 ASSERT_GL_NO_ERROR();
1224
1225 glViewport(0, 0, 1, 1);
1226 glScissor(0, 0, 1, 1);
Martin Radeveef80e42017-08-11 14:44:57 +03001227 glEnable(GL_SCISSOR_TEST);
Martin Radev61bd9992017-08-11 13:10:55 +03001228 glClearColor(0, 0, 0, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001229
1230 // Clear the buffers, propagate divisor to the driver, bind the vao and keep it active.
1231 // It is necessary to call draw, so that the divisor is propagated and to guarantee that dirty
1232 // bits are cleared.
1233 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001234 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1235 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001236 glBindVertexArray(vao[0]);
1237 glVertexAttribDivisor(1, 0);
1238 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1239 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001240 ASSERT_GL_NO_ERROR();
1241
1242 // Check that vertexAttribDivisor uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001243 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001244 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001245 glUseProgram(program);
1246 glVertexAttribDivisor(1, 1);
1247 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001248
1249 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001250 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1251 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001252
1253 // Clear the buffers and propagate divisor to the driver.
1254 // We keep the vao active and propagate the divisor to guarantee that there are no unresolved
1255 // dirty bits when useProgram is called.
1256 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001257 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1258 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001259 glVertexAttribDivisor(1, 1);
1260 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1261 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001262 ASSERT_GL_NO_ERROR();
1263
1264 // Check that useProgram uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001265 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001266 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001267 glUseProgram(program);
1268 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001269
1270 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001271 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1272 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001273
1274 // We go through similar steps as before.
1275 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001276 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1277 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001278 glVertexAttribDivisor(1, 1);
1279 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1280 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001281 ASSERT_GL_NO_ERROR();
1282
1283 // Check that bindVertexArray uses the number of views to update the divisor.
1284 {
1285 // Call useProgram with vao[1] being active to guarantee that useProgram will adjust the
1286 // divisor for vao[1] only.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001287 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001288 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001289 glBindVertexArray(vao[1]);
1290 glUseProgram(program);
1291 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001292 glBindVertexArray(0);
1293 ASSERT_GL_NO_ERROR();
1294 }
1295 // Bind vao[0] after useProgram is called to ensure that bindVertexArray is the call which
1296 // adjusts the divisor.
Martin Radevda8e2572017-09-12 17:21:16 +03001297 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001298 glBindVertexArray(vao[0]);
1299 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001300
1301 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001302 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1303 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001304}
1305
Martin Radev0d671c92017-08-10 16:41:52 +03001306// Test that no fragments pass the occlusion query for a multi-view vertex shader which always
1307// transforms geometry to be outside of the clip region.
Martin Radev3c25ad02017-08-22 17:36:53 +03001308TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryNothingVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001309{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001310 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1311 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001312
Jamie Madill35cd7332018-12-02 12:03:33 -05001313 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001314 "#version 300 es\n"
1315 "#extension GL_OVR_multiview : require\n"
1316 "layout(num_views = 2) in;\n"
1317 "in vec3 vPosition;\n"
1318 "void main()\n"
1319 "{\n"
1320 " gl_Position.x = 2.0;\n"
1321 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1322 "}\n";
1323
Jamie Madill35cd7332018-12-02 12:03:33 -05001324 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001325 "#version 300 es\n"
1326 "#extension GL_OVR_multiview : require\n"
1327 "precision mediump float;\n"
1328 "out vec4 col;\n"
1329 "void main()\n"
1330 "{\n"
1331 " col = vec4(1,0,0,0);\n"
1332 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001333 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001334 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001335
1336 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1337 ASSERT_GL_NO_ERROR();
1338 EXPECT_GL_FALSE(result);
1339}
1340
1341// Test that there are fragments passing the occlusion query if only view 0 can produce
1342// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001343TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyLeftVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001344{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001345 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1346 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001347
Jamie Madill35cd7332018-12-02 12:03:33 -05001348 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001349 "#version 300 es\n"
1350 "#extension GL_OVR_multiview : require\n"
1351 "layout(num_views = 2) in;\n"
1352 "in vec3 vPosition;\n"
1353 "void main()\n"
1354 "{\n"
1355 " gl_Position.x = gl_ViewID_OVR == 0u ? vPosition.x : 2.0;\n"
1356 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1357 "}\n";
1358
Jamie Madill35cd7332018-12-02 12:03:33 -05001359 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001360 "#version 300 es\n"
1361 "#extension GL_OVR_multiview : require\n"
1362 "precision mediump float;\n"
1363 "out vec4 col;\n"
1364 "void main()\n"
1365 "{\n"
1366 " col = vec4(1,0,0,0);\n"
1367 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001368 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001369 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001370
1371 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1372 ASSERT_GL_NO_ERROR();
1373 EXPECT_GL_TRUE(result);
1374}
1375
1376// Test that there are fragments passing the occlusion query if only view 1 can produce
1377// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001378TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyRightVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001379{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001380 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1381 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001382
Jamie Madill35cd7332018-12-02 12:03:33 -05001383 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001384 "#version 300 es\n"
1385 "#extension GL_OVR_multiview : require\n"
1386 "layout(num_views = 2) in;\n"
1387 "in vec3 vPosition;\n"
1388 "void main()\n"
1389 "{\n"
1390 " gl_Position.x = gl_ViewID_OVR == 1u ? vPosition.x : 2.0;\n"
1391 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1392 "}\n";
1393
Jamie Madill35cd7332018-12-02 12:03:33 -05001394 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001395 "#version 300 es\n"
1396 "#extension GL_OVR_multiview : require\n"
1397 "precision mediump float;\n"
1398 "out vec4 col;\n"
1399 "void main()\n"
1400 "{\n"
1401 " col = vec4(1,0,0,0);\n"
1402 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001403 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001404 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001405
1406 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1407 ASSERT_GL_NO_ERROR();
1408 EXPECT_GL_TRUE(result);
1409}
1410
Martin Radev41ac68e2017-06-06 12:16:58 +03001411// Test that a simple multi-view program which doesn't use gl_ViewID_OVR in neither VS nor FS
1412// compiles and links without an error.
1413TEST_P(MultiviewProgramGenerationTest, SimpleProgram)
1414{
1415 if (!requestMultiviewExtension())
1416 {
1417 return;
1418 }
1419
Jamie Madill35cd7332018-12-02 12:03:33 -05001420 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001421 "#version 300 es\n"
1422 "#extension GL_OVR_multiview : require\n"
1423 "layout(num_views = 2) in;\n"
1424 "void main()\n"
1425 "{\n"
1426 "}\n";
1427
Jamie Madill35cd7332018-12-02 12:03:33 -05001428 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001429 "#version 300 es\n"
1430 "#extension GL_OVR_multiview : require\n"
1431 "precision mediump float;\n"
1432 "void main()\n"
1433 "{\n"
1434 "}\n";
1435
Jamie Madill35cd7332018-12-02 12:03:33 -05001436 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001437 glUseProgram(program);
1438
1439 EXPECT_GL_NO_ERROR();
1440}
1441
1442// Test that a simple multi-view program which uses gl_ViewID_OVR only in VS compiles and links
1443// without an error.
1444TEST_P(MultiviewProgramGenerationTest, UseViewIDInVertexShader)
1445{
1446 if (!requestMultiviewExtension())
1447 {
1448 return;
1449 }
1450
Jamie Madill35cd7332018-12-02 12:03:33 -05001451 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001452 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001453 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001454 "layout(num_views = 2) in;\n"
1455 "void main()\n"
1456 "{\n"
1457 " if (gl_ViewID_OVR == 0u) {\n"
1458 " gl_Position = vec4(1,0,0,1);\n"
1459 " } else {\n"
1460 " gl_Position = vec4(-1,0,0,1);\n"
1461 " }\n"
1462 "}\n";
1463
Jamie Madill35cd7332018-12-02 12:03:33 -05001464 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001465 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001466 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001467 "precision mediump float;\n"
1468 "void main()\n"
1469 "{\n"
1470 "}\n";
1471
Jamie Madill35cd7332018-12-02 12:03:33 -05001472 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001473 glUseProgram(program);
1474
1475 EXPECT_GL_NO_ERROR();
1476}
1477
1478// Test that a simple multi-view program which uses gl_ViewID_OVR only in FS compiles and links
1479// without an error.
1480TEST_P(MultiviewProgramGenerationTest, UseViewIDInFragmentShader)
1481{
1482 if (!requestMultiviewExtension())
1483 {
1484 return;
1485 }
1486
Jamie Madill35cd7332018-12-02 12:03:33 -05001487 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001488 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001489 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001490 "layout(num_views = 2) in;\n"
1491 "void main()\n"
1492 "{\n"
1493 "}\n";
1494
Jamie Madill35cd7332018-12-02 12:03:33 -05001495 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001496 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001497 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001498 "precision mediump float;\n"
1499 "out vec4 col;\n"
1500 "void main()\n"
1501 "{\n"
1502 " if (gl_ViewID_OVR == 0u) {\n"
1503 " col = vec4(1,0,0,1);\n"
1504 " } else {\n"
1505 " col = vec4(-1,0,0,1);\n"
1506 " }\n"
1507 "}\n";
1508
Jamie Madill35cd7332018-12-02 12:03:33 -05001509 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001510 glUseProgram(program);
1511
1512 EXPECT_GL_NO_ERROR();
1513}
1514
Martin Radev61bd9992017-08-11 13:10:55 +03001515// The test checks that GL_POINTS is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001516TEST_P(MultiviewRenderPrimitiveTest, Points)
Martin Radev61bd9992017-08-11 13:10:55 +03001517{
1518 if (!requestMultiviewExtension())
1519 {
1520 return;
1521 }
1522
Geoff Lang25858162017-11-06 11:25:58 -05001523 // Test failing on P400 graphics card (anglebug.com/2228)
1524 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1525
Jamie Madill35cd7332018-12-02 12:03:33 -05001526 constexpr char kVS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001527 "#version 300 es\n"
1528 "#extension GL_OVR_multiview : require\n"
1529 "layout(num_views = 2) in;\n"
1530 "layout(location=0) in vec2 vPosition;\n"
1531 "void main()\n"
1532 "{\n"
1533 " gl_PointSize = 1.0;\n"
1534 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1535 "}\n";
1536
Jamie Madill35cd7332018-12-02 12:03:33 -05001537 constexpr char kFS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001538 "#version 300 es\n"
1539 "#extension GL_OVR_multiview : require\n"
1540 "precision mediump float;\n"
1541 "out vec4 col;\n"
1542 "void main()\n"
1543 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001544 " col = vec4(0,1,0,1);\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001545 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001546 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev61bd9992017-08-11 13:10:55 +03001547 glUseProgram(program);
1548
Martin Radev3c25ad02017-08-22 17:36:53 +03001549 const int kViewWidth = 4;
1550 const int kViewHeight = 2;
1551 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001552 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001553
1554 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 1)};
1555 std::vector<Vector2> vertexDataInClipSpace =
1556 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1557 setupGeometry(vertexDataInClipSpace);
1558
1559 glDrawArrays(GL_POINTS, 0, 2);
1560
Martin Radev67a8a012017-09-08 13:03:52 +03001561 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001562 {{255, 0, 0, 0}, {0, 0, 0, 255}}, {{255, 0, 0, 0}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001563 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001564}
1565
1566// The test checks that GL_LINES is correctly rendered.
1567// The behavior of this test is not guaranteed by the spec:
1568// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1569// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1570// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1571// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001572TEST_P(MultiviewRenderPrimitiveTest, Lines)
Martin Radev61bd9992017-08-11 13:10:55 +03001573{
1574 if (!requestMultiviewExtension())
1575 {
1576 return;
1577 }
1578
Martin Radevced5c862017-08-17 16:05:29 +03001579 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001580 ASSERT_NE(program, 0u);
1581 glUseProgram(program);
1582 ASSERT_GL_NO_ERROR();
1583
Martin Radev3c25ad02017-08-22 17:36:53 +03001584 const int kViewWidth = 4;
1585 const int kViewHeight = 2;
1586 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001587 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001588
1589 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(4, 0)};
1590 std::vector<Vector2> vertexDataInClipSpace =
1591 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1592 setupGeometry(vertexDataInClipSpace);
1593
1594 glDrawArrays(GL_LINES, 0, 2);
1595
Martin Radev67a8a012017-09-08 13:03:52 +03001596 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001597 {{255, 255, 255, 255}, {0, 0, 0, 0}}, {{255, 255, 255, 255}, {0, 0, 0, 0}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001598 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001599
1600 glDeleteProgram(program);
1601}
1602
1603// The test checks that GL_LINE_STRIP is correctly rendered.
1604// The behavior of this test is not guaranteed by the spec:
1605// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1606// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1607// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1608// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001609TEST_P(MultiviewRenderPrimitiveTest, LineStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001610{
1611 if (!requestMultiviewExtension())
1612 {
1613 return;
1614 }
1615
Martin Radevced5c862017-08-17 16:05:29 +03001616 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001617 ASSERT_NE(program, 0u);
1618 glUseProgram(program);
1619 ASSERT_GL_NO_ERROR();
1620
Martin Radev3c25ad02017-08-22 17:36:53 +03001621 const int kViewWidth = 4;
1622 const int kViewHeight = 2;
1623 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001624 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001625
1626 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 2)};
1627 std::vector<Vector2> vertexDataInClipSpace =
1628 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1629 setupGeometry(vertexDataInClipSpace);
1630
1631 glDrawArrays(GL_LINE_STRIP, 0, 3);
1632
Martin Radev67a8a012017-09-08 13:03:52 +03001633 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001634 {{255, 255, 255, 255}, {0, 0, 0, 255}}, {{255, 255, 255, 255}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001635 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001636
1637 glDeleteProgram(program);
1638}
1639
1640// The test checks that GL_LINE_LOOP is correctly rendered.
1641// The behavior of this test is not guaranteed by the spec:
1642// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1643// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1644// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1645// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001646TEST_P(MultiviewRenderPrimitiveTest, LineLoop)
Martin Radev61bd9992017-08-11 13:10:55 +03001647{
1648 if (!requestMultiviewExtension())
1649 {
1650 return;
1651 }
1652
Martin Radevced5c862017-08-17 16:05:29 +03001653 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001654 ASSERT_NE(program, 0u);
1655 glUseProgram(program);
1656 ASSERT_GL_NO_ERROR();
1657
Martin Radev3c25ad02017-08-22 17:36:53 +03001658 const int kViewWidth = 4;
1659 const int kViewHeight = 4;
1660 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001661 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001662
1663 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 3),
1664 Vector2I(0, 3)};
1665 std::vector<Vector2> vertexDataInClipSpace =
1666 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 4);
1667 setupGeometry(vertexDataInClipSpace);
1668
1669 glDrawArrays(GL_LINE_LOOP, 0, 4);
1670
Martin Radev67a8a012017-09-08 13:03:52 +03001671 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001672 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}},
1673 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001674 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001675
1676 glDeleteProgram(program);
1677}
1678
1679// The test checks that GL_TRIANGLE_STRIP is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001680TEST_P(MultiviewRenderPrimitiveTest, TriangleStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001681{
1682 if (!requestMultiviewExtension())
1683 {
1684 return;
1685 }
1686
Martin Radevced5c862017-08-17 16:05:29 +03001687 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001688 ASSERT_NE(program, 0u);
1689 glUseProgram(program);
1690 ASSERT_GL_NO_ERROR();
1691
1692 std::vector<Vector2> vertexDataInClipSpace = {Vector2(1.0f, 0.0f), Vector2(0.0f, 0.0f),
1693 Vector2(1.0f, 1.0f), Vector2(0.0f, 1.0f)};
1694 setupGeometry(vertexDataInClipSpace);
1695
Martin Radev3c25ad02017-08-22 17:36:53 +03001696 const int kViewWidth = 2;
1697 const int kViewHeight = 2;
1698 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001699 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001700
1701 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1702
Martin Radev67a8a012017-09-08 13:03:52 +03001703 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1704 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1705 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001706
1707 glDeleteProgram(program);
1708}
1709
1710// The test checks that GL_TRIANGLE_FAN is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001711TEST_P(MultiviewRenderPrimitiveTest, TriangleFan)
Martin Radev61bd9992017-08-11 13:10:55 +03001712{
1713 if (!requestMultiviewExtension())
1714 {
1715 return;
1716 }
1717
Martin Radevced5c862017-08-17 16:05:29 +03001718 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001719 ASSERT_NE(program, 0u);
1720 glUseProgram(program);
1721 ASSERT_GL_NO_ERROR();
1722
1723 std::vector<Vector2> vertexDataInClipSpace = {Vector2(0.0f, 0.0f), Vector2(0.0f, 1.0f),
1724 Vector2(1.0f, 1.0f), Vector2(1.0f, 0.0f)};
1725 setupGeometry(vertexDataInClipSpace);
1726
Martin Radev3c25ad02017-08-22 17:36:53 +03001727 const int kViewWidth = 2;
1728 const int kViewHeight = 2;
1729 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001730 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001731
1732 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1733
Martin Radev67a8a012017-09-08 13:03:52 +03001734 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1735 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1736 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001737
1738 glDeleteProgram(program);
1739}
1740
1741// Test that rendering enlarged points and lines does not leak fragments outside of the views'
1742// bounds. The test does not rely on the actual line width being greater than 1.0.
Martin Radev3c25ad02017-08-22 17:36:53 +03001743TEST_P(MultiviewSideBySideRenderTest, NoLeakingFragments)
Martin Radev61bd9992017-08-11 13:10:55 +03001744{
1745 if (!requestMultiviewExtension())
1746 {
1747 return;
1748 }
1749
Olli Etuaho9259fd02018-08-22 12:12:00 +03001750 GLTexture colorTexture;
Martin Radev61bd9992017-08-11 13:10:55 +03001751
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001752 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0, 2, 1, 2,
Olli Etuaho9259fd02018-08-22 12:12:00 +03001753 colorTexture, 0u, 0u);
1754
1755 GLFramebuffer drawFramebuffer;
1756 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFramebuffer);
Martin Radev61bd9992017-08-11 13:10:55 +03001757 GLint viewportOffsets[4] = {1, 0, 3, 0};
1758 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
Olli Etuaho9259fd02018-08-22 12:12:00 +03001759 colorTexture, 0, 2, &viewportOffsets[0]);
1760
1761 GLFramebuffer readFramebuffer;
1762 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
1763 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
1764 0);
1765
1766 ASSERT_GL_NO_ERROR();
Martin Radev61bd9992017-08-11 13:10:55 +03001767
1768 glViewport(0, 0, 1, 1);
1769 glScissor(0, 0, 1, 1);
1770 glEnable(GL_SCISSOR_TEST);
1771
Jamie Madill35cd7332018-12-02 12:03:33 -05001772 constexpr char kVS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001773 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001774 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001775 "layout(num_views = 2) in;\n"
1776 "layout(location=0) in vec2 vPosition;\n"
1777 "void main()\n"
1778 "{\n"
1779 " gl_PointSize = 10.0;\n"
1780 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1781 "}\n";
1782
Jamie Madill35cd7332018-12-02 12:03:33 -05001783 constexpr char kFS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001784 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001785 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001786 "precision mediump float;\n"
1787 "out vec4 col;\n"
1788 "void main()\n"
1789 "{\n"
1790 " if (gl_ViewID_OVR == 0u) {\n"
1791 " col = vec4(1,0,0,1);\n"
1792 " } else {\n"
1793 " col = vec4(0,1,0,1);\n"
1794 " }\n"
1795 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001796 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev61bd9992017-08-11 13:10:55 +03001797 glUseProgram(program);
1798
1799 const std::vector<Vector2I> &windowCoordinates = {Vector2I(0, 0), Vector2I(2, 0)};
1800 const std::vector<Vector2> &vertexDataInClipSpace =
1801 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 1, 1);
Martin Radev3c25ad02017-08-22 17:36:53 +03001802
1803 GLBuffer vbo;
1804 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1805 glBufferData(GL_ARRAY_BUFFER, vertexDataInClipSpace.size() * sizeof(Vector2),
1806 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
1807 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -05001808 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +03001809
1810 // Test rendering points.
1811 {
1812 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1813 glDrawArrays(GL_POINTS, 0, 2);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001814 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001815 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001816 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001817 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1818 }
1819
1820 // Test rendering lines.
1821 {
1822 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1823 glLineWidth(10.f);
1824 glDrawArrays(GL_LINES, 0, 2);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001825 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001826 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001827 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001828 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1829 }
1830}
1831
Martin Radev0abb7a22017-08-28 15:34:45 +03001832// Verify that re-linking a program adjusts the attribute divisor.
1833// The test uses instacing to draw for each view a strips of two red quads and two blue quads next
1834// to each other. The quads' position and color depend on the corresponding attribute divisors.
1835TEST_P(MultiviewRenderTest, ProgramRelinkUpdatesAttribDivisor)
1836{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001837 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev0abb7a22017-08-28 15:34:45 +03001838 {
1839 return;
1840 }
1841
Corentin Wallez02cd1522018-08-22 13:46:21 +02001842 // Looks like an incorrect D3D debug layer message is generated on Windows AMD and NVIDIA.
Olli Etuaho44ae8992018-08-20 15:37:09 +03001843 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001844 if (IsWindows() && IsD3D11())
1845 {
1846 ignoreD3D11SDKLayersWarnings();
1847 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001848
Martin Radev0abb7a22017-08-28 15:34:45 +03001849 const int kViewWidth = 4;
1850 const int kViewHeight = 1;
1851 const int kNumViews = 2;
1852
Jamie Madill35cd7332018-12-02 12:03:33 -05001853 constexpr char kFS[] =
Martin Radev0abb7a22017-08-28 15:34:45 +03001854 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001855 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001856 "precision mediump float;\n"
1857 "in vec4 oColor;\n"
1858 "out vec4 col;\n"
1859 "void main()\n"
1860 "{\n"
1861 " col = oColor;\n"
1862 "}\n";
1863
1864 auto generateVertexShaderSource = [](int numViews) -> std::string {
1865 std::string source =
1866 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001867 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001868 "layout(num_views = " +
1869 ToString(numViews) +
1870 ") in;\n"
1871 "in vec3 vPosition;\n"
1872 "in float vOffsetX;\n"
1873 "in vec4 vColor;\n"
1874 "out vec4 oColor;\n"
1875 "void main()\n"
1876 "{\n"
1877 " vec4 p = vec4(vPosition, 1.);\n"
1878 " p.x = p.x * 0.25 - 0.75 + vOffsetX;\n"
1879 " oColor = vColor;\n"
1880 " gl_Position = p;\n"
1881 "}\n";
1882 return source;
1883 };
1884
1885 std::string vsSource = generateVertexShaderSource(kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001886 ANGLE_GL_PROGRAM(program, vsSource.c_str(), kFS);
Martin Radev0abb7a22017-08-28 15:34:45 +03001887 glUseProgram(program);
1888
1889 GLint positionLoc;
1890 GLBuffer xOffsetVBO;
1891 GLint xOffsetLoc;
1892 GLBuffer colorVBO;
1893 GLint colorLoc;
1894
1895 {
1896 // Initialize buffers and setup attributes.
1897 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1898 const GLfloat kXOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1899 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, kXOffsetData, GL_STATIC_DRAW);
1900 xOffsetLoc = glGetAttribLocation(program, "vOffsetX");
1901 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1902 glVertexAttribDivisor(xOffsetLoc, 1);
1903 glEnableVertexAttribArray(xOffsetLoc);
1904
1905 glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
1906 const GLColor kColors[2] = {GLColor::red, GLColor::blue};
1907 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 2, kColors, GL_STATIC_DRAW);
1908 colorLoc = glGetAttribLocation(program, "vColor");
1909 glVertexAttribDivisor(colorLoc, 2);
1910 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1911 glEnableVertexAttribArray(colorLoc);
1912
1913 positionLoc = glGetAttribLocation(program, "vPosition");
1914 }
1915
1916 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03001917 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001918
Martin Radev67a8a012017-09-08 13:03:52 +03001919 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001920 ASSERT_GL_NO_ERROR();
1921
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001922 resolveMultisampledFBO();
Martin Radev0abb7a22017-08-28 15:34:45 +03001923 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
1924 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, 0));
1925 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, 0));
1926 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, 0));
1927 }
1928
1929 {
1930 const int kNewNumViews = 3;
1931 vsSource = generateVertexShaderSource(kNewNumViews);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001932 updateFBOs(kViewWidth, kViewHeight, kNewNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001933
Jamie Madill35cd7332018-12-02 12:03:33 -05001934 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource.c_str());
Martin Radev0abb7a22017-08-28 15:34:45 +03001935 ASSERT_NE(0u, vs);
Jamie Madill35cd7332018-12-02 12:03:33 -05001936 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
Martin Radev0abb7a22017-08-28 15:34:45 +03001937 ASSERT_NE(0u, fs);
1938
1939 GLint numAttachedShaders = 0;
1940 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
1941
1942 GLuint attachedShaders[2] = {0u};
1943 glGetAttachedShaders(program, numAttachedShaders, nullptr, attachedShaders);
1944 for (int i = 0; i < 2; ++i)
1945 {
1946 glDetachShader(program, attachedShaders[i]);
1947 }
1948
1949 glAttachShader(program, vs);
1950 glDeleteShader(vs);
1951
1952 glAttachShader(program, fs);
1953 glDeleteShader(fs);
1954
1955 glBindAttribLocation(program, positionLoc, "vPosition");
1956 glBindAttribLocation(program, xOffsetLoc, "vOffsetX");
1957 glBindAttribLocation(program, colorLoc, "vColor");
1958
1959 glLinkProgram(program);
1960
Martin Radev67a8a012017-09-08 13:03:52 +03001961 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001962 ASSERT_GL_NO_ERROR();
1963
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001964 resolveMultisampledFBO();
Martin Radev0abb7a22017-08-28 15:34:45 +03001965 for (int i = 0; i < kNewNumViews; ++i)
1966 {
1967 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, i));
1968 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, i));
1969 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, i));
1970 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, i));
1971 }
1972 }
1973}
1974
Martin Radevced5c862017-08-17 16:05:29 +03001975// Test that useProgram applies the number of views in computing the final value of the attribute
1976// divisor.
1977TEST_P(MultiviewRenderTest, DivisorUpdatedOnProgramChange)
1978{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001979 if (!requestMultiviewExtension(isMultisampled()))
Martin Radevced5c862017-08-17 16:05:29 +03001980 {
1981 return;
1982 }
1983
Geoff Lang25858162017-11-06 11:25:58 -05001984 // Test failing on P400 graphics card (anglebug.com/2228)
1985 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1986
Olli Etuaho44ae8992018-08-20 15:37:09 +03001987 // Looks like an incorrect D3D debug layer message is generated on Windows / AMD.
1988 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001989 if (IsWindows() && IsD3D11())
1990 {
1991 ignoreD3D11SDKLayersWarnings();
1992 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001993
Martin Radevced5c862017-08-17 16:05:29 +03001994 GLVertexArray vao;
1995 glBindVertexArray(vao);
1996 GLBuffer vbo;
1997 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1998 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(1, 0), Vector2I(2, 0),
1999 Vector2I(3, 0)};
2000 std::vector<Vector2> vertexDataInClipSpace =
2001 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 1);
2002 // Fill with x positions so that the resulting clip space coordinate fails the clip test.
2003 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2) * vertexDataInClipSpace.size(),
2004 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
2005 glEnableVertexAttribArray(0);
2006 glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, nullptr);
2007 glVertexAttribDivisor(0, 1);
2008 ASSERT_GL_NO_ERROR();
2009
2010 // Create a program and fbo with N views and draw N instances of a point horizontally.
2011 for (int numViews = 2; numViews <= 4; ++numViews)
2012 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03002013 updateFBOs(4, 1, numViews);
Martin Radevced5c862017-08-17 16:05:29 +03002014 ASSERT_GL_NO_ERROR();
2015
2016 GLuint program = CreateSimplePassthroughProgram(numViews);
2017 ASSERT_NE(program, 0u);
2018 glUseProgram(program);
2019 ASSERT_GL_NO_ERROR();
2020
2021 glDrawArraysInstanced(GL_POINTS, 0, 1, numViews);
2022
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002023 resolveMultisampledFBO();
Martin Radevced5c862017-08-17 16:05:29 +03002024 for (int view = 0; view < numViews; ++view)
2025 {
2026 for (int j = 0; j < numViews; ++j)
2027 {
Martin Radev67a8a012017-09-08 13:03:52 +03002028 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03002029 }
2030 for (int j = numViews; j < 4; ++j)
2031 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03002032 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03002033 }
2034 }
2035
2036 glDeleteProgram(program);
2037 }
2038}
2039
Martin Radev72b4e1e2017-08-31 15:42:56 +03002040// The test checks that gl_ViewID_OVR is correctly propagated to the fragment shader.
2041TEST_P(MultiviewRenderTest, SelectColorBasedOnViewIDOVR)
2042{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002043 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev72b4e1e2017-08-31 15:42:56 +03002044 {
2045 return;
2046 }
2047
Jamie Madill35cd7332018-12-02 12:03:33 -05002048 constexpr char kVS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002049 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002050 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002051 "layout(num_views = 3) in;\n"
2052 "in vec3 vPosition;\n"
2053 "void main()\n"
2054 "{\n"
2055 " gl_Position = vec4(vPosition, 1.);\n"
2056 "}\n";
2057
Jamie Madill35cd7332018-12-02 12:03:33 -05002058 constexpr char kFS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002059 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002060 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002061 "precision mediump float;\n"
2062 "out vec4 col;\n"
2063 "void main()\n"
2064 "{\n"
2065 " if (gl_ViewID_OVR == 0u) {\n"
2066 " col = vec4(1,0,0,1);\n"
2067 " } else if (gl_ViewID_OVR == 1u) {\n"
2068 " col = vec4(0,1,0,1);\n"
2069 " } else if (gl_ViewID_OVR == 2u) {\n"
2070 " col = vec4(0,0,1,1);\n"
2071 " } else {\n"
2072 " col = vec4(0,0,0,0);\n"
2073 " }\n"
2074 "}\n";
2075
Olli Etuaho4836acc2018-08-20 15:23:18 +03002076 updateFBOs(1, 1, 3);
Jamie Madill35cd7332018-12-02 12:03:33 -05002077 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev72b4e1e2017-08-31 15:42:56 +03002078
2079 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2080 ASSERT_GL_NO_ERROR();
2081
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002082 resolveMultisampledFBO();
Martin Radev72b4e1e2017-08-31 15:42:56 +03002083 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2084 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2085 EXPECT_EQ(GLColor::blue, GetViewColor(0, 0, 2));
2086}
2087
2088// The test checks that the inactive layers of a 2D texture array are not written to by a
2089// multi-view program.
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002090TEST_P(MultiviewLayeredRenderTest, RenderToSubrangeOfLayers)
Martin Radev72b4e1e2017-08-31 15:42:56 +03002091{
2092 if (!requestMultiviewExtension())
2093 {
2094 return;
2095 }
2096
Jamie Madill35cd7332018-12-02 12:03:33 -05002097 constexpr char kVS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002098 "#version 300 es\n"
2099 "#extension GL_OVR_multiview : require\n"
2100 "layout(num_views = 2) in;\n"
2101 "in vec3 vPosition;\n"
2102 "void main()\n"
2103 "{\n"
2104 " gl_Position = vec4(vPosition, 1.);\n"
2105 "}\n";
2106
Jamie Madill35cd7332018-12-02 12:03:33 -05002107 constexpr char kFS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002108 "#version 300 es\n"
2109 "#extension GL_OVR_multiview : require\n"
2110 "precision mediump float;\n"
2111 "out vec4 col;\n"
2112 "void main()\n"
2113 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002114 " col = vec4(0,1,0,1);\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002115 "}\n";
2116
Olli Etuaho4836acc2018-08-20 15:23:18 +03002117 updateFBOs(1, 1, 2, 4, 1);
Jamie Madill35cd7332018-12-02 12:03:33 -05002118 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev72b4e1e2017-08-31 15:42:56 +03002119
2120 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2121 ASSERT_GL_NO_ERROR();
2122
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002123 resolveMultisampledFBO();
Martin Radev72b4e1e2017-08-31 15:42:56 +03002124 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +03002125 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2126 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 2));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002127 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 3));
2128}
2129
Martin Radevc1d4e552017-08-21 12:01:10 +03002130// The D3D11 renderer uses a GS whenever the varyings are flat interpolated which can cause
2131// potential bugs if the view is selected in the VS. The test contains a program in which the
2132// gl_InstanceID is passed as a flat varying to the fragment shader where it is used to discard the
2133// fragment if its value is negative. The gl_InstanceID should never be negative and that branch is
2134// never taken. One quad is drawn and the color is selected based on the ViewID - red for view 0 and
2135// green for view 1.
2136TEST_P(MultiviewRenderTest, FlatInterpolation)
Martin Radev3c25ad02017-08-22 17:36:53 +03002137{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002138 if (!requestMultiviewExtension(isMultisampled()))
Martin Radevc1d4e552017-08-21 12:01:10 +03002139 {
2140 return;
2141 }
2142
Jamie Madill35cd7332018-12-02 12:03:33 -05002143 constexpr char kVS[] =
Martin Radevc1d4e552017-08-21 12:01:10 +03002144 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002145 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002146 "layout(num_views = 2) in;\n"
2147 "in vec3 vPosition;\n"
2148 "flat out int oInstanceID;\n"
2149 "void main()\n"
2150 "{\n"
2151 " gl_Position = vec4(vPosition, 1.);\n"
2152 " oInstanceID = gl_InstanceID;\n"
2153 "}\n";
2154
Jamie Madill35cd7332018-12-02 12:03:33 -05002155 constexpr char kFS[] =
Martin Radevc1d4e552017-08-21 12:01:10 +03002156 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002157 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002158 "precision mediump float;\n"
2159 "flat in int oInstanceID;\n"
2160 "out vec4 col;\n"
2161 "void main()\n"
2162 "{\n"
2163 " if (oInstanceID < 0) {\n"
2164 " discard;\n"
2165 " }\n"
2166 " if (gl_ViewID_OVR == 0u) {\n"
2167 " col = vec4(1,0,0,1);\n"
2168 " } else {\n"
2169 " col = vec4(0,1,0,1);\n"
2170 " }\n"
2171 "}\n";
2172
Olli Etuaho4836acc2018-08-20 15:23:18 +03002173 updateFBOs(1, 1, 2);
Jamie Madill35cd7332018-12-02 12:03:33 -05002174 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radevc1d4e552017-08-21 12:01:10 +03002175
2176 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2177 ASSERT_GL_NO_ERROR();
2178
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002179 resolveMultisampledFBO();
Martin Radevc1d4e552017-08-21 12:01:10 +03002180 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2181 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev3c25ad02017-08-22 17:36:53 +03002182}
2183
Olli Etuaho604d8732018-07-20 11:02:43 +03002184// This test assigns gl_ViewID_OVR to a flat int varying and then sets the color based on that
2185// varying in the fragment shader.
2186TEST_P(MultiviewRenderTest, FlatInterpolation2)
2187{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002188 if (!requestMultiviewExtension(isMultisampled()))
Olli Etuaho604d8732018-07-20 11:02:43 +03002189 {
2190 return;
2191 }
2192
Jamie Madill35cd7332018-12-02 12:03:33 -05002193 constexpr char kVS[] =
Olli Etuaho604d8732018-07-20 11:02:43 +03002194 "#version 300 es\n"
2195 "#extension GL_OVR_multiview : require\n"
2196 "layout(num_views = 2) in;\n"
2197 "in vec3 vPosition;\n"
2198 "flat out int flatVarying;\n"
2199 "void main()\n"
2200 "{\n"
2201 " gl_Position = vec4(vPosition, 1.);\n"
2202 " flatVarying = int(gl_ViewID_OVR);\n"
2203 "}\n";
2204
Jamie Madill35cd7332018-12-02 12:03:33 -05002205 constexpr char kFS[] =
Olli Etuaho604d8732018-07-20 11:02:43 +03002206 "#version 300 es\n"
2207 "#extension GL_OVR_multiview : require\n"
2208 "precision mediump float;\n"
2209 "flat in int flatVarying;\n"
2210 "out vec4 col;\n"
2211 "void main()\n"
2212 "{\n"
2213 " if (flatVarying == 0) {\n"
2214 " col = vec4(1,0,0,1);\n"
2215 " } else {\n"
2216 " col = vec4(0,1,0,1);\n"
2217 " }\n"
2218 "}\n";
2219
Olli Etuaho4836acc2018-08-20 15:23:18 +03002220 updateFBOs(1, 1, 2);
Jamie Madill35cd7332018-12-02 12:03:33 -05002221 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho604d8732018-07-20 11:02:43 +03002222
2223 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2224 ASSERT_GL_NO_ERROR();
2225
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002226 resolveMultisampledFBO();
Olli Etuaho604d8732018-07-20 11:02:43 +03002227 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2228 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2229}
2230
Martin Radev265a6d42017-09-12 16:51:37 +03002231// The test is added to cover a bug which resulted in the viewport/scissor and viewport offsets not
2232// being correctly applied.
2233TEST_P(MultiviewSideBySideRenderTest, ViewportOffsetsAppliedBugCoverage)
2234{
2235 if (!requestMultiviewExtension())
2236 {
2237 return;
2238 }
2239
Olli Etuaho4836acc2018-08-20 15:23:18 +03002240 updateFBOs(1, 1, 2);
Martin Radev265a6d42017-09-12 16:51:37 +03002241
2242 // Create multiview program.
Jamie Madill35cd7332018-12-02 12:03:33 -05002243 constexpr char kVS[] =
Martin Radev265a6d42017-09-12 16:51:37 +03002244 "#version 300 es\n"
2245 "#extension GL_OVR_multiview : require\n"
2246 "layout(num_views = 2) in;\n"
2247 "layout(location = 0) in vec3 vPosition;\n"
2248 "void main()\n"
2249 "{\n"
2250 " gl_Position = vec4(vPosition, 1.0);\n"
2251 "}\n";
2252
Jamie Madill35cd7332018-12-02 12:03:33 -05002253 constexpr char kFS[] =
Martin Radev265a6d42017-09-12 16:51:37 +03002254 "#version 300 es\n"
2255 "#extension GL_OVR_multiview : require\n"
2256 "precision mediump float;\n"
2257 "out vec4 col;\n"
2258 "void main()\n"
2259 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002260 " col = vec4(0,1,0,1);\n"
Martin Radev265a6d42017-09-12 16:51:37 +03002261 "}\n";
2262
Jamie Madill35cd7332018-12-02 12:03:33 -05002263 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev265a6d42017-09-12 16:51:37 +03002264
2265 glViewport(0, 0, 1, 1);
2266 glScissor(0, 0, 1, 1);
2267 glEnable(GL_SCISSOR_TEST);
2268 glClearColor(0, 0, 0, 1);
2269
2270 // Bind the default FBO and make sure that the state is synchronized.
2271 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2272 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2273 ASSERT_GL_NO_ERROR();
2274
2275 // Draw and check that both views are rendered to.
Olli Etuaho4836acc2018-08-20 15:23:18 +03002276 bindMemberDrawFramebuffer();
Martin Radev265a6d42017-09-12 16:51:37 +03002277 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev67a8a012017-09-08 13:03:52 +03002278
Martin Radev265a6d42017-09-12 16:51:37 +03002279 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
Martin Radev67a8a012017-09-08 13:03:52 +03002280 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
2281 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev265a6d42017-09-12 16:51:37 +03002282}
2283
Olli Etuahof26b27e2018-08-17 11:01:19 +03002284MultiviewRenderTestParams SideBySideVertexShaderOpenGL(GLint majorVersion = 3,
2285 GLint minorVersion = 0)
Martin Radev3c25ad02017-08-22 17:36:53 +03002286{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002287 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002288 VertexShaderOpenGL(majorVersion, minorVersion));
Martin Radev3c25ad02017-08-22 17:36:53 +03002289}
2290
Olli Etuahof26b27e2018-08-17 11:01:19 +03002291MultiviewRenderTestParams LayeredVertexShaderOpenGL()
Martin Radev3c25ad02017-08-22 17:36:53 +03002292{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002293 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002294 VertexShaderOpenGL(3, 0));
Martin Radev3c25ad02017-08-22 17:36:53 +03002295}
2296
Olli Etuahof26b27e2018-08-17 11:01:19 +03002297MultiviewRenderTestParams SideBySideGeomShaderD3D11()
Martin Radev72b4e1e2017-08-31 15:42:56 +03002298{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002299 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002300 GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002301}
2302
Olli Etuahof26b27e2018-08-17 11:01:19 +03002303MultiviewRenderTestParams LayeredGeomShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002304{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002305 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
2306 GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002307}
2308
Olli Etuahof26b27e2018-08-17 11:01:19 +03002309MultiviewRenderTestParams SideBySideVertexShaderD3D11(GLint majorVersion = 3,
2310 GLint minorVersion = 0)
Martin Radevc1d4e552017-08-21 12:01:10 +03002311{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002312 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002313 VertexShaderD3D11(majorVersion, minorVersion));
Martin Radevc1d4e552017-08-21 12:01:10 +03002314}
2315
Olli Etuahof26b27e2018-08-17 11:01:19 +03002316MultiviewRenderTestParams LayeredVertexShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002317{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002318 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002319 VertexShaderD3D11(3, 0));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002320}
2321
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002322MultiviewRenderTestParams LayeredMultisampledVertexShaderOpenGL()
2323{
2324 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 2,
2325 VertexShaderOpenGL(3, 1));
2326}
2327
2328MultiviewRenderTestParams LayeredMultisampledVertexShaderD3D11()
2329{
2330 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 2,
2331 VertexShaderD3D11(3, 1));
2332}
2333
Jamie Madill04c084d2018-08-08 15:49:28 -04002334ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest,
Olli Etuaho44ae8992018-08-20 15:37:09 +03002335 VertexShaderOpenGL(3, 1),
2336 VertexShaderD3D11(3, 1));
Martin Radevced5c862017-08-17 16:05:29 +03002337ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002338 SideBySideVertexShaderOpenGL(),
2339 LayeredVertexShaderOpenGL(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002340 LayeredMultisampledVertexShaderOpenGL(),
Martin Radevc1d4e552017-08-21 12:01:10 +03002341 SideBySideGeomShaderD3D11(),
2342 SideBySideVertexShaderD3D11(),
2343 LayeredGeomShaderD3D11(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002344 LayeredVertexShaderD3D11(),
2345 LayeredMultisampledVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002346ANGLE_INSTANTIATE_TEST(MultiviewRenderTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002347 SideBySideVertexShaderOpenGL(),
2348 LayeredVertexShaderOpenGL(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002349 LayeredMultisampledVertexShaderOpenGL(),
Martin Radevc1d4e552017-08-21 12:01:10 +03002350 SideBySideGeomShaderD3D11(),
2351 SideBySideVertexShaderD3D11(),
2352 LayeredGeomShaderD3D11(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002353 LayeredVertexShaderD3D11(),
2354 LayeredMultisampledVertexShaderD3D11());
Martin Radevced5c862017-08-17 16:05:29 +03002355ANGLE_INSTANTIATE_TEST(MultiviewOcclusionQueryTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002356 SideBySideVertexShaderOpenGL(),
2357 LayeredVertexShaderOpenGL(),
2358 SideBySideGeomShaderD3D11(),
2359 SideBySideVertexShaderD3D11(),
2360 LayeredGeomShaderD3D11(),
2361 LayeredVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002362ANGLE_INSTANTIATE_TEST(MultiviewProgramGenerationTest,
Olli Etuaho4bcaf992018-08-17 17:18:28 +03002363 VertexShaderOpenGL(3, 0),
2364 GeomShaderD3D11(3, 0),
2365 VertexShaderD3D11(3, 0));
Martin Radevced5c862017-08-17 16:05:29 +03002366ANGLE_INSTANTIATE_TEST(MultiviewRenderPrimitiveTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002367 SideBySideVertexShaderOpenGL(),
2368 LayeredVertexShaderOpenGL(),
2369 SideBySideGeomShaderD3D11(),
2370 SideBySideVertexShaderD3D11(),
2371 LayeredGeomShaderD3D11(),
2372 LayeredVertexShaderD3D11());
Jamie Madill04c084d2018-08-08 15:49:28 -04002373ANGLE_INSTANTIATE_TEST(MultiviewSideBySideRenderTest,
2374 VertexShaderOpenGL(3, 0),
2375 GeomShaderD3D11(3, 0));
2376ANGLE_INSTANTIATE_TEST(MultiviewLayeredRenderTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));