blob: c753e681f209c0d5e818b94e1aaefe6888c9a676 [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 {
46 ASSERT(multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE ||
47 multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
48 }
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:
67 UNREACHABLE();
68 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +030069 if (params.mSamples > 0)
70 {
71 os << "_samples_" << params.mSamples;
72 }
Martin Radev3c25ad02017-08-22 17:36:53 +030073 return os;
74}
75
Olli Etuaho4836acc2018-08-20 15:23:18 +030076class MultiviewFramebufferTestBase : public MultiviewTestBase
Martin Radev8f276e22017-05-30 12:05:52 +030077{
78 protected:
Olli Etuaho2c8f0842018-09-12 14:44:55 +030079 MultiviewFramebufferTestBase(const PlatformParameters &params,
80 GLenum multiviewLayout,
81 int samples)
Olli Etuahof26b27e2018-08-17 11:01:19 +030082 : MultiviewTestBase(params),
Martin Radev3c25ad02017-08-22 17:36:53 +030083 mViewWidth(0),
84 mViewHeight(0),
Olli Etuaho4836acc2018-08-20 15:23:18 +030085 mNumViews(0),
Olli Etuaho44ae8992018-08-20 15:37:09 +030086 mColorTexture(0u),
87 mDepthTexture(0u),
88 mDrawFramebuffer(0u),
Olli Etuaho2c8f0842018-09-12 14:44:55 +030089 mMultiviewLayout(multiviewLayout),
90 mSamples(samples),
91 mResolveTexture(0u)
Jamie Madillb980c562018-11-27 11:34:27 -050092 {}
Olli Etuaho44ae8992018-08-20 15:37:09 +030093
Olli Etuaho4836acc2018-08-20 15:23:18 +030094 void FramebufferTestSetUp() { MultiviewTestBase::MultiviewTestBaseSetUp(); }
Olli Etuaho44ae8992018-08-20 15:37:09 +030095
96 void FramebufferTestTearDown()
97 {
98 freeFBOs();
99 MultiviewTestBase::MultiviewTestBaseTearDown();
100 }
101
Olli Etuaho4836acc2018-08-20 15:23:18 +0300102 void updateFBOs(int viewWidth, int height, int numViews, int numLayers, int baseViewIndex)
Martin Radev3c25ad02017-08-22 17:36:53 +0300103 {
Martin Radev72b4e1e2017-08-31 15:42:56 +0300104 ASSERT(numViews + baseViewIndex <= numLayers);
105
Olli Etuaho44ae8992018-08-20 15:37:09 +0300106 freeFBOs();
107
Martin Radev3c25ad02017-08-22 17:36:53 +0300108 mViewWidth = viewWidth;
109 mViewHeight = height;
110 mNumViews = numViews;
Martin Radev8f276e22017-05-30 12:05:52 +0300111
Olli Etuaho44ae8992018-08-20 15:37:09 +0300112 glGenTextures(1, &mColorTexture);
113 glGenTextures(1, &mDepthTexture);
Martin Radev0abb7a22017-08-28 15:34:45 +0300114
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300115 CreateMultiviewBackingTextures(mMultiviewLayout, mSamples, viewWidth, height, numLayers,
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300116 mColorTexture, mDepthTexture, 0u);
Martin Radev3c25ad02017-08-22 17:36:53 +0300117
Olli Etuaho44ae8992018-08-20 15:37:09 +0300118 glGenFramebuffers(1, &mDrawFramebuffer);
119
Martin Radev3c25ad02017-08-22 17:36:53 +0300120 // Create draw framebuffer to be used for multiview rendering.
121 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300122 AttachMultiviewTextures(GL_DRAW_FRAMEBUFFER, mMultiviewLayout, viewWidth, numViews,
123 baseViewIndex, mColorTexture, mDepthTexture, 0u);
Martin Radev8f276e22017-05-30 12:05:52 +0300124
Martin Radev8f276e22017-05-30 12:05:52 +0300125 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
126
127 // Create read framebuffer to be used to retrieve the pixel information for testing
128 // purposes.
Martin Radev3c25ad02017-08-22 17:36:53 +0300129 switch (mMultiviewLayout)
130 {
131 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
132 mReadFramebuffer.resize(1);
Olli Etuaho44ae8992018-08-20 15:37:09 +0300133 glGenFramebuffers(1, mReadFramebuffer.data());
Martin Radev3c25ad02017-08-22 17:36:53 +0300134 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[0]);
135 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
136 mColorTexture, 0);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300137 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
138 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300139 break;
140 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev72b4e1e2017-08-31 15:42:56 +0300141 mReadFramebuffer.resize(numLayers);
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400142 glGenFramebuffers(static_cast<GLsizei>(mReadFramebuffer.size()),
143 mReadFramebuffer.data());
Martin Radev72b4e1e2017-08-31 15:42:56 +0300144 for (int i = 0; i < numLayers; ++i)
Martin Radev3c25ad02017-08-22 17:36:53 +0300145 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300146 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[i]);
147 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
148 mColorTexture, 0, i);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300149 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
150 glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
Martin Radev3c25ad02017-08-22 17:36:53 +0300151 }
152 break;
153 default:
154 UNREACHABLE();
155 }
Martin Radev8f276e22017-05-30 12:05:52 +0300156
157 // Clear the buffers.
Martin Radev3c25ad02017-08-22 17:36:53 +0300158 glViewport(0, 0, viewWidth, height);
159 if (mMultiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
160 {
161 // Enable the scissor test only for side-by-side framebuffers.
162 glEnable(GL_SCISSOR_TEST);
163 glScissor(0, 0, viewWidth, height);
164 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300165 }
Martin Radev8f276e22017-05-30 12:05:52 +0300166
Olli Etuaho4836acc2018-08-20 15:23:18 +0300167 void updateFBOs(int viewWidth, int height, int numViews)
Martin Radev72b4e1e2017-08-31 15:42:56 +0300168 {
Olli Etuaho4836acc2018-08-20 15:23:18 +0300169 updateFBOs(viewWidth, height, numViews, numViews, 0);
Martin Radev72b4e1e2017-08-31 15:42:56 +0300170 }
171
Olli Etuaho4836acc2018-08-20 15:23:18 +0300172 void bindMemberDrawFramebuffer() { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawFramebuffer); }
173
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300174 // In case we have a multisampled framebuffer, creates and binds a resolve framebuffer as the
175 // draw framebuffer, and resolves the read framebuffer to it.
176 void resolveMultisampledFBO()
177 {
178 if (mSamples == 0)
179 {
180 return;
181 }
182 int numLayers = mReadFramebuffer.size();
183 if (mResolveFramebuffer.empty())
184 {
185 ASSERT(mResolveTexture == 0u);
186 glGenTextures(1, &mResolveTexture);
187 CreateMultiviewBackingTextures(mMultiviewLayout, 0, mViewWidth, mViewHeight, numLayers,
188 mResolveTexture, 0u, 0u);
189
190 mResolveFramebuffer.resize(numLayers);
191 glGenFramebuffers(static_cast<GLsizei>(mResolveFramebuffer.size()),
192 mResolveFramebuffer.data());
193 for (int i = 0; i < numLayers; ++i)
194 {
195 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFramebuffer[i]);
196 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
197 mResolveTexture, 0, i);
198 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE,
199 glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
200 }
201 }
202 for (int i = 0; i < numLayers; ++i)
203 {
204 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[i]);
205 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFramebuffer[i]);
206 glBlitFramebuffer(0, 0, mViewWidth, mViewHeight, 0, 0, mViewWidth, mViewHeight,
207 GL_COLOR_BUFFER_BIT, GL_NEAREST);
208 }
209 }
210
Martin Radev3c25ad02017-08-22 17:36:53 +0300211 GLColor GetViewColor(int x, int y, int view)
212 {
213 switch (mMultiviewLayout)
214 {
215 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300216 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[0]);
Martin Radev3c25ad02017-08-22 17:36:53 +0300217 return ReadColor(view * mViewWidth + x, y);
218 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
219 ASSERT(static_cast<size_t>(view) < mReadFramebuffer.size());
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300220 if (mSamples > 0)
221 {
222 ASSERT(static_cast<size_t>(view) < mResolveFramebuffer.size());
223 glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFramebuffer[view]);
224 }
225 else
226 {
227 glBindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer[view]);
228 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300229 return ReadColor(x, y);
230 default:
231 UNREACHABLE();
232 }
233 return GLColor(0, 0, 0, 0);
Martin Radev8f276e22017-05-30 12:05:52 +0300234 }
235
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300236 bool isMultisampled() { return mSamples > 0; }
237
Martin Radev3c25ad02017-08-22 17:36:53 +0300238 int mViewWidth;
239 int mViewHeight;
240 int mNumViews;
Olli Etuaho4836acc2018-08-20 15:23:18 +0300241
Olli Etuaho44ae8992018-08-20 15:37:09 +0300242 GLuint mColorTexture;
243 GLuint mDepthTexture;
244
Olli Etuaho4836acc2018-08-20 15:23:18 +0300245 private:
Olli Etuaho44ae8992018-08-20 15:37:09 +0300246 GLuint mDrawFramebuffer;
247 std::vector<GLuint> mReadFramebuffer;
Olli Etuaho4836acc2018-08-20 15:23:18 +0300248 GLenum mMultiviewLayout;
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300249 int mSamples;
250
251 // For reading back multisampled framebuffer.
252 std::vector<GLuint> mResolveFramebuffer;
253 GLuint mResolveTexture;
Olli Etuaho44ae8992018-08-20 15:37:09 +0300254
255 void freeFBOs()
256 {
257 if (mDrawFramebuffer)
258 {
259 glDeleteFramebuffers(1, &mDrawFramebuffer);
260 mDrawFramebuffer = 0;
261 }
262 if (!mReadFramebuffer.empty())
263 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400264 GLsizei framebufferCount = static_cast<GLsizei>(mReadFramebuffer.size());
265 glDeleteFramebuffers(framebufferCount, mReadFramebuffer.data());
Olli Etuaho44ae8992018-08-20 15:37:09 +0300266 mReadFramebuffer.clear();
267 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300268 if (!mResolveFramebuffer.empty())
269 {
270 GLsizei framebufferCount = static_cast<GLsizei>(mResolveFramebuffer.size());
271 glDeleteFramebuffers(framebufferCount, mResolveFramebuffer.data());
272 mResolveFramebuffer.clear();
273 }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300274 if (mDepthTexture)
275 {
276 glDeleteTextures(1, &mDepthTexture);
277 mDepthTexture = 0;
278 }
279 if (mColorTexture)
280 {
281 glDeleteTextures(1, &mColorTexture);
282 mColorTexture = 0;
283 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300284 if (mResolveTexture)
285 {
286 glDeleteTextures(1, &mResolveTexture);
287 mResolveTexture = 0;
288 }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300289 }
Martin Radev8f276e22017-05-30 12:05:52 +0300290};
291
Olli Etuaho4836acc2018-08-20 15:23:18 +0300292class MultiviewRenderTest : public MultiviewFramebufferTestBase,
Olli Etuahof26b27e2018-08-17 11:01:19 +0300293 public ::testing::TestWithParam<MultiviewRenderTestParams>
Martin Radev8f276e22017-05-30 12:05:52 +0300294{
295 protected:
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300296 MultiviewRenderTest()
297 : MultiviewFramebufferTestBase(GetParam(), GetParam().mMultiviewLayout, GetParam().mSamples)
Jamie Madillb980c562018-11-27 11:34:27 -0500298 {}
Olli Etuaho4836acc2018-08-20 15:23:18 +0300299 void SetUp() override { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300300 void TearDown() override { MultiviewFramebufferTestBase::FramebufferTestTearDown(); }
Martin Radevc1d4e552017-08-21 12:01:10 +0300301
302 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) override
303 {
304 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
305 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300306};
307
Jamie Madill04c084d2018-08-08 15:49:28 -0400308constexpr char kDualViewVSSource[] = R"(#version 300 es
309#extension GL_OVR_multiview : require
310layout(num_views = 2) in;
311in vec4 vPosition;
312void main()
313{
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300314 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 -0400315 gl_Position.yzw = vPosition.yzw;
316})";
317
318constexpr char kDualViewFSSource[] = R"(#version 300 es
319#extension GL_OVR_multiview : require
320precision mediump float;
321out vec4 col;
322void main()
323{
324 col = vec4(0,1,0,1);
325})";
326
Martin Radev3c25ad02017-08-22 17:36:53 +0300327class MultiviewRenderDualViewTest : public MultiviewRenderTest
328{
329 protected:
330 MultiviewRenderDualViewTest() : mProgram(0u) {}
Martin Radev8f276e22017-05-30 12:05:52 +0300331
332 void SetUp() override
333 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300334 MultiviewRenderTest::SetUp();
Martin Radev8f276e22017-05-30 12:05:52 +0300335
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300336 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev8f276e22017-05-30 12:05:52 +0300337 {
338 return;
339 }
340
Olli Etuaho4836acc2018-08-20 15:23:18 +0300341 updateFBOs(2, 1, 2);
Jamie Madill04c084d2018-08-08 15:49:28 -0400342 mProgram = CompileProgram(kDualViewVSSource, kDualViewFSSource);
Martin Radev61bd9992017-08-11 13:10:55 +0300343 ASSERT_NE(mProgram, 0u);
Martin Radev8f276e22017-05-30 12:05:52 +0300344 glUseProgram(mProgram);
345 ASSERT_GL_NO_ERROR();
346 }
347
Olli Etuaho44ae8992018-08-20 15:37:09 +0300348 void TearDown() override
349 {
350 if (mProgram != 0u)
351 {
352 glDeleteProgram(mProgram);
353 mProgram = 0u;
354 }
355
356 MultiviewRenderTest::TearDown();
357 }
358
Martin Radev8f276e22017-05-30 12:05:52 +0300359 void checkOutput()
360 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300361 resolveMultisampledFBO();
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300362 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +0300363 EXPECT_EQ(GLColor::green, GetViewColor(1, 0, 0));
364 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300365 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(1, 0, 1));
Martin Radev8f276e22017-05-30 12:05:52 +0300366 }
367
368 GLuint mProgram;
369};
370
Olli Etuaho44ae8992018-08-20 15:37:09 +0300371// Base class for tests that care mostly about draw call validity and not rendering results.
372class MultiviewDrawValidationTest : public MultiviewTest
Jamie Madill04c084d2018-08-08 15:49:28 -0400373{
374 protected:
Olli Etuaho44ae8992018-08-20 15:37:09 +0300375 MultiviewDrawValidationTest() : MultiviewTest() {}
Jamie Madill04c084d2018-08-08 15:49:28 -0400376
Olli Etuaho44ae8992018-08-20 15:37:09 +0300377 void initOnePixelColorTexture2D(GLuint texId)
Jamie Madill04c084d2018-08-08 15:49:28 -0400378 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300379 glBindTexture(GL_TEXTURE_2D, texId);
Jamie Madill04c084d2018-08-08 15:49:28 -0400380 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Olli Etuaho44ae8992018-08-20 15:37:09 +0300381 }
Jamie Madill04c084d2018-08-08 15:49:28 -0400382
Olli Etuaho44ae8992018-08-20 15:37:09 +0300383 // This initializes a simple VAO with a valid vertex buffer and index buffer with three
384 // vertices.
385 void initVAO(GLuint vao, GLuint vertexBuffer, GLuint indexBuffer)
386 {
387 glBindVertexArray(vao);
Jamie Madill04c084d2018-08-08 15:49:28 -0400388
389 const float kVertexData[3] = {0.0f};
Olli Etuaho44ae8992018-08-20 15:37:09 +0300390 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
Jamie Madill04c084d2018-08-08 15:49:28 -0400391 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3u, &kVertexData[0], GL_STATIC_DRAW);
392
393 const unsigned int kIndices[3] = {0u, 1u, 2u};
Olli Etuaho44ae8992018-08-20 15:37:09 +0300394 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
Jamie Madill04c084d2018-08-08 15:49:28 -0400395 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, &kIndices[0],
396 GL_STATIC_DRAW);
397 ASSERT_GL_NO_ERROR();
398 }
Jamie Madill04c084d2018-08-08 15:49:28 -0400399};
400
Martin Radev3c25ad02017-08-22 17:36:53 +0300401class MultiviewOcclusionQueryTest : public MultiviewRenderTest
Martin Radev0d671c92017-08-10 16:41:52 +0300402{
403 protected:
Martin Radev3c25ad02017-08-22 17:36:53 +0300404 MultiviewOcclusionQueryTest() {}
Martin Radev0d671c92017-08-10 16:41:52 +0300405
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400406 bool requestOcclusionQueryExtension()
407 {
408 if (extensionRequestable("GL_EXT_occlusion_query_boolean"))
409 {
410 glRequestExtensionANGLE("GL_EXT_occlusion_query_boolean");
411 }
412
413 if (!extensionEnabled("GL_EXT_occlusion_query_boolean"))
414 {
415 std::cout << "Test skipped due to missing GL_EXT_occlusion_query_boolean." << std::endl;
416 return false;
417 }
418 return true;
419 }
420
Martin Radev0d671c92017-08-10 16:41:52 +0300421 GLuint drawAndRetrieveOcclusionQueryResult(GLuint program)
422 {
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400423 GLQueryEXT query;
424 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED, query);
Martin Radev0d671c92017-08-10 16:41:52 +0300425 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
426 glEndQueryEXT(GL_ANY_SAMPLES_PASSED);
427
428 GLuint result = GL_TRUE;
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400429 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT, &result);
Martin Radev0d671c92017-08-10 16:41:52 +0300430 return result;
431 }
432};
433
Olli Etuaho4bcaf992018-08-17 17:18:28 +0300434class MultiviewProgramGenerationTest : public MultiviewTest
Martin Radev41ac68e2017-06-06 12:16:58 +0300435{
436 protected:
437 MultiviewProgramGenerationTest() {}
438};
439
Martin Radev3c25ad02017-08-22 17:36:53 +0300440class MultiviewRenderPrimitiveTest : public MultiviewRenderTest
Martin Radev61bd9992017-08-11 13:10:55 +0300441{
442 protected:
Olli Etuaho44ae8992018-08-20 15:37:09 +0300443 MultiviewRenderPrimitiveTest() : mVBO(0u) {}
444
445 void SetUp() override
446 {
447 MultiviewRenderTest::SetUp();
448 glGenBuffers(1, &mVBO);
449 }
450
451 void TearDown() override
452 {
453 if (mVBO)
454 {
455 glDeleteBuffers(1, &mVBO);
456 mVBO = 0u;
457 }
458 MultiviewRenderTest::TearDown();
459 }
Martin Radev61bd9992017-08-11 13:10:55 +0300460
461 void setupGeometry(const std::vector<Vector2> &vertexData)
462 {
Martin Radev61bd9992017-08-11 13:10:55 +0300463 glBindBuffer(GL_ARRAY_BUFFER, mVBO);
464 glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vector2), vertexData.data(),
465 GL_STATIC_DRAW);
466 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -0500467 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +0300468 }
469
Martin Radev67a8a012017-09-08 13:03:52 +0300470 void checkGreenChannel(const GLubyte expectedGreenChannelData[])
Martin Radev61bd9992017-08-11 13:10:55 +0300471 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300472 for (int view = 0; view < mNumViews; ++view)
Martin Radev61bd9992017-08-11 13:10:55 +0300473 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300474 for (int w = 0; w < mViewWidth; ++w)
Martin Radev61bd9992017-08-11 13:10:55 +0300475 {
Martin Radev3c25ad02017-08-22 17:36:53 +0300476 for (int h = 0; h < mViewHeight; ++h)
477 {
478 size_t flatIndex =
479 static_cast<size_t>(view * mViewWidth * mViewHeight + mViewWidth * h + w);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300480 EXPECT_EQ(GLColor(0, expectedGreenChannelData[flatIndex], 0,
481 expectedGreenChannelData[flatIndex]),
Martin Radev3c25ad02017-08-22 17:36:53 +0300482 GetViewColor(w, h, view));
483 }
Martin Radev61bd9992017-08-11 13:10:55 +0300484 }
485 }
486 }
Olli Etuaho44ae8992018-08-20 15:37:09 +0300487 GLuint mVBO;
Martin Radev61bd9992017-08-11 13:10:55 +0300488};
489
Olli Etuaho4836acc2018-08-20 15:23:18 +0300490class MultiviewSideBySideRenderTest : public MultiviewFramebufferTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300491 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev3c25ad02017-08-22 17:36:53 +0300492{
493 protected:
494 MultiviewSideBySideRenderTest()
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300495 : MultiviewFramebufferTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0)
Jamie Madillb980c562018-11-27 11:34:27 -0500496 {}
Olli Etuaho44ae8992018-08-20 15:37:09 +0300497
498 void SetUp() final { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
499 void TearDown() final { MultiviewFramebufferTestBase::FramebufferTestTearDown(); }
500 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) final
Martin Radevc1d4e552017-08-21 12:01:10 +0300501 {
502 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
503 }
Martin Radev3c25ad02017-08-22 17:36:53 +0300504};
505
Olli Etuaho4836acc2018-08-20 15:23:18 +0300506class MultiviewLayeredRenderTest : public MultiviewFramebufferTestBase,
Martin Radevc1d4e552017-08-21 12:01:10 +0300507 public ::testing::TestWithParam<MultiviewImplementationParams>
Martin Radev72b4e1e2017-08-31 15:42:56 +0300508{
509 protected:
510 MultiviewLayeredRenderTest()
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300511 : MultiviewFramebufferTestBase(GetParam(), GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0)
Jamie Madillb980c562018-11-27 11:34:27 -0500512 {}
Olli Etuaho44ae8992018-08-20 15:37:09 +0300513 void SetUp() final { MultiviewFramebufferTestBase::FramebufferTestSetUp(); }
514 void TearDown() final { MultiviewFramebufferTestBase::FramebufferTestTearDown(); }
515 void overrideWorkaroundsD3D(WorkaroundsD3D *workarounds) final
Martin Radevc1d4e552017-08-21 12:01:10 +0300516 {
517 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
518 }
Martin Radev72b4e1e2017-08-31 15:42:56 +0300519};
520
Martin Radev14a26ae2017-07-24 15:56:29 +0300521// The test verifies that glDraw*Indirect:
522// 1) generates an INVALID_OPERATION error if the number of views in the draw framebuffer is greater
523// than 1.
524// 2) does not generate any error if the draw framebuffer has exactly 1 view.
Martin Radev7cf61662017-07-26 17:10:53 +0300525TEST_P(MultiviewDrawValidationTest, IndirectDraw)
Martin Radev14a26ae2017-07-24 15:56:29 +0300526{
527 if (!requestMultiviewExtension())
528 {
529 return;
530 }
531
Martin Radev14a26ae2017-07-24 15:56:29 +0300532 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Martin Radev14a26ae2017-07-24 15:56:29 +0300533
Jamie Madill35cd7332018-12-02 12:03:33 -0500534 constexpr char kFS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300535 "#version 300 es\n"
536 "#extension GL_OVR_multiview : require\n"
537 "precision mediump float;\n"
538 "void main()\n"
539 "{}\n";
540
Olli Etuaho44ae8992018-08-20 15:37:09 +0300541 GLVertexArray vao;
542 GLBuffer vertexBuffer;
543 GLBuffer indexBuffer;
544 initVAO(vao, vertexBuffer, indexBuffer);
545
546 GLFramebuffer fbo;
547 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
548
Martin Radev14a26ae2017-07-24 15:56:29 +0300549 GLBuffer commandBuffer;
550 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, commandBuffer);
551 const GLuint commandData[] = {1u, 1u, 0u, 0u, 0u};
552 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(GLuint) * 5u, &commandData[0], GL_STATIC_DRAW);
553 ASSERT_GL_NO_ERROR();
554
Olli Etuaho44ae8992018-08-20 15:37:09 +0300555 GLTexture tex2D;
556 initOnePixelColorTexture2D(tex2D);
557
Martin Radev14a26ae2017-07-24 15:56:29 +0300558 // Check for a GL_INVALID_OPERATION error with the framebuffer having 2 views.
559 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500560 constexpr char kVS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300561 "#version 300 es\n"
562 "#extension GL_OVR_multiview : require\n"
563 "layout(num_views = 2) in;\n"
564 "void main()\n"
565 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500566 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev14a26ae2017-07-24 15:56:29 +0300567 glUseProgram(program);
568
Olli Etuaho44ae8992018-08-20 15:37:09 +0300569 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
570 2, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300571
572 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
573 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
574
575 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
576 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
577 }
578
579 // Check that no errors are generated if the number of views is 1.
580 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500581 constexpr char kVS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300582 "#version 300 es\n"
583 "#extension GL_OVR_multiview : require\n"
584 "layout(num_views = 1) in;\n"
585 "void main()\n"
586 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500587 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev14a26ae2017-07-24 15:56:29 +0300588 glUseProgram(program);
589
Olli Etuaho44ae8992018-08-20 15:37:09 +0300590 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
591 1, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300592
593 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
594 EXPECT_GL_NO_ERROR();
595
596 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
597 EXPECT_GL_NO_ERROR();
598 }
599}
600
Martin Radev7cf61662017-07-26 17:10:53 +0300601// The test verifies that glDraw*:
602// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and
603// program differs.
604// 2) does not generate any error if the number of views is the same.
Martin Radev7cf61662017-07-26 17:10:53 +0300605TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
606{
607 if (!requestMultiviewExtension())
608 {
609 return;
610 }
611
612 const GLint viewportOffsets[4] = {0, 0, 2, 0};
613
Jamie Madill35cd7332018-12-02 12:03:33 -0500614 constexpr char kVS[] =
Martin Radev7cf61662017-07-26 17:10:53 +0300615 "#version 300 es\n"
616 "#extension GL_OVR_multiview : require\n"
617 "layout(num_views = 2) in;\n"
618 "void main()\n"
619 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500620 constexpr char kFS[] =
Martin Radev7cf61662017-07-26 17:10:53 +0300621 "#version 300 es\n"
622 "#extension GL_OVR_multiview : require\n"
623 "precision mediump float;\n"
624 "void main()\n"
625 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500626 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev7cf61662017-07-26 17:10:53 +0300627 glUseProgram(program);
628
Olli Etuaho44ae8992018-08-20 15:37:09 +0300629 GLVertexArray vao;
630 GLBuffer vertexBuffer;
631 GLBuffer indexBuffer;
632 initVAO(vao, vertexBuffer, indexBuffer);
633
634 GLFramebuffer fbo;
635 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
636
637 GLTexture tex2D;
638 initOnePixelColorTexture2D(tex2D);
639
Martin Radev7cf61662017-07-26 17:10:53 +0300640 // Check for a GL_INVALID_OPERATION error with the framebuffer and program having different
641 // number of views.
642 {
643 // The framebuffer has only 1 view.
Olli Etuaho44ae8992018-08-20 15:37:09 +0300644 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
645 1, &viewportOffsets[0]);
Martin Radev7cf61662017-07-26 17:10:53 +0300646
647 glDrawArrays(GL_TRIANGLES, 0, 3);
648 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
649
650 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
651 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
652 }
653
654 // Check that no errors are generated if the number of views in both program and draw
655 // framebuffer matches.
656 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300657 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
658 2, &viewportOffsets[0]);
Martin Radev7cf61662017-07-26 17:10:53 +0300659
660 glDrawArrays(GL_TRIANGLES, 0, 3);
661 EXPECT_GL_NO_ERROR();
662
663 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
664 EXPECT_GL_NO_ERROR();
665 }
Martin Radevda8e2572017-09-12 17:21:16 +0300666}
Martin Radev7cf61662017-07-26 17:10:53 +0300667
Martin Radevda8e2572017-09-12 17:21:16 +0300668// The test verifies that glDraw* generates an INVALID_OPERATION error if the program does not use
669// the multiview extension, but the active draw framebuffer has more than one view.
670TEST_P(MultiviewDrawValidationTest, NumViewsMismatchForNonMultiviewProgram)
671{
672 if (!requestMultiviewExtension())
Martin Radev7cf61662017-07-26 17:10:53 +0300673 {
Martin Radevda8e2572017-09-12 17:21:16 +0300674 return;
Martin Radev7cf61662017-07-26 17:10:53 +0300675 }
Martin Radevda8e2572017-09-12 17:21:16 +0300676
Jamie Madill35cd7332018-12-02 12:03:33 -0500677 constexpr char kVS[] =
Martin Radevda8e2572017-09-12 17:21:16 +0300678 "#version 300 es\n"
679 "void main()\n"
680 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500681 constexpr char kFS[] =
Martin Radevda8e2572017-09-12 17:21:16 +0300682 "#version 300 es\n"
683 "precision mediump float;\n"
684 "void main()\n"
685 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500686 ANGLE_GL_PROGRAM(programNoMultiview, kVS, kFS);
Martin Radevda8e2572017-09-12 17:21:16 +0300687 glUseProgram(programNoMultiview);
688
Olli Etuaho44ae8992018-08-20 15:37:09 +0300689 GLVertexArray vao;
690 GLBuffer vertexBuffer;
691 GLBuffer indexBuffer;
692 initVAO(vao, vertexBuffer, indexBuffer);
693
694 GLFramebuffer fbo;
695 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
696
697 GLTexture tex2D;
698 initOnePixelColorTexture2D(tex2D);
699
Martin Radevda8e2572017-09-12 17:21:16 +0300700 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Olli Etuaho44ae8992018-08-20 15:37:09 +0300701 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0, 2,
Martin Radevda8e2572017-09-12 17:21:16 +0300702 &viewportOffsets[0]);
703
704 glDrawArrays(GL_TRIANGLES, 0, 3);
705 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
706
707 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
708 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radev7cf61662017-07-26 17:10:53 +0300709}
710
Martin Radev7e69f762017-07-27 14:54:13 +0300711// The test verifies that glDraw*:
712// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
713// greater than 1 and there is an active transform feedback object.
714// 2) does not generate any error if the number of views in the draw framebuffer is 1.
715TEST_P(MultiviewDrawValidationTest, ActiveTransformFeedback)
716{
717 if (!requestMultiviewExtension())
718 {
719 return;
720 }
721
722 const GLint viewportOffsets[4] = {0, 0, 2, 0};
723
Jamie Madill35cd7332018-12-02 12:03:33 -0500724 constexpr char kVS[] = R"(#version 300 es
725out float tfVarying;
726void main()
727{
728 tfVarying = 1.0;
729})";
730
731 constexpr char kFS[] = R"(#version 300 es
732precision mediump float;
733void main()
734{})";
Jamie Madill04c084d2018-08-08 15:49:28 -0400735
Olli Etuaho3755c482017-10-13 15:40:26 +0300736 std::vector<std::string> tfVaryings;
Jamie Madill04c084d2018-08-08 15:49:28 -0400737 tfVaryings.emplace_back("tfVarying");
Jamie Madill35cd7332018-12-02 12:03:33 -0500738 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(singleViewProgram, kVS, kFS, tfVaryings,
Olli Etuaho3755c482017-10-13 15:40:26 +0300739 GL_SEPARATE_ATTRIBS);
Jamie Madill04c084d2018-08-08 15:49:28 -0400740
741 std::vector<std::string> dualViewTFVaryings;
742 dualViewTFVaryings.emplace_back("gl_Position");
743 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(dualViewProgram, kDualViewVSSource, kDualViewFSSource,
744 dualViewTFVaryings, GL_SEPARATE_ATTRIBS);
Martin Radev7e69f762017-07-27 14:54:13 +0300745
Olli Etuaho44ae8992018-08-20 15:37:09 +0300746 GLVertexArray vao;
747 GLBuffer vertexBuffer;
748 GLBuffer indexBuffer;
749 initVAO(vao, vertexBuffer, indexBuffer);
750
Martin Radev7e69f762017-07-27 14:54:13 +0300751 GLBuffer tbo;
752 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);
Jamie Madill04c084d2018-08-08 15:49:28 -0400753 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 16u, nullptr, GL_STATIC_DRAW);
Martin Radev7e69f762017-07-27 14:54:13 +0300754
755 GLTransformFeedback transformFeedback;
756 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
Olli Etuaho3755c482017-10-13 15:40:26 +0300757
758 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
759
Jamie Madill04c084d2018-08-08 15:49:28 -0400760 glUseProgram(dualViewProgram);
Martin Radev7e69f762017-07-27 14:54:13 +0300761 glBeginTransformFeedback(GL_TRIANGLES);
762 ASSERT_GL_NO_ERROR();
763
Olli Etuaho44ae8992018-08-20 15:37:09 +0300764 GLFramebuffer fbo;
765 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
766
767 GLTexture tex2D;
768 initOnePixelColorTexture2D(tex2D);
769
Martin Radev7e69f762017-07-27 14:54:13 +0300770 // Check that drawArrays generates an error when there is an active transform feedback object
771 // and the number of views in the draw framebuffer is greater than 1.
772 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300773 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
774 2, &viewportOffsets[0]);
Martin Radev7e69f762017-07-27 14:54:13 +0300775 glDrawArrays(GL_TRIANGLES, 0, 3);
776 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
777 }
778
Jamie Madill04c084d2018-08-08 15:49:28 -0400779 glEndTransformFeedback();
780
781 // Ending transform feedback should allow the draw to succeed.
782 {
783 glDrawArrays(GL_TRIANGLES, 0, 3);
784 EXPECT_GL_NO_ERROR();
785 }
786
787 // A paused transform feedback should still trigger an error.
788 glBeginTransformFeedback(GL_TRIANGLES);
789 glPauseTransformFeedback();
790 ASSERT_GL_NO_ERROR();
791
792 glDrawArrays(GL_TRIANGLES, 0, 3);
793 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
794
795 // Unbind transform feedback - should succeed.
796 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
797 glDrawArrays(GL_TRIANGLES, 0, 3);
798 ASSERT_GL_NO_ERROR();
799
800 // Rebind paused transform feedback - should fail.
801 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
802 glDrawArrays(GL_TRIANGLES, 0, 3);
803 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
804
805 glResumeTransformFeedback();
806 glEndTransformFeedback();
807
808 glUseProgram(singleViewProgram);
809 glBeginTransformFeedback(GL_TRIANGLES);
810 ASSERT_GL_NO_ERROR();
811
Martin Radev7e69f762017-07-27 14:54:13 +0300812 // Check that drawArrays does not generate an error when the number of views in the draw
813 // framebuffer is 1.
814 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300815 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
816 1, &viewportOffsets[0]);
Martin Radev7e69f762017-07-27 14:54:13 +0300817 glDrawArrays(GL_TRIANGLES, 0, 3);
818 EXPECT_GL_NO_ERROR();
819 }
820
821 glEndTransformFeedback();
822}
823
Martin Radevffe754b2017-07-31 10:38:07 +0300824// The test verifies that glDraw*:
825// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
826// greater than 1 and there is an active query for target GL_TIME_ELAPSED_EXT.
827// 2) does not generate any error if the number of views in the draw framebuffer is 1.
828TEST_P(MultiviewDrawValidationTest, ActiveTimeElapsedQuery)
829{
Yunchao He9550c602018-02-13 14:47:05 +0800830 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radevffe754b2017-07-31 10:38:07 +0300831
Olli Etuaho94c91a92018-07-19 15:10:24 +0300832 if (extensionRequestable("GL_EXT_disjoint_timer_query"))
833 {
834 glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
835 }
836
Yunchao He9550c602018-02-13 14:47:05 +0800837 ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_disjoint_timer_query"));
Martin Radevffe754b2017-07-31 10:38:07 +0300838
Olli Etuaho44ae8992018-08-20 15:37:09 +0300839 ANGLE_GL_PROGRAM(dualViewProgram, kDualViewVSSource, kDualViewFSSource);
840
Martin Radevffe754b2017-07-31 10:38:07 +0300841 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Jamie Madill35cd7332018-12-02 12:03:33 -0500842 constexpr char kVS[] =
Martin Radevffe754b2017-07-31 10:38:07 +0300843 "#version 300 es\n"
844 "void main()\n"
845 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500846 constexpr char kFS[] =
Martin Radevffe754b2017-07-31 10:38:07 +0300847 "#version 300 es\n"
848 "precision mediump float;\n"
849 "void main()\n"
850 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500851 ANGLE_GL_PROGRAM(singleViewProgram, kVS, kFS);
Jamie Madill04c084d2018-08-08 15:49:28 -0400852 glUseProgram(singleViewProgram);
Martin Radevffe754b2017-07-31 10:38:07 +0300853
Olli Etuaho44ae8992018-08-20 15:37:09 +0300854 GLVertexArray vao;
855 GLBuffer vertexBuffer;
856 GLBuffer indexBuffer;
857 initVAO(vao, vertexBuffer, indexBuffer);
858
Martin Radevffe754b2017-07-31 10:38:07 +0300859 GLuint query = 0u;
860 glGenQueriesEXT(1, &query);
861 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
862
Olli Etuaho44ae8992018-08-20 15:37:09 +0300863 GLFramebuffer fbo;
864 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
865
866 GLTexture tex2D;
867 initOnePixelColorTexture2D(tex2D);
868
Martin Radevffe754b2017-07-31 10:38:07 +0300869 // Check first case.
870 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300871 glUseProgram(dualViewProgram);
872 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
873 2, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300874 glClear(GL_COLOR_BUFFER_BIT);
875 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radevffe754b2017-07-31 10:38:07 +0300876 glDrawArrays(GL_TRIANGLES, 0, 3);
877 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
878 }
879
880 // Check second case.
881 {
Jamie Madill04c084d2018-08-08 15:49:28 -0400882 glUseProgram(singleViewProgram);
Olli Etuaho44ae8992018-08-20 15:37:09 +0300883 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
884 1, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300885 glClear(GL_COLOR_BUFFER_BIT);
886 EXPECT_GL_NO_ERROR();
Martin Radevffe754b2017-07-31 10:38:07 +0300887 glDrawArrays(GL_TRIANGLES, 0, 3);
888 EXPECT_GL_NO_ERROR();
889 }
890
891 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
892 glDeleteQueries(1, &query);
Jamie Madill04c084d2018-08-08 15:49:28 -0400893
894 // Check starting a query after a successful draw.
895 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300896 glUseProgram(dualViewProgram);
897 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
898 2, &viewportOffsets[0]);
Jamie Madill04c084d2018-08-08 15:49:28 -0400899 glClear(GL_COLOR_BUFFER_BIT);
900 EXPECT_GL_NO_ERROR();
901 glDrawArrays(GL_TRIANGLES, 0, 3);
902 EXPECT_GL_NO_ERROR();
903
904 glGenQueriesEXT(1, &query);
905 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
906
907 glDrawArrays(GL_TRIANGLES, 0, 3);
908 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
909
910 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
911 glDrawArrays(GL_TRIANGLES, 0, 3);
912 EXPECT_GL_NO_ERROR();
913
914 glDeleteQueries(1, &query);
915 }
Martin Radevffe754b2017-07-31 10:38:07 +0300916}
917
Martin Radev8f276e22017-05-30 12:05:52 +0300918// The test checks that glDrawArrays can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300919TEST_P(MultiviewRenderDualViewTest, DrawArrays)
Martin Radev8f276e22017-05-30 12:05:52 +0300920{
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300921 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev8f276e22017-05-30 12:05:52 +0300922 {
923 return;
924 }
925 drawQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
926 ASSERT_GL_NO_ERROR();
927
928 checkOutput();
929}
930
931// The test checks that glDrawElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300932TEST_P(MultiviewRenderDualViewTest, DrawElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300933{
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300934 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev8f276e22017-05-30 12:05:52 +0300935 {
936 return;
937 }
938 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
939 ASSERT_GL_NO_ERROR();
940
941 checkOutput();
942}
943
944// The test checks that glDrawRangeElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300945TEST_P(MultiviewRenderDualViewTest, DrawRangeElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300946{
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300947 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev8f276e22017-05-30 12:05:52 +0300948 {
949 return;
950 }
951 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true, true);
952 ASSERT_GL_NO_ERROR();
953
954 checkOutput();
955}
956
957// The test checks that glDrawArrays can be used to render into four views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300958TEST_P(MultiviewRenderTest, DrawArraysFourViews)
Martin Radev8f276e22017-05-30 12:05:52 +0300959{
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300960 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev8f276e22017-05-30 12:05:52 +0300961 {
962 return;
963 }
964
Jamie Madill35cd7332018-12-02 12:03:33 -0500965 constexpr char kVS[] =
Martin Radev8f276e22017-05-30 12:05:52 +0300966 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300967 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300968 "layout(num_views = 4) in;\n"
969 "in vec4 vPosition;\n"
970 "void main()\n"
971 "{\n"
972 " if (gl_ViewID_OVR == 0u) {\n"
973 " gl_Position.x = vPosition.x*0.25 - 0.75;\n"
974 " } else if (gl_ViewID_OVR == 1u) {\n"
975 " gl_Position.x = vPosition.x*0.25 - 0.25;\n"
976 " } else if (gl_ViewID_OVR == 2u) {\n"
977 " gl_Position.x = vPosition.x*0.25 + 0.25;\n"
978 " } else {\n"
979 " gl_Position.x = vPosition.x*0.25 + 0.75;\n"
980 " }"
981 " gl_Position.yzw = vPosition.yzw;\n"
982 "}\n";
983
Jamie Madill35cd7332018-12-02 12:03:33 -0500984 constexpr char kFS[] =
Martin Radev8f276e22017-05-30 12:05:52 +0300985 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300986 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300987 "precision mediump float;\n"
988 "out vec4 col;\n"
989 "void main()\n"
990 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300991 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300992 "}\n";
993
Olli Etuaho4836acc2018-08-20 15:23:18 +0300994 updateFBOs(4, 1, 4);
Jamie Madill35cd7332018-12-02 12:03:33 -0500995 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev8f276e22017-05-30 12:05:52 +0300996
997 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
998 ASSERT_GL_NO_ERROR();
999
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001000 resolveMultisampledFBO();
Martin Radev8f276e22017-05-30 12:05:52 +03001001 for (int i = 0; i < 4; ++i)
1002 {
1003 for (int j = 0; j < 4; ++j)
1004 {
Martin Radev8f276e22017-05-30 12:05:52 +03001005 if (i == j)
1006 {
Martin Radev67a8a012017-09-08 13:03:52 +03001007 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +03001008 }
1009 else
1010 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001011 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +03001012 }
1013 }
1014 }
1015 EXPECT_GL_NO_ERROR();
1016}
1017
1018// The test checks that glDrawArraysInstanced can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +03001019TEST_P(MultiviewRenderTest, DrawArraysInstanced)
Martin Radev8f276e22017-05-30 12:05:52 +03001020{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001021 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev8f276e22017-05-30 12:05:52 +03001022 {
1023 return;
1024 }
1025
Jamie Madill35cd7332018-12-02 12:03:33 -05001026 constexpr char kVS[] =
Martin Radev8f276e22017-05-30 12:05:52 +03001027 "#version 300 es\n"
1028 "#extension GL_OVR_multiview : require\n"
1029 "layout(num_views = 2) in;\n"
1030 "in vec4 vPosition;\n"
1031 "void main()\n"
1032 "{\n"
1033 " vec4 p = vPosition;\n"
1034 " if (gl_InstanceID == 1){\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001035 " p.y = p.y * 0.5 + 0.5;\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001036 " } else {\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001037 " p.y = p.y * 0.5 - 0.5;\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001038 " }\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001039 " 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 +03001040 " gl_Position.yzw = p.yzw;\n"
1041 "}\n";
1042
Jamie Madill35cd7332018-12-02 12:03:33 -05001043 constexpr char kFS[] =
Martin Radev8f276e22017-05-30 12:05:52 +03001044 "#version 300 es\n"
1045 "#extension GL_OVR_multiview : require\n"
1046 "precision mediump float;\n"
1047 "out vec4 col;\n"
1048 "void main()\n"
1049 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001050 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001051 "}\n";
1052
Martin Radev3c25ad02017-08-22 17:36:53 +03001053 const int kViewWidth = 2;
1054 const int kViewHeight = 2;
1055 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001056 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001057 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev8f276e22017-05-30 12:05:52 +03001058
Martin Radev67a8a012017-09-08 13:03:52 +03001059 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 2u);
Martin Radev8f276e22017-05-30 12:05:52 +03001060 ASSERT_GL_NO_ERROR();
1061
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001062 resolveMultisampledFBO();
1063
Martin Radev67a8a012017-09-08 13:03:52 +03001064 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {{{0, 255}, {0, 255}},
1065 {{255, 0}, {255, 0}}};
Martin Radev3c25ad02017-08-22 17:36:53 +03001066
1067 for (int view = 0; view < 2; ++view)
Martin Radev8f276e22017-05-30 12:05:52 +03001068 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001069 for (int y = 0; y < 2; ++y)
Martin Radev8f276e22017-05-30 12:05:52 +03001070 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001071 for (int x = 0; x < 2; ++x)
1072 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001073 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][y][x], 0,
1074 expectedGreenChannel[view][y][x]),
Martin Radev3c25ad02017-08-22 17:36:53 +03001075 GetViewColor(x, y, view));
1076 }
Martin Radev8f276e22017-05-30 12:05:52 +03001077 }
1078 }
1079}
1080
Martin Radev553590a2017-07-31 16:40:39 +03001081// The test verifies that the attribute divisor is correctly adjusted when drawing with a multi-view
1082// program. The test draws 4 instances of a quad each of which covers a single pixel. The x and y
1083// offset of each quad are passed as separate attributes which are indexed based on the
1084// corresponding attribute divisors. A divisor of 1 is used for the y offset to have all quads
1085// drawn vertically next to each other. A divisor of 3 is used for the x offset to have the last
1086// quad offsetted by one pixel to the right. Note that the number of views is divisible by 1, but
1087// not by 3.
Martin Radev3c25ad02017-08-22 17:36:53 +03001088TEST_P(MultiviewRenderTest, AttribDivisor)
Martin Radev553590a2017-07-31 16:40:39 +03001089{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001090 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev553590a2017-07-31 16:40:39 +03001091 {
1092 return;
1093 }
1094
Corentin Wallez02cd1522018-08-22 13:46:21 +02001095 // Looks like an incorrect D3D debug layer message is generated on Windows AMD and NVIDIA.
Olli Etuaho44ae8992018-08-20 15:37:09 +03001096 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001097 if (IsWindows() && IsD3D11())
1098 {
1099 ignoreD3D11SDKLayersWarnings();
1100 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001101
Jamie Madill35cd7332018-12-02 12:03:33 -05001102 constexpr char kVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001103 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001104 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001105 "layout(num_views = 2) in;\n"
1106 "in vec3 vPosition;\n"
1107 "in float offsetX;\n"
1108 "in float offsetY;\n"
1109 "void main()\n"
1110 "{\n"
1111 " vec4 p = vec4(vPosition, 1.);\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001112 " p.xy = p.xy * 0.25 - vec2(0.75) + vec2(offsetX, offsetY);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001113 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x : p.x + 1.0);\n"
1114 " gl_Position.yzw = p.yzw;\n"
1115 "}\n";
1116
Jamie Madill35cd7332018-12-02 12:03:33 -05001117 constexpr char kFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001118 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001119 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001120 "precision mediump float;\n"
1121 "out vec4 col;\n"
1122 "void main()\n"
1123 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001124 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001125 "}\n";
Martin Radev3c25ad02017-08-22 17:36:53 +03001126
1127 const int kViewWidth = 4;
1128 const int kViewHeight = 4;
1129 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001130 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001131 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev553590a2017-07-31 16:40:39 +03001132
1133 GLBuffer xOffsetVBO;
1134 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1135 const GLfloat xOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.0f};
1136 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, xOffsetData, GL_STATIC_DRAW);
1137 GLint xOffsetLoc = glGetAttribLocation(program, "offsetX");
1138 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1139 glVertexAttribDivisor(xOffsetLoc, 3);
1140 glEnableVertexAttribArray(xOffsetLoc);
1141
1142 GLBuffer yOffsetVBO;
1143 glBindBuffer(GL_ARRAY_BUFFER, yOffsetVBO);
1144 const GLfloat yOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1145 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, yOffsetData, GL_STATIC_DRAW);
1146 GLint yOffsetLoc = glGetAttribLocation(program, "offsetY");
1147 glVertexAttribDivisor(yOffsetLoc, 1);
1148 glVertexAttribPointer(yOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1149 glEnableVertexAttribArray(yOffsetLoc);
1150
Martin Radev67a8a012017-09-08 13:03:52 +03001151 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev553590a2017-07-31 16:40:39 +03001152 ASSERT_GL_NO_ERROR();
1153
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001154 resolveMultisampledFBO();
1155
Martin Radev67a8a012017-09-08 13:03:52 +03001156 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001157 {{255, 0, 0, 0}, {255, 0, 0, 0}, {255, 0, 0, 0}, {0, 255, 0, 0}},
1158 {{0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 0, 255}}};
1159 for (int view = 0; view < 2; ++view)
Martin Radev553590a2017-07-31 16:40:39 +03001160 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001161 for (int row = 0; row < 4; ++row)
Martin Radev553590a2017-07-31 16:40:39 +03001162 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001163 for (int col = 0; col < 4; ++col)
1164 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001165 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][row][col], 0,
1166 expectedGreenChannel[view][row][col]),
Martin Radev3c25ad02017-08-22 17:36:53 +03001167 GetViewColor(col, row, view));
1168 }
Martin Radev553590a2017-07-31 16:40:39 +03001169 }
1170 }
1171}
1172
1173// Test that different sequences of vertexAttribDivisor, useProgram and bindVertexArray in a
1174// multi-view context propagate the correct divisor to the driver.
Martin Radev3c25ad02017-08-22 17:36:53 +03001175TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
Martin Radev553590a2017-07-31 16:40:39 +03001176{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001177 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev553590a2017-07-31 16:40:39 +03001178 {
1179 return;
1180 }
1181
Olli Etuaho4836acc2018-08-20 15:23:18 +03001182 updateFBOs(1, 1, 2);
Martin Radev553590a2017-07-31 16:40:39 +03001183
1184 // Create multiview program.
Jamie Madill35cd7332018-12-02 12:03:33 -05001185 constexpr char kVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001186 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001187 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001188 "layout(num_views = 2) in;\n"
1189 "layout(location = 0) in vec2 vPosition;\n"
1190 "layout(location = 1) in float offsetX;\n"
1191 "void main()\n"
1192 "{\n"
1193 " vec4 p = vec4(vPosition, 0.0, 1.0);\n"
1194 " p.x += offsetX;\n"
1195 " gl_Position = p;\n"
1196 "}\n";
1197
Jamie Madill35cd7332018-12-02 12:03:33 -05001198 constexpr char kFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001199 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001200 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001201 "precision mediump float;\n"
1202 "out vec4 col;\n"
1203 "void main()\n"
1204 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001205 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001206 "}\n";
1207
Jamie Madill35cd7332018-12-02 12:03:33 -05001208 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev553590a2017-07-31 16:40:39 +03001209
Jamie Madill35cd7332018-12-02 12:03:33 -05001210 constexpr char kDummyVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001211 "#version 300 es\n"
1212 "layout(location = 0) in vec2 vPosition;\n"
1213 "layout(location = 1) in float offsetX;\n"
1214 "void main()\n"
1215 "{\n"
1216 " gl_Position = vec4(vPosition, 0.0, 1.0);\n"
1217 "}\n";
1218
Jamie Madill35cd7332018-12-02 12:03:33 -05001219 constexpr char kDummyFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001220 "#version 300 es\n"
1221 "precision mediump float;\n"
1222 "out vec4 col;\n"
1223 "void main()\n"
1224 "{\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001225 " col = vec4(0,0,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001226 "}\n";
1227
Jamie Madill35cd7332018-12-02 12:03:33 -05001228 ANGLE_GL_PROGRAM(dummyProgram, kDummyVS, kDummyFS);
Martin Radev553590a2017-07-31 16:40:39 +03001229
1230 GLBuffer xOffsetVBO;
1231 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1232 const GLfloat xOffsetData[12] = {0.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f,
1233 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f};
1234 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 12, xOffsetData, GL_STATIC_DRAW);
1235
1236 GLBuffer vertexVBO;
1237 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1238 Vector2 kQuadVertices[6] = {Vector2(-1.f, -1.f), Vector2(1.f, -1.f), Vector2(1.f, 1.f),
1239 Vector2(-1.f, -1.f), Vector2(1.f, 1.f), Vector2(-1.f, 1.f)};
1240 glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
1241
1242 GLVertexArray vao[2];
1243 for (size_t i = 0u; i < 2u; ++i)
1244 {
1245 glBindVertexArray(vao[i]);
1246
1247 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1248 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
1249 glEnableVertexAttribArray(0);
1250
1251 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1252 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
1253 glEnableVertexAttribArray(1);
1254 }
1255 ASSERT_GL_NO_ERROR();
1256
1257 glViewport(0, 0, 1, 1);
1258 glScissor(0, 0, 1, 1);
Martin Radeveef80e42017-08-11 14:44:57 +03001259 glEnable(GL_SCISSOR_TEST);
Martin Radev61bd9992017-08-11 13:10:55 +03001260 glClearColor(0, 0, 0, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001261
1262 // Clear the buffers, propagate divisor to the driver, bind the vao and keep it active.
1263 // It is necessary to call draw, so that the divisor is propagated and to guarantee that dirty
1264 // bits are cleared.
1265 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001266 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1267 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001268 glBindVertexArray(vao[0]);
1269 glVertexAttribDivisor(1, 0);
1270 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1271 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001272 ASSERT_GL_NO_ERROR();
1273
1274 // Check that vertexAttribDivisor uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001275 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001276 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001277 glUseProgram(program);
1278 glVertexAttribDivisor(1, 1);
1279 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001280
1281 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001282 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1283 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001284
1285 // Clear the buffers and propagate divisor to the driver.
1286 // We keep the vao active and propagate the divisor to guarantee that there are no unresolved
1287 // dirty bits when useProgram is called.
1288 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001289 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1290 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001291 glVertexAttribDivisor(1, 1);
1292 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1293 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001294 ASSERT_GL_NO_ERROR();
1295
1296 // Check that useProgram uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001297 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001298 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001299 glUseProgram(program);
1300 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001301
1302 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001303 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1304 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001305
1306 // We go through similar steps as before.
1307 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001308 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1309 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001310 glVertexAttribDivisor(1, 1);
1311 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1312 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001313 ASSERT_GL_NO_ERROR();
1314
1315 // Check that bindVertexArray uses the number of views to update the divisor.
1316 {
1317 // Call useProgram with vao[1] being active to guarantee that useProgram will adjust the
1318 // divisor for vao[1] only.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001319 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001320 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001321 glBindVertexArray(vao[1]);
1322 glUseProgram(program);
1323 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001324 glBindVertexArray(0);
1325 ASSERT_GL_NO_ERROR();
1326 }
1327 // Bind vao[0] after useProgram is called to ensure that bindVertexArray is the call which
1328 // adjusts the divisor.
Martin Radevda8e2572017-09-12 17:21:16 +03001329 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001330 glBindVertexArray(vao[0]);
1331 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001332
1333 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001334 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1335 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001336}
1337
Martin Radev0d671c92017-08-10 16:41:52 +03001338// Test that no fragments pass the occlusion query for a multi-view vertex shader which always
1339// transforms geometry to be outside of the clip region.
Martin Radev3c25ad02017-08-22 17:36:53 +03001340TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryNothingVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001341{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001342 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1343 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001344
Jamie Madill35cd7332018-12-02 12:03:33 -05001345 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001346 "#version 300 es\n"
1347 "#extension GL_OVR_multiview : require\n"
1348 "layout(num_views = 2) in;\n"
1349 "in vec3 vPosition;\n"
1350 "void main()\n"
1351 "{\n"
1352 " gl_Position.x = 2.0;\n"
1353 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1354 "}\n";
1355
Jamie Madill35cd7332018-12-02 12:03:33 -05001356 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001357 "#version 300 es\n"
1358 "#extension GL_OVR_multiview : require\n"
1359 "precision mediump float;\n"
1360 "out vec4 col;\n"
1361 "void main()\n"
1362 "{\n"
1363 " col = vec4(1,0,0,0);\n"
1364 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001365 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001366 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001367
1368 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1369 ASSERT_GL_NO_ERROR();
1370 EXPECT_GL_FALSE(result);
1371}
1372
1373// Test that there are fragments passing the occlusion query if only view 0 can produce
1374// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001375TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyLeftVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001376{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001377 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1378 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001379
Jamie Madill35cd7332018-12-02 12:03:33 -05001380 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001381 "#version 300 es\n"
1382 "#extension GL_OVR_multiview : require\n"
1383 "layout(num_views = 2) in;\n"
1384 "in vec3 vPosition;\n"
1385 "void main()\n"
1386 "{\n"
1387 " gl_Position.x = gl_ViewID_OVR == 0u ? vPosition.x : 2.0;\n"
1388 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1389 "}\n";
1390
Jamie Madill35cd7332018-12-02 12:03:33 -05001391 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001392 "#version 300 es\n"
1393 "#extension GL_OVR_multiview : require\n"
1394 "precision mediump float;\n"
1395 "out vec4 col;\n"
1396 "void main()\n"
1397 "{\n"
1398 " col = vec4(1,0,0,0);\n"
1399 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001400 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001401 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001402
1403 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1404 ASSERT_GL_NO_ERROR();
1405 EXPECT_GL_TRUE(result);
1406}
1407
1408// Test that there are fragments passing the occlusion query if only view 1 can produce
1409// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001410TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyRightVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001411{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001412 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1413 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001414
Jamie Madill35cd7332018-12-02 12:03:33 -05001415 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001416 "#version 300 es\n"
1417 "#extension GL_OVR_multiview : require\n"
1418 "layout(num_views = 2) in;\n"
1419 "in vec3 vPosition;\n"
1420 "void main()\n"
1421 "{\n"
1422 " gl_Position.x = gl_ViewID_OVR == 1u ? vPosition.x : 2.0;\n"
1423 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1424 "}\n";
1425
Jamie Madill35cd7332018-12-02 12:03:33 -05001426 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001427 "#version 300 es\n"
1428 "#extension GL_OVR_multiview : require\n"
1429 "precision mediump float;\n"
1430 "out vec4 col;\n"
1431 "void main()\n"
1432 "{\n"
1433 " col = vec4(1,0,0,0);\n"
1434 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001435 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001436 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001437
1438 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1439 ASSERT_GL_NO_ERROR();
1440 EXPECT_GL_TRUE(result);
1441}
1442
Martin Radev41ac68e2017-06-06 12:16:58 +03001443// Test that a simple multi-view program which doesn't use gl_ViewID_OVR in neither VS nor FS
1444// compiles and links without an error.
1445TEST_P(MultiviewProgramGenerationTest, SimpleProgram)
1446{
1447 if (!requestMultiviewExtension())
1448 {
1449 return;
1450 }
1451
Jamie Madill35cd7332018-12-02 12:03:33 -05001452 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001453 "#version 300 es\n"
1454 "#extension GL_OVR_multiview : require\n"
1455 "layout(num_views = 2) in;\n"
1456 "void main()\n"
1457 "{\n"
1458 "}\n";
1459
Jamie Madill35cd7332018-12-02 12:03:33 -05001460 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001461 "#version 300 es\n"
1462 "#extension GL_OVR_multiview : require\n"
1463 "precision mediump float;\n"
1464 "void main()\n"
1465 "{\n"
1466 "}\n";
1467
Jamie Madill35cd7332018-12-02 12:03:33 -05001468 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001469 glUseProgram(program);
1470
1471 EXPECT_GL_NO_ERROR();
1472}
1473
1474// Test that a simple multi-view program which uses gl_ViewID_OVR only in VS compiles and links
1475// without an error.
1476TEST_P(MultiviewProgramGenerationTest, UseViewIDInVertexShader)
1477{
1478 if (!requestMultiviewExtension())
1479 {
1480 return;
1481 }
1482
Jamie Madill35cd7332018-12-02 12:03:33 -05001483 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001484 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001485 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001486 "layout(num_views = 2) in;\n"
1487 "void main()\n"
1488 "{\n"
1489 " if (gl_ViewID_OVR == 0u) {\n"
1490 " gl_Position = vec4(1,0,0,1);\n"
1491 " } else {\n"
1492 " gl_Position = vec4(-1,0,0,1);\n"
1493 " }\n"
1494 "}\n";
1495
Jamie Madill35cd7332018-12-02 12:03:33 -05001496 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001497 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001498 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001499 "precision mediump float;\n"
1500 "void main()\n"
1501 "{\n"
1502 "}\n";
1503
Jamie Madill35cd7332018-12-02 12:03:33 -05001504 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001505 glUseProgram(program);
1506
1507 EXPECT_GL_NO_ERROR();
1508}
1509
1510// Test that a simple multi-view program which uses gl_ViewID_OVR only in FS compiles and links
1511// without an error.
1512TEST_P(MultiviewProgramGenerationTest, UseViewIDInFragmentShader)
1513{
1514 if (!requestMultiviewExtension())
1515 {
1516 return;
1517 }
1518
Jamie Madill35cd7332018-12-02 12:03:33 -05001519 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001520 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001521 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001522 "layout(num_views = 2) in;\n"
1523 "void main()\n"
1524 "{\n"
1525 "}\n";
1526
Jamie Madill35cd7332018-12-02 12:03:33 -05001527 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001528 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001529 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001530 "precision mediump float;\n"
1531 "out vec4 col;\n"
1532 "void main()\n"
1533 "{\n"
1534 " if (gl_ViewID_OVR == 0u) {\n"
1535 " col = vec4(1,0,0,1);\n"
1536 " } else {\n"
1537 " col = vec4(-1,0,0,1);\n"
1538 " }\n"
1539 "}\n";
1540
Jamie Madill35cd7332018-12-02 12:03:33 -05001541 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001542 glUseProgram(program);
1543
1544 EXPECT_GL_NO_ERROR();
1545}
1546
Martin Radev61bd9992017-08-11 13:10:55 +03001547// The test checks that GL_POINTS is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001548TEST_P(MultiviewRenderPrimitiveTest, Points)
Martin Radev61bd9992017-08-11 13:10:55 +03001549{
1550 if (!requestMultiviewExtension())
1551 {
1552 return;
1553 }
1554
Geoff Lang25858162017-11-06 11:25:58 -05001555 // Test failing on P400 graphics card (anglebug.com/2228)
1556 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1557
Jamie Madill35cd7332018-12-02 12:03:33 -05001558 constexpr char kVS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001559 "#version 300 es\n"
1560 "#extension GL_OVR_multiview : require\n"
1561 "layout(num_views = 2) in;\n"
1562 "layout(location=0) in vec2 vPosition;\n"
1563 "void main()\n"
1564 "{\n"
1565 " gl_PointSize = 1.0;\n"
1566 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1567 "}\n";
1568
Jamie Madill35cd7332018-12-02 12:03:33 -05001569 constexpr char kFS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001570 "#version 300 es\n"
1571 "#extension GL_OVR_multiview : require\n"
1572 "precision mediump float;\n"
1573 "out vec4 col;\n"
1574 "void main()\n"
1575 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001576 " col = vec4(0,1,0,1);\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001577 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001578 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev61bd9992017-08-11 13:10:55 +03001579 glUseProgram(program);
1580
Martin Radev3c25ad02017-08-22 17:36:53 +03001581 const int kViewWidth = 4;
1582 const int kViewHeight = 2;
1583 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001584 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001585
1586 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 1)};
1587 std::vector<Vector2> vertexDataInClipSpace =
1588 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1589 setupGeometry(vertexDataInClipSpace);
1590
1591 glDrawArrays(GL_POINTS, 0, 2);
1592
Martin Radev67a8a012017-09-08 13:03:52 +03001593 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001594 {{255, 0, 0, 0}, {0, 0, 0, 255}}, {{255, 0, 0, 0}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001595 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001596}
1597
1598// The test checks that GL_LINES is correctly rendered.
1599// The behavior of this test is not guaranteed by the spec:
1600// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1601// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1602// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1603// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001604TEST_P(MultiviewRenderPrimitiveTest, Lines)
Martin Radev61bd9992017-08-11 13:10:55 +03001605{
1606 if (!requestMultiviewExtension())
1607 {
1608 return;
1609 }
1610
Martin Radevced5c862017-08-17 16:05:29 +03001611 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001612 ASSERT_NE(program, 0u);
1613 glUseProgram(program);
1614 ASSERT_GL_NO_ERROR();
1615
Martin Radev3c25ad02017-08-22 17:36:53 +03001616 const int kViewWidth = 4;
1617 const int kViewHeight = 2;
1618 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001619 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001620
1621 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(4, 0)};
1622 std::vector<Vector2> vertexDataInClipSpace =
1623 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1624 setupGeometry(vertexDataInClipSpace);
1625
1626 glDrawArrays(GL_LINES, 0, 2);
1627
Martin Radev67a8a012017-09-08 13:03:52 +03001628 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001629 {{255, 255, 255, 255}, {0, 0, 0, 0}}, {{255, 255, 255, 255}, {0, 0, 0, 0}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001630 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001631
1632 glDeleteProgram(program);
1633}
1634
1635// The test checks that GL_LINE_STRIP is correctly rendered.
1636// The behavior of this test is not guaranteed by the spec:
1637// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1638// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1639// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1640// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001641TEST_P(MultiviewRenderPrimitiveTest, LineStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001642{
1643 if (!requestMultiviewExtension())
1644 {
1645 return;
1646 }
1647
Martin Radevced5c862017-08-17 16:05:29 +03001648 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001649 ASSERT_NE(program, 0u);
1650 glUseProgram(program);
1651 ASSERT_GL_NO_ERROR();
1652
Martin Radev3c25ad02017-08-22 17:36:53 +03001653 const int kViewWidth = 4;
1654 const int kViewHeight = 2;
1655 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001656 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001657
1658 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 2)};
1659 std::vector<Vector2> vertexDataInClipSpace =
1660 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1661 setupGeometry(vertexDataInClipSpace);
1662
1663 glDrawArrays(GL_LINE_STRIP, 0, 3);
1664
Martin Radev67a8a012017-09-08 13:03:52 +03001665 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001666 {{255, 255, 255, 255}, {0, 0, 0, 255}}, {{255, 255, 255, 255}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001667 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001668
1669 glDeleteProgram(program);
1670}
1671
1672// The test checks that GL_LINE_LOOP is correctly rendered.
1673// The behavior of this test is not guaranteed by the spec:
1674// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1675// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1676// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1677// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001678TEST_P(MultiviewRenderPrimitiveTest, LineLoop)
Martin Radev61bd9992017-08-11 13:10:55 +03001679{
1680 if (!requestMultiviewExtension())
1681 {
1682 return;
1683 }
1684
Martin Radevced5c862017-08-17 16:05:29 +03001685 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001686 ASSERT_NE(program, 0u);
1687 glUseProgram(program);
1688 ASSERT_GL_NO_ERROR();
1689
Martin Radev3c25ad02017-08-22 17:36:53 +03001690 const int kViewWidth = 4;
1691 const int kViewHeight = 4;
1692 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001693 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001694
1695 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 3),
1696 Vector2I(0, 3)};
1697 std::vector<Vector2> vertexDataInClipSpace =
1698 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 4);
1699 setupGeometry(vertexDataInClipSpace);
1700
1701 glDrawArrays(GL_LINE_LOOP, 0, 4);
1702
Martin Radev67a8a012017-09-08 13:03:52 +03001703 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001704 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}},
1705 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001706 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001707
1708 glDeleteProgram(program);
1709}
1710
1711// The test checks that GL_TRIANGLE_STRIP is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001712TEST_P(MultiviewRenderPrimitiveTest, TriangleStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001713{
1714 if (!requestMultiviewExtension())
1715 {
1716 return;
1717 }
1718
Martin Radevced5c862017-08-17 16:05:29 +03001719 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001720 ASSERT_NE(program, 0u);
1721 glUseProgram(program);
1722 ASSERT_GL_NO_ERROR();
1723
1724 std::vector<Vector2> vertexDataInClipSpace = {Vector2(1.0f, 0.0f), Vector2(0.0f, 0.0f),
1725 Vector2(1.0f, 1.0f), Vector2(0.0f, 1.0f)};
1726 setupGeometry(vertexDataInClipSpace);
1727
Martin Radev3c25ad02017-08-22 17:36:53 +03001728 const int kViewWidth = 2;
1729 const int kViewHeight = 2;
1730 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001731 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001732
1733 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1734
Martin Radev67a8a012017-09-08 13:03:52 +03001735 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1736 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1737 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001738
1739 glDeleteProgram(program);
1740}
1741
1742// The test checks that GL_TRIANGLE_FAN is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001743TEST_P(MultiviewRenderPrimitiveTest, TriangleFan)
Martin Radev61bd9992017-08-11 13:10:55 +03001744{
1745 if (!requestMultiviewExtension())
1746 {
1747 return;
1748 }
1749
Martin Radevced5c862017-08-17 16:05:29 +03001750 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001751 ASSERT_NE(program, 0u);
1752 glUseProgram(program);
1753 ASSERT_GL_NO_ERROR();
1754
1755 std::vector<Vector2> vertexDataInClipSpace = {Vector2(0.0f, 0.0f), Vector2(0.0f, 1.0f),
1756 Vector2(1.0f, 1.0f), Vector2(1.0f, 0.0f)};
1757 setupGeometry(vertexDataInClipSpace);
1758
Martin Radev3c25ad02017-08-22 17:36:53 +03001759 const int kViewWidth = 2;
1760 const int kViewHeight = 2;
1761 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001762 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001763
1764 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1765
Martin Radev67a8a012017-09-08 13:03:52 +03001766 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1767 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1768 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001769
1770 glDeleteProgram(program);
1771}
1772
1773// Test that rendering enlarged points and lines does not leak fragments outside of the views'
1774// bounds. The test does not rely on the actual line width being greater than 1.0.
Martin Radev3c25ad02017-08-22 17:36:53 +03001775TEST_P(MultiviewSideBySideRenderTest, NoLeakingFragments)
Martin Radev61bd9992017-08-11 13:10:55 +03001776{
1777 if (!requestMultiviewExtension())
1778 {
1779 return;
1780 }
1781
Olli Etuaho9259fd02018-08-22 12:12:00 +03001782 GLTexture colorTexture;
Martin Radev61bd9992017-08-11 13:10:55 +03001783
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001784 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0, 2, 1, 2,
Olli Etuaho9259fd02018-08-22 12:12:00 +03001785 colorTexture, 0u, 0u);
1786
1787 GLFramebuffer drawFramebuffer;
1788 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFramebuffer);
Martin Radev61bd9992017-08-11 13:10:55 +03001789 GLint viewportOffsets[4] = {1, 0, 3, 0};
1790 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
Olli Etuaho9259fd02018-08-22 12:12:00 +03001791 colorTexture, 0, 2, &viewportOffsets[0]);
1792
1793 GLFramebuffer readFramebuffer;
1794 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
1795 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
1796 0);
1797
1798 ASSERT_GL_NO_ERROR();
Martin Radev61bd9992017-08-11 13:10:55 +03001799
1800 glViewport(0, 0, 1, 1);
1801 glScissor(0, 0, 1, 1);
1802 glEnable(GL_SCISSOR_TEST);
1803
Jamie Madill35cd7332018-12-02 12:03:33 -05001804 constexpr char kVS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001805 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001806 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001807 "layout(num_views = 2) in;\n"
1808 "layout(location=0) in vec2 vPosition;\n"
1809 "void main()\n"
1810 "{\n"
1811 " gl_PointSize = 10.0;\n"
1812 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1813 "}\n";
1814
Jamie Madill35cd7332018-12-02 12:03:33 -05001815 constexpr char kFS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001816 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001817 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001818 "precision mediump float;\n"
1819 "out vec4 col;\n"
1820 "void main()\n"
1821 "{\n"
1822 " if (gl_ViewID_OVR == 0u) {\n"
1823 " col = vec4(1,0,0,1);\n"
1824 " } else {\n"
1825 " col = vec4(0,1,0,1);\n"
1826 " }\n"
1827 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001828 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev61bd9992017-08-11 13:10:55 +03001829 glUseProgram(program);
1830
1831 const std::vector<Vector2I> &windowCoordinates = {Vector2I(0, 0), Vector2I(2, 0)};
1832 const std::vector<Vector2> &vertexDataInClipSpace =
1833 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 1, 1);
Martin Radev3c25ad02017-08-22 17:36:53 +03001834
1835 GLBuffer vbo;
1836 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1837 glBufferData(GL_ARRAY_BUFFER, vertexDataInClipSpace.size() * sizeof(Vector2),
1838 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
1839 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -05001840 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +03001841
1842 // Test rendering points.
1843 {
1844 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1845 glDrawArrays(GL_POINTS, 0, 2);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001846 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001847 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001848 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001849 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1850 }
1851
1852 // Test rendering lines.
1853 {
1854 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1855 glLineWidth(10.f);
1856 glDrawArrays(GL_LINES, 0, 2);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001857 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001858 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001859 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001860 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1861 }
1862}
1863
Martin Radev0abb7a22017-08-28 15:34:45 +03001864// Verify that re-linking a program adjusts the attribute divisor.
1865// The test uses instacing to draw for each view a strips of two red quads and two blue quads next
1866// to each other. The quads' position and color depend on the corresponding attribute divisors.
1867TEST_P(MultiviewRenderTest, ProgramRelinkUpdatesAttribDivisor)
1868{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001869 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev0abb7a22017-08-28 15:34:45 +03001870 {
1871 return;
1872 }
1873
Corentin Wallez02cd1522018-08-22 13:46:21 +02001874 // Looks like an incorrect D3D debug layer message is generated on Windows AMD and NVIDIA.
Olli Etuaho44ae8992018-08-20 15:37:09 +03001875 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001876 if (IsWindows() && IsD3D11())
1877 {
1878 ignoreD3D11SDKLayersWarnings();
1879 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001880
Martin Radev0abb7a22017-08-28 15:34:45 +03001881 const int kViewWidth = 4;
1882 const int kViewHeight = 1;
1883 const int kNumViews = 2;
1884
Jamie Madill35cd7332018-12-02 12:03:33 -05001885 constexpr char kFS[] =
Martin Radev0abb7a22017-08-28 15:34:45 +03001886 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001887 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001888 "precision mediump float;\n"
1889 "in vec4 oColor;\n"
1890 "out vec4 col;\n"
1891 "void main()\n"
1892 "{\n"
1893 " col = oColor;\n"
1894 "}\n";
1895
1896 auto generateVertexShaderSource = [](int numViews) -> std::string {
1897 std::string source =
1898 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001899 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001900 "layout(num_views = " +
1901 ToString(numViews) +
1902 ") in;\n"
1903 "in vec3 vPosition;\n"
1904 "in float vOffsetX;\n"
1905 "in vec4 vColor;\n"
1906 "out vec4 oColor;\n"
1907 "void main()\n"
1908 "{\n"
1909 " vec4 p = vec4(vPosition, 1.);\n"
1910 " p.x = p.x * 0.25 - 0.75 + vOffsetX;\n"
1911 " oColor = vColor;\n"
1912 " gl_Position = p;\n"
1913 "}\n";
1914 return source;
1915 };
1916
1917 std::string vsSource = generateVertexShaderSource(kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001918 ANGLE_GL_PROGRAM(program, vsSource.c_str(), kFS);
Martin Radev0abb7a22017-08-28 15:34:45 +03001919 glUseProgram(program);
1920
1921 GLint positionLoc;
1922 GLBuffer xOffsetVBO;
1923 GLint xOffsetLoc;
1924 GLBuffer colorVBO;
1925 GLint colorLoc;
1926
1927 {
1928 // Initialize buffers and setup attributes.
1929 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1930 const GLfloat kXOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1931 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, kXOffsetData, GL_STATIC_DRAW);
1932 xOffsetLoc = glGetAttribLocation(program, "vOffsetX");
1933 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1934 glVertexAttribDivisor(xOffsetLoc, 1);
1935 glEnableVertexAttribArray(xOffsetLoc);
1936
1937 glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
1938 const GLColor kColors[2] = {GLColor::red, GLColor::blue};
1939 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 2, kColors, GL_STATIC_DRAW);
1940 colorLoc = glGetAttribLocation(program, "vColor");
1941 glVertexAttribDivisor(colorLoc, 2);
1942 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1943 glEnableVertexAttribArray(colorLoc);
1944
1945 positionLoc = glGetAttribLocation(program, "vPosition");
1946 }
1947
1948 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03001949 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001950
Martin Radev67a8a012017-09-08 13:03:52 +03001951 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001952 ASSERT_GL_NO_ERROR();
1953
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001954 resolveMultisampledFBO();
Martin Radev0abb7a22017-08-28 15:34:45 +03001955 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
1956 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, 0));
1957 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, 0));
1958 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, 0));
1959 }
1960
1961 {
1962 const int kNewNumViews = 3;
1963 vsSource = generateVertexShaderSource(kNewNumViews);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001964 updateFBOs(kViewWidth, kViewHeight, kNewNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001965
Jamie Madill35cd7332018-12-02 12:03:33 -05001966 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource.c_str());
Martin Radev0abb7a22017-08-28 15:34:45 +03001967 ASSERT_NE(0u, vs);
Jamie Madill35cd7332018-12-02 12:03:33 -05001968 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
Martin Radev0abb7a22017-08-28 15:34:45 +03001969 ASSERT_NE(0u, fs);
1970
1971 GLint numAttachedShaders = 0;
1972 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
1973
1974 GLuint attachedShaders[2] = {0u};
1975 glGetAttachedShaders(program, numAttachedShaders, nullptr, attachedShaders);
1976 for (int i = 0; i < 2; ++i)
1977 {
1978 glDetachShader(program, attachedShaders[i]);
1979 }
1980
1981 glAttachShader(program, vs);
1982 glDeleteShader(vs);
1983
1984 glAttachShader(program, fs);
1985 glDeleteShader(fs);
1986
1987 glBindAttribLocation(program, positionLoc, "vPosition");
1988 glBindAttribLocation(program, xOffsetLoc, "vOffsetX");
1989 glBindAttribLocation(program, colorLoc, "vColor");
1990
1991 glLinkProgram(program);
1992
Martin Radev67a8a012017-09-08 13:03:52 +03001993 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001994 ASSERT_GL_NO_ERROR();
1995
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001996 resolveMultisampledFBO();
Martin Radev0abb7a22017-08-28 15:34:45 +03001997 for (int i = 0; i < kNewNumViews; ++i)
1998 {
1999 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, i));
2000 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, i));
2001 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, i));
2002 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, i));
2003 }
2004 }
2005}
2006
Martin Radevced5c862017-08-17 16:05:29 +03002007// Test that useProgram applies the number of views in computing the final value of the attribute
2008// divisor.
2009TEST_P(MultiviewRenderTest, DivisorUpdatedOnProgramChange)
2010{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002011 if (!requestMultiviewExtension(isMultisampled()))
Martin Radevced5c862017-08-17 16:05:29 +03002012 {
2013 return;
2014 }
2015
Geoff Lang25858162017-11-06 11:25:58 -05002016 // Test failing on P400 graphics card (anglebug.com/2228)
2017 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
2018
Olli Etuaho44ae8992018-08-20 15:37:09 +03002019 // Looks like an incorrect D3D debug layer message is generated on Windows / AMD.
2020 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03002021 if (IsWindows() && IsD3D11())
2022 {
2023 ignoreD3D11SDKLayersWarnings();
2024 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03002025
Martin Radevced5c862017-08-17 16:05:29 +03002026 GLVertexArray vao;
2027 glBindVertexArray(vao);
2028 GLBuffer vbo;
2029 glBindBuffer(GL_ARRAY_BUFFER, vbo);
2030 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(1, 0), Vector2I(2, 0),
2031 Vector2I(3, 0)};
2032 std::vector<Vector2> vertexDataInClipSpace =
2033 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 1);
2034 // Fill with x positions so that the resulting clip space coordinate fails the clip test.
2035 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2) * vertexDataInClipSpace.size(),
2036 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
2037 glEnableVertexAttribArray(0);
2038 glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, nullptr);
2039 glVertexAttribDivisor(0, 1);
2040 ASSERT_GL_NO_ERROR();
2041
2042 // Create a program and fbo with N views and draw N instances of a point horizontally.
2043 for (int numViews = 2; numViews <= 4; ++numViews)
2044 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03002045 updateFBOs(4, 1, numViews);
Martin Radevced5c862017-08-17 16:05:29 +03002046 ASSERT_GL_NO_ERROR();
2047
2048 GLuint program = CreateSimplePassthroughProgram(numViews);
2049 ASSERT_NE(program, 0u);
2050 glUseProgram(program);
2051 ASSERT_GL_NO_ERROR();
2052
2053 glDrawArraysInstanced(GL_POINTS, 0, 1, numViews);
2054
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002055 resolveMultisampledFBO();
Martin Radevced5c862017-08-17 16:05:29 +03002056 for (int view = 0; view < numViews; ++view)
2057 {
2058 for (int j = 0; j < numViews; ++j)
2059 {
Martin Radev67a8a012017-09-08 13:03:52 +03002060 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03002061 }
2062 for (int j = numViews; j < 4; ++j)
2063 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03002064 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03002065 }
2066 }
2067
2068 glDeleteProgram(program);
2069 }
2070}
2071
Martin Radev72b4e1e2017-08-31 15:42:56 +03002072// The test checks that gl_ViewID_OVR is correctly propagated to the fragment shader.
2073TEST_P(MultiviewRenderTest, SelectColorBasedOnViewIDOVR)
2074{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002075 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev72b4e1e2017-08-31 15:42:56 +03002076 {
2077 return;
2078 }
2079
Jamie Madill35cd7332018-12-02 12:03:33 -05002080 constexpr char kVS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002081 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002082 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002083 "layout(num_views = 3) in;\n"
2084 "in vec3 vPosition;\n"
2085 "void main()\n"
2086 "{\n"
2087 " gl_Position = vec4(vPosition, 1.);\n"
2088 "}\n";
2089
Jamie Madill35cd7332018-12-02 12:03:33 -05002090 constexpr char kFS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002091 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002092 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002093 "precision mediump float;\n"
2094 "out vec4 col;\n"
2095 "void main()\n"
2096 "{\n"
2097 " if (gl_ViewID_OVR == 0u) {\n"
2098 " col = vec4(1,0,0,1);\n"
2099 " } else if (gl_ViewID_OVR == 1u) {\n"
2100 " col = vec4(0,1,0,1);\n"
2101 " } else if (gl_ViewID_OVR == 2u) {\n"
2102 " col = vec4(0,0,1,1);\n"
2103 " } else {\n"
2104 " col = vec4(0,0,0,0);\n"
2105 " }\n"
2106 "}\n";
2107
Olli Etuaho4836acc2018-08-20 15:23:18 +03002108 updateFBOs(1, 1, 3);
Jamie Madill35cd7332018-12-02 12:03:33 -05002109 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev72b4e1e2017-08-31 15:42:56 +03002110
2111 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2112 ASSERT_GL_NO_ERROR();
2113
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002114 resolveMultisampledFBO();
Martin Radev72b4e1e2017-08-31 15:42:56 +03002115 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2116 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2117 EXPECT_EQ(GLColor::blue, GetViewColor(0, 0, 2));
2118}
2119
2120// The test checks that the inactive layers of a 2D texture array are not written to by a
2121// multi-view program.
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002122TEST_P(MultiviewLayeredRenderTest, RenderToSubrangeOfLayers)
Martin Radev72b4e1e2017-08-31 15:42:56 +03002123{
2124 if (!requestMultiviewExtension())
2125 {
2126 return;
2127 }
2128
Jamie Madill35cd7332018-12-02 12:03:33 -05002129 constexpr char kVS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002130 "#version 300 es\n"
2131 "#extension GL_OVR_multiview : require\n"
2132 "layout(num_views = 2) in;\n"
2133 "in vec3 vPosition;\n"
2134 "void main()\n"
2135 "{\n"
2136 " gl_Position = vec4(vPosition, 1.);\n"
2137 "}\n";
2138
Jamie Madill35cd7332018-12-02 12:03:33 -05002139 constexpr char kFS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002140 "#version 300 es\n"
2141 "#extension GL_OVR_multiview : require\n"
2142 "precision mediump float;\n"
2143 "out vec4 col;\n"
2144 "void main()\n"
2145 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002146 " col = vec4(0,1,0,1);\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002147 "}\n";
2148
Olli Etuaho4836acc2018-08-20 15:23:18 +03002149 updateFBOs(1, 1, 2, 4, 1);
Jamie Madill35cd7332018-12-02 12:03:33 -05002150 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev72b4e1e2017-08-31 15:42:56 +03002151
2152 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2153 ASSERT_GL_NO_ERROR();
2154
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002155 resolveMultisampledFBO();
Martin Radev72b4e1e2017-08-31 15:42:56 +03002156 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +03002157 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2158 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 2));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002159 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 3));
2160}
2161
Martin Radevc1d4e552017-08-21 12:01:10 +03002162// The D3D11 renderer uses a GS whenever the varyings are flat interpolated which can cause
2163// potential bugs if the view is selected in the VS. The test contains a program in which the
2164// gl_InstanceID is passed as a flat varying to the fragment shader where it is used to discard the
2165// fragment if its value is negative. The gl_InstanceID should never be negative and that branch is
2166// never taken. One quad is drawn and the color is selected based on the ViewID - red for view 0 and
2167// green for view 1.
2168TEST_P(MultiviewRenderTest, FlatInterpolation)
Martin Radev3c25ad02017-08-22 17:36:53 +03002169{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002170 if (!requestMultiviewExtension(isMultisampled()))
Martin Radevc1d4e552017-08-21 12:01:10 +03002171 {
2172 return;
2173 }
2174
Jamie Madill35cd7332018-12-02 12:03:33 -05002175 constexpr char kVS[] =
Martin Radevc1d4e552017-08-21 12:01:10 +03002176 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002177 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002178 "layout(num_views = 2) in;\n"
2179 "in vec3 vPosition;\n"
2180 "flat out int oInstanceID;\n"
2181 "void main()\n"
2182 "{\n"
2183 " gl_Position = vec4(vPosition, 1.);\n"
2184 " oInstanceID = gl_InstanceID;\n"
2185 "}\n";
2186
Jamie Madill35cd7332018-12-02 12:03:33 -05002187 constexpr char kFS[] =
Martin Radevc1d4e552017-08-21 12:01:10 +03002188 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002189 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002190 "precision mediump float;\n"
2191 "flat in int oInstanceID;\n"
2192 "out vec4 col;\n"
2193 "void main()\n"
2194 "{\n"
2195 " if (oInstanceID < 0) {\n"
2196 " discard;\n"
2197 " }\n"
2198 " if (gl_ViewID_OVR == 0u) {\n"
2199 " col = vec4(1,0,0,1);\n"
2200 " } else {\n"
2201 " col = vec4(0,1,0,1);\n"
2202 " }\n"
2203 "}\n";
2204
Olli Etuaho4836acc2018-08-20 15:23:18 +03002205 updateFBOs(1, 1, 2);
Jamie Madill35cd7332018-12-02 12:03:33 -05002206 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radevc1d4e552017-08-21 12:01:10 +03002207
2208 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2209 ASSERT_GL_NO_ERROR();
2210
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002211 resolveMultisampledFBO();
Martin Radevc1d4e552017-08-21 12:01:10 +03002212 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2213 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev3c25ad02017-08-22 17:36:53 +03002214}
2215
Olli Etuaho604d8732018-07-20 11:02:43 +03002216// This test assigns gl_ViewID_OVR to a flat int varying and then sets the color based on that
2217// varying in the fragment shader.
2218TEST_P(MultiviewRenderTest, FlatInterpolation2)
2219{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002220 if (!requestMultiviewExtension(isMultisampled()))
Olli Etuaho604d8732018-07-20 11:02:43 +03002221 {
2222 return;
2223 }
2224
Jamie Madill35cd7332018-12-02 12:03:33 -05002225 constexpr char kVS[] =
Olli Etuaho604d8732018-07-20 11:02:43 +03002226 "#version 300 es\n"
2227 "#extension GL_OVR_multiview : require\n"
2228 "layout(num_views = 2) in;\n"
2229 "in vec3 vPosition;\n"
2230 "flat out int flatVarying;\n"
2231 "void main()\n"
2232 "{\n"
2233 " gl_Position = vec4(vPosition, 1.);\n"
2234 " flatVarying = int(gl_ViewID_OVR);\n"
2235 "}\n";
2236
Jamie Madill35cd7332018-12-02 12:03:33 -05002237 constexpr char kFS[] =
Olli Etuaho604d8732018-07-20 11:02:43 +03002238 "#version 300 es\n"
2239 "#extension GL_OVR_multiview : require\n"
2240 "precision mediump float;\n"
2241 "flat in int flatVarying;\n"
2242 "out vec4 col;\n"
2243 "void main()\n"
2244 "{\n"
2245 " if (flatVarying == 0) {\n"
2246 " col = vec4(1,0,0,1);\n"
2247 " } else {\n"
2248 " col = vec4(0,1,0,1);\n"
2249 " }\n"
2250 "}\n";
2251
Olli Etuaho4836acc2018-08-20 15:23:18 +03002252 updateFBOs(1, 1, 2);
Jamie Madill35cd7332018-12-02 12:03:33 -05002253 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho604d8732018-07-20 11:02:43 +03002254
2255 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2256 ASSERT_GL_NO_ERROR();
2257
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002258 resolveMultisampledFBO();
Olli Etuaho604d8732018-07-20 11:02:43 +03002259 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2260 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2261}
2262
Martin Radev265a6d42017-09-12 16:51:37 +03002263// The test is added to cover a bug which resulted in the viewport/scissor and viewport offsets not
2264// being correctly applied.
2265TEST_P(MultiviewSideBySideRenderTest, ViewportOffsetsAppliedBugCoverage)
2266{
2267 if (!requestMultiviewExtension())
2268 {
2269 return;
2270 }
2271
Olli Etuaho4836acc2018-08-20 15:23:18 +03002272 updateFBOs(1, 1, 2);
Martin Radev265a6d42017-09-12 16:51:37 +03002273
2274 // Create multiview program.
Jamie Madill35cd7332018-12-02 12:03:33 -05002275 constexpr char kVS[] =
Martin Radev265a6d42017-09-12 16:51:37 +03002276 "#version 300 es\n"
2277 "#extension GL_OVR_multiview : require\n"
2278 "layout(num_views = 2) in;\n"
2279 "layout(location = 0) in vec3 vPosition;\n"
2280 "void main()\n"
2281 "{\n"
2282 " gl_Position = vec4(vPosition, 1.0);\n"
2283 "}\n";
2284
Jamie Madill35cd7332018-12-02 12:03:33 -05002285 constexpr char kFS[] =
Martin Radev265a6d42017-09-12 16:51:37 +03002286 "#version 300 es\n"
2287 "#extension GL_OVR_multiview : require\n"
2288 "precision mediump float;\n"
2289 "out vec4 col;\n"
2290 "void main()\n"
2291 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002292 " col = vec4(0,1,0,1);\n"
Martin Radev265a6d42017-09-12 16:51:37 +03002293 "}\n";
2294
Jamie Madill35cd7332018-12-02 12:03:33 -05002295 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev265a6d42017-09-12 16:51:37 +03002296
2297 glViewport(0, 0, 1, 1);
2298 glScissor(0, 0, 1, 1);
2299 glEnable(GL_SCISSOR_TEST);
2300 glClearColor(0, 0, 0, 1);
2301
2302 // Bind the default FBO and make sure that the state is synchronized.
2303 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2304 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2305 ASSERT_GL_NO_ERROR();
2306
2307 // Draw and check that both views are rendered to.
Olli Etuaho4836acc2018-08-20 15:23:18 +03002308 bindMemberDrawFramebuffer();
Martin Radev265a6d42017-09-12 16:51:37 +03002309 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev67a8a012017-09-08 13:03:52 +03002310
Martin Radev265a6d42017-09-12 16:51:37 +03002311 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
Martin Radev67a8a012017-09-08 13:03:52 +03002312 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
2313 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev265a6d42017-09-12 16:51:37 +03002314}
2315
Olli Etuahof26b27e2018-08-17 11:01:19 +03002316MultiviewRenderTestParams SideBySideVertexShaderOpenGL(GLint majorVersion = 3,
2317 GLint minorVersion = 0)
Martin Radev3c25ad02017-08-22 17:36:53 +03002318{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002319 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002320 VertexShaderOpenGL(majorVersion, minorVersion));
Martin Radev3c25ad02017-08-22 17:36:53 +03002321}
2322
Olli Etuahof26b27e2018-08-17 11:01:19 +03002323MultiviewRenderTestParams LayeredVertexShaderOpenGL()
Martin Radev3c25ad02017-08-22 17:36:53 +03002324{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002325 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002326 VertexShaderOpenGL(3, 0));
Martin Radev3c25ad02017-08-22 17:36:53 +03002327}
2328
Olli Etuahof26b27e2018-08-17 11:01:19 +03002329MultiviewRenderTestParams SideBySideGeomShaderD3D11()
Martin Radev72b4e1e2017-08-31 15:42:56 +03002330{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002331 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002332 GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002333}
2334
Olli Etuahof26b27e2018-08-17 11:01:19 +03002335MultiviewRenderTestParams LayeredGeomShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002336{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002337 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
2338 GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002339}
2340
Olli Etuahof26b27e2018-08-17 11:01:19 +03002341MultiviewRenderTestParams SideBySideVertexShaderD3D11(GLint majorVersion = 3,
2342 GLint minorVersion = 0)
Martin Radevc1d4e552017-08-21 12:01:10 +03002343{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002344 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002345 VertexShaderD3D11(majorVersion, minorVersion));
Martin Radevc1d4e552017-08-21 12:01:10 +03002346}
2347
Olli Etuahof26b27e2018-08-17 11:01:19 +03002348MultiviewRenderTestParams LayeredVertexShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002349{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002350 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002351 VertexShaderD3D11(3, 0));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002352}
2353
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002354MultiviewRenderTestParams LayeredMultisampledVertexShaderOpenGL()
2355{
2356 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 2,
2357 VertexShaderOpenGL(3, 1));
2358}
2359
2360MultiviewRenderTestParams LayeredMultisampledVertexShaderD3D11()
2361{
2362 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 2,
2363 VertexShaderD3D11(3, 1));
2364}
2365
Jamie Madill04c084d2018-08-08 15:49:28 -04002366ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest,
Olli Etuaho44ae8992018-08-20 15:37:09 +03002367 VertexShaderOpenGL(3, 1),
2368 VertexShaderD3D11(3, 1));
Martin Radevced5c862017-08-17 16:05:29 +03002369ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002370 SideBySideVertexShaderOpenGL(),
2371 LayeredVertexShaderOpenGL(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002372 LayeredMultisampledVertexShaderOpenGL(),
Martin Radevc1d4e552017-08-21 12:01:10 +03002373 SideBySideGeomShaderD3D11(),
2374 SideBySideVertexShaderD3D11(),
2375 LayeredGeomShaderD3D11(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002376 LayeredVertexShaderD3D11(),
2377 LayeredMultisampledVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002378ANGLE_INSTANTIATE_TEST(MultiviewRenderTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002379 SideBySideVertexShaderOpenGL(),
2380 LayeredVertexShaderOpenGL(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002381 LayeredMultisampledVertexShaderOpenGL(),
Martin Radevc1d4e552017-08-21 12:01:10 +03002382 SideBySideGeomShaderD3D11(),
2383 SideBySideVertexShaderD3D11(),
2384 LayeredGeomShaderD3D11(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002385 LayeredVertexShaderD3D11(),
2386 LayeredMultisampledVertexShaderD3D11());
Martin Radevced5c862017-08-17 16:05:29 +03002387ANGLE_INSTANTIATE_TEST(MultiviewOcclusionQueryTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002388 SideBySideVertexShaderOpenGL(),
2389 LayeredVertexShaderOpenGL(),
2390 SideBySideGeomShaderD3D11(),
2391 SideBySideVertexShaderD3D11(),
2392 LayeredGeomShaderD3D11(),
2393 LayeredVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002394ANGLE_INSTANTIATE_TEST(MultiviewProgramGenerationTest,
Olli Etuaho4bcaf992018-08-17 17:18:28 +03002395 VertexShaderOpenGL(3, 0),
2396 GeomShaderD3D11(3, 0),
2397 VertexShaderD3D11(3, 0));
Martin Radevced5c862017-08-17 16:05:29 +03002398ANGLE_INSTANTIATE_TEST(MultiviewRenderPrimitiveTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002399 SideBySideVertexShaderOpenGL(),
2400 LayeredVertexShaderOpenGL(),
2401 SideBySideGeomShaderD3D11(),
2402 SideBySideVertexShaderD3D11(),
2403 LayeredGeomShaderD3D11(),
2404 LayeredVertexShaderD3D11());
Jamie Madill04c084d2018-08-08 15:49:28 -04002405ANGLE_INSTANTIATE_TEST(MultiviewSideBySideRenderTest,
2406 VertexShaderOpenGL(3, 0),
2407 GeomShaderD3D11(3, 0));
2408ANGLE_INSTANTIATE_TEST(MultiviewLayeredRenderTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));