blob: d297e94947b1887c245b8d63e51a812b72748a9a [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{
Jamie Madill3a256222018-12-08 09:56:39 -0500527 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev14a26ae2017-07-24 15:56:29 +0300528
Martin Radev14a26ae2017-07-24 15:56:29 +0300529 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Martin Radev14a26ae2017-07-24 15:56:29 +0300530
Jamie Madill35cd7332018-12-02 12:03:33 -0500531 constexpr char kFS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300532 "#version 300 es\n"
533 "#extension GL_OVR_multiview : require\n"
534 "precision mediump float;\n"
535 "void main()\n"
536 "{}\n";
537
Olli Etuaho44ae8992018-08-20 15:37:09 +0300538 GLVertexArray vao;
539 GLBuffer vertexBuffer;
540 GLBuffer indexBuffer;
541 initVAO(vao, vertexBuffer, indexBuffer);
542
543 GLFramebuffer fbo;
544 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
545
Martin Radev14a26ae2017-07-24 15:56:29 +0300546 GLBuffer commandBuffer;
547 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, commandBuffer);
548 const GLuint commandData[] = {1u, 1u, 0u, 0u, 0u};
549 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(GLuint) * 5u, &commandData[0], GL_STATIC_DRAW);
550 ASSERT_GL_NO_ERROR();
551
Olli Etuaho44ae8992018-08-20 15:37:09 +0300552 GLTexture tex2D;
553 initOnePixelColorTexture2D(tex2D);
554
Martin Radev14a26ae2017-07-24 15:56:29 +0300555 // Check for a GL_INVALID_OPERATION error with the framebuffer having 2 views.
556 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500557 constexpr char kVS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300558 "#version 300 es\n"
559 "#extension GL_OVR_multiview : require\n"
560 "layout(num_views = 2) in;\n"
561 "void main()\n"
562 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500563 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev14a26ae2017-07-24 15:56:29 +0300564 glUseProgram(program);
565
Olli Etuaho44ae8992018-08-20 15:37:09 +0300566 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
567 2, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300568
569 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
570 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
571
572 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
573 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
574 }
575
576 // Check that no errors are generated if the number of views is 1.
577 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500578 constexpr char kVS[] =
Martin Radev14a26ae2017-07-24 15:56:29 +0300579 "#version 300 es\n"
580 "#extension GL_OVR_multiview : require\n"
581 "layout(num_views = 1) in;\n"
582 "void main()\n"
583 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500584 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev14a26ae2017-07-24 15:56:29 +0300585 glUseProgram(program);
586
Olli Etuaho44ae8992018-08-20 15:37:09 +0300587 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
588 1, &viewportOffsets[0]);
Martin Radev14a26ae2017-07-24 15:56:29 +0300589
590 glDrawArraysIndirect(GL_TRIANGLES, nullptr);
591 EXPECT_GL_NO_ERROR();
592
593 glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr);
594 EXPECT_GL_NO_ERROR();
595 }
596}
597
Martin Radev7cf61662017-07-26 17:10:53 +0300598// The test verifies that glDraw*:
599// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer and
600// program differs.
601// 2) does not generate any error if the number of views is the same.
Martin Radev7cf61662017-07-26 17:10:53 +0300602TEST_P(MultiviewDrawValidationTest, NumViewsMismatch)
603{
Jamie Madill3a256222018-12-08 09:56:39 -0500604 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev7cf61662017-07-26 17:10:53 +0300605
606 const GLint viewportOffsets[4] = {0, 0, 2, 0};
607
Jamie Madill35cd7332018-12-02 12:03:33 -0500608 constexpr char kVS[] =
Martin Radev7cf61662017-07-26 17:10:53 +0300609 "#version 300 es\n"
610 "#extension GL_OVR_multiview : require\n"
611 "layout(num_views = 2) in;\n"
612 "void main()\n"
613 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500614 constexpr char kFS[] =
Martin Radev7cf61662017-07-26 17:10:53 +0300615 "#version 300 es\n"
616 "#extension GL_OVR_multiview : require\n"
617 "precision mediump float;\n"
618 "void main()\n"
619 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500620 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev7cf61662017-07-26 17:10:53 +0300621 glUseProgram(program);
622
Olli Etuaho44ae8992018-08-20 15:37:09 +0300623 GLVertexArray vao;
624 GLBuffer vertexBuffer;
625 GLBuffer indexBuffer;
626 initVAO(vao, vertexBuffer, indexBuffer);
627
628 GLFramebuffer fbo;
629 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
630
631 GLTexture tex2D;
632 initOnePixelColorTexture2D(tex2D);
633
Martin Radev7cf61662017-07-26 17:10:53 +0300634 // Check for a GL_INVALID_OPERATION error with the framebuffer and program having different
635 // number of views.
636 {
637 // The framebuffer has only 1 view.
Olli Etuaho44ae8992018-08-20 15:37:09 +0300638 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
639 1, &viewportOffsets[0]);
Martin Radev7cf61662017-07-26 17:10:53 +0300640
641 glDrawArrays(GL_TRIANGLES, 0, 3);
642 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
643
644 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
645 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
646 }
647
648 // Check that no errors are generated if the number of views in both program and draw
649 // framebuffer matches.
650 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300651 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
652 2, &viewportOffsets[0]);
Martin Radev7cf61662017-07-26 17:10:53 +0300653
654 glDrawArrays(GL_TRIANGLES, 0, 3);
655 EXPECT_GL_NO_ERROR();
656
657 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
658 EXPECT_GL_NO_ERROR();
659 }
Martin Radevda8e2572017-09-12 17:21:16 +0300660}
Martin Radev7cf61662017-07-26 17:10:53 +0300661
Martin Radevda8e2572017-09-12 17:21:16 +0300662// The test verifies that glDraw* generates an INVALID_OPERATION error if the program does not use
663// the multiview extension, but the active draw framebuffer has more than one view.
664TEST_P(MultiviewDrawValidationTest, NumViewsMismatchForNonMultiviewProgram)
665{
666 if (!requestMultiviewExtension())
Martin Radev7cf61662017-07-26 17:10:53 +0300667 {
Martin Radevda8e2572017-09-12 17:21:16 +0300668 return;
Martin Radev7cf61662017-07-26 17:10:53 +0300669 }
Martin Radevda8e2572017-09-12 17:21:16 +0300670
Jamie Madill35cd7332018-12-02 12:03:33 -0500671 constexpr char kVS[] =
Martin Radevda8e2572017-09-12 17:21:16 +0300672 "#version 300 es\n"
673 "void main()\n"
674 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500675 constexpr char kFS[] =
Martin Radevda8e2572017-09-12 17:21:16 +0300676 "#version 300 es\n"
677 "precision mediump float;\n"
678 "void main()\n"
679 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500680 ANGLE_GL_PROGRAM(programNoMultiview, kVS, kFS);
Martin Radevda8e2572017-09-12 17:21:16 +0300681 glUseProgram(programNoMultiview);
682
Olli Etuaho44ae8992018-08-20 15:37:09 +0300683 GLVertexArray vao;
684 GLBuffer vertexBuffer;
685 GLBuffer indexBuffer;
686 initVAO(vao, vertexBuffer, indexBuffer);
687
688 GLFramebuffer fbo;
689 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
690
691 GLTexture tex2D;
692 initOnePixelColorTexture2D(tex2D);
693
Martin Radevda8e2572017-09-12 17:21:16 +0300694 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Olli Etuaho44ae8992018-08-20 15:37:09 +0300695 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0, 2,
Martin Radevda8e2572017-09-12 17:21:16 +0300696 &viewportOffsets[0]);
697
698 glDrawArrays(GL_TRIANGLES, 0, 3);
699 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
700
701 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
702 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radev7cf61662017-07-26 17:10:53 +0300703}
704
Martin Radev7e69f762017-07-27 14:54:13 +0300705// The test verifies that glDraw*:
706// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
Jamie Madill3a256222018-12-08 09:56:39 -0500707// greater than 1 and there is an active not paused transform feedback object.
Martin Radev7e69f762017-07-27 14:54:13 +0300708// 2) does not generate any error if the number of views in the draw framebuffer is 1.
709TEST_P(MultiviewDrawValidationTest, ActiveTransformFeedback)
710{
Jamie Madill3a256222018-12-08 09:56:39 -0500711 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Martin Radev7e69f762017-07-27 14:54:13 +0300712
713 const GLint viewportOffsets[4] = {0, 0, 2, 0};
714
Jamie Madill35cd7332018-12-02 12:03:33 -0500715 constexpr char kVS[] = R"(#version 300 es
716out float tfVarying;
717void main()
718{
719 tfVarying = 1.0;
720})";
721
722 constexpr char kFS[] = R"(#version 300 es
723precision mediump float;
724void main()
725{})";
Jamie Madill04c084d2018-08-08 15:49:28 -0400726
Olli Etuaho3755c482017-10-13 15:40:26 +0300727 std::vector<std::string> tfVaryings;
Jamie Madill04c084d2018-08-08 15:49:28 -0400728 tfVaryings.emplace_back("tfVarying");
Jamie Madill35cd7332018-12-02 12:03:33 -0500729 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(singleViewProgram, kVS, kFS, tfVaryings,
Olli Etuaho3755c482017-10-13 15:40:26 +0300730 GL_SEPARATE_ATTRIBS);
Jamie Madill04c084d2018-08-08 15:49:28 -0400731
732 std::vector<std::string> dualViewTFVaryings;
733 dualViewTFVaryings.emplace_back("gl_Position");
734 ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(dualViewProgram, kDualViewVSSource, kDualViewFSSource,
735 dualViewTFVaryings, GL_SEPARATE_ATTRIBS);
Martin Radev7e69f762017-07-27 14:54:13 +0300736
Olli Etuaho44ae8992018-08-20 15:37:09 +0300737 GLVertexArray vao;
738 GLBuffer vertexBuffer;
739 GLBuffer indexBuffer;
740 initVAO(vao, vertexBuffer, indexBuffer);
741
Martin Radev7e69f762017-07-27 14:54:13 +0300742 GLBuffer tbo;
743 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);
Jamie Madill04c084d2018-08-08 15:49:28 -0400744 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 16u, nullptr, GL_STATIC_DRAW);
Martin Radev7e69f762017-07-27 14:54:13 +0300745
746 GLTransformFeedback transformFeedback;
747 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
Olli Etuaho3755c482017-10-13 15:40:26 +0300748
749 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
750
Jamie Madill04c084d2018-08-08 15:49:28 -0400751 glUseProgram(dualViewProgram);
Martin Radev7e69f762017-07-27 14:54:13 +0300752 glBeginTransformFeedback(GL_TRIANGLES);
753 ASSERT_GL_NO_ERROR();
754
Olli Etuaho44ae8992018-08-20 15:37:09 +0300755 GLFramebuffer fbo;
756 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
757
758 GLTexture tex2D;
759 initOnePixelColorTexture2D(tex2D);
760
Martin Radev7e69f762017-07-27 14:54:13 +0300761 // Check that drawArrays generates an error when there is an active transform feedback object
762 // and the number of views in the draw framebuffer is greater than 1.
763 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300764 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
765 2, &viewportOffsets[0]);
Martin Radev7e69f762017-07-27 14:54:13 +0300766 glDrawArrays(GL_TRIANGLES, 0, 3);
767 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
768 }
769
Jamie Madill04c084d2018-08-08 15:49:28 -0400770 glEndTransformFeedback();
771
772 // Ending transform feedback should allow the draw to succeed.
773 {
774 glDrawArrays(GL_TRIANGLES, 0, 3);
775 EXPECT_GL_NO_ERROR();
776 }
777
Jamie Madill3a256222018-12-08 09:56:39 -0500778 // A paused transform feedback should not trigger an error.
Jamie Madill04c084d2018-08-08 15:49:28 -0400779 glBeginTransformFeedback(GL_TRIANGLES);
780 glPauseTransformFeedback();
781 ASSERT_GL_NO_ERROR();
782
783 glDrawArrays(GL_TRIANGLES, 0, 3);
Jamie Madill3a256222018-12-08 09:56:39 -0500784 ASSERT_GL_NO_ERROR();
Jamie Madill04c084d2018-08-08 15:49:28 -0400785
786 // Unbind transform feedback - should succeed.
787 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
788 glDrawArrays(GL_TRIANGLES, 0, 3);
789 ASSERT_GL_NO_ERROR();
790
Jamie Madill3a256222018-12-08 09:56:39 -0500791 // Rebind paused transform feedback - should succeed.
Jamie Madill04c084d2018-08-08 15:49:28 -0400792 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
793 glDrawArrays(GL_TRIANGLES, 0, 3);
Jamie Madill3a256222018-12-08 09:56:39 -0500794 ASSERT_GL_NO_ERROR();
Jamie Madill04c084d2018-08-08 15:49:28 -0400795
796 glResumeTransformFeedback();
797 glEndTransformFeedback();
798
799 glUseProgram(singleViewProgram);
800 glBeginTransformFeedback(GL_TRIANGLES);
801 ASSERT_GL_NO_ERROR();
802
Martin Radev7e69f762017-07-27 14:54:13 +0300803 // Check that drawArrays does not generate an error when the number of views in the draw
804 // framebuffer is 1.
805 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300806 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
807 1, &viewportOffsets[0]);
Martin Radev7e69f762017-07-27 14:54:13 +0300808 glDrawArrays(GL_TRIANGLES, 0, 3);
809 EXPECT_GL_NO_ERROR();
810 }
811
812 glEndTransformFeedback();
813}
814
Martin Radevffe754b2017-07-31 10:38:07 +0300815// The test verifies that glDraw*:
816// 1) generates an INVALID_OPERATION error if the number of views in the active draw framebuffer is
817// greater than 1 and there is an active query for target GL_TIME_ELAPSED_EXT.
818// 2) does not generate any error if the number of views in the draw framebuffer is 1.
819TEST_P(MultiviewDrawValidationTest, ActiveTimeElapsedQuery)
820{
Yunchao He9550c602018-02-13 14:47:05 +0800821 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
Jamie Madill3a256222018-12-08 09:56:39 -0500822 ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_EXT_disjoint_timer_query"));
Martin Radevffe754b2017-07-31 10:38:07 +0300823
Olli Etuaho44ae8992018-08-20 15:37:09 +0300824 ANGLE_GL_PROGRAM(dualViewProgram, kDualViewVSSource, kDualViewFSSource);
825
Martin Radevffe754b2017-07-31 10:38:07 +0300826 const GLint viewportOffsets[4] = {0, 0, 2, 0};
Jamie Madill35cd7332018-12-02 12:03:33 -0500827 constexpr char kVS[] =
Martin Radevffe754b2017-07-31 10:38:07 +0300828 "#version 300 es\n"
829 "void main()\n"
830 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500831 constexpr char kFS[] =
Martin Radevffe754b2017-07-31 10:38:07 +0300832 "#version 300 es\n"
833 "precision mediump float;\n"
834 "void main()\n"
835 "{}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500836 ANGLE_GL_PROGRAM(singleViewProgram, kVS, kFS);
Jamie Madill04c084d2018-08-08 15:49:28 -0400837 glUseProgram(singleViewProgram);
Martin Radevffe754b2017-07-31 10:38:07 +0300838
Olli Etuaho44ae8992018-08-20 15:37:09 +0300839 GLVertexArray vao;
840 GLBuffer vertexBuffer;
841 GLBuffer indexBuffer;
842 initVAO(vao, vertexBuffer, indexBuffer);
843
Martin Radevffe754b2017-07-31 10:38:07 +0300844 GLuint query = 0u;
845 glGenQueriesEXT(1, &query);
846 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
847
Olli Etuaho44ae8992018-08-20 15:37:09 +0300848 GLFramebuffer fbo;
849 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
850
851 GLTexture tex2D;
852 initOnePixelColorTexture2D(tex2D);
853
Martin Radevffe754b2017-07-31 10:38:07 +0300854 // Check first case.
855 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300856 glUseProgram(dualViewProgram);
857 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
858 2, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300859 glClear(GL_COLOR_BUFFER_BIT);
860 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Martin Radevffe754b2017-07-31 10:38:07 +0300861 glDrawArrays(GL_TRIANGLES, 0, 3);
862 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
863 }
864
865 // Check second case.
866 {
Jamie Madill04c084d2018-08-08 15:49:28 -0400867 glUseProgram(singleViewProgram);
Olli Etuaho44ae8992018-08-20 15:37:09 +0300868 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
869 1, &viewportOffsets[0]);
Olli Etuaho94c91a92018-07-19 15:10:24 +0300870 glClear(GL_COLOR_BUFFER_BIT);
871 EXPECT_GL_NO_ERROR();
Martin Radevffe754b2017-07-31 10:38:07 +0300872 glDrawArrays(GL_TRIANGLES, 0, 3);
873 EXPECT_GL_NO_ERROR();
874 }
875
876 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
877 glDeleteQueries(1, &query);
Jamie Madill04c084d2018-08-08 15:49:28 -0400878
879 // Check starting a query after a successful draw.
880 {
Olli Etuaho44ae8992018-08-20 15:37:09 +0300881 glUseProgram(dualViewProgram);
882 glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2D, 0,
883 2, &viewportOffsets[0]);
Jamie Madill04c084d2018-08-08 15:49:28 -0400884 glClear(GL_COLOR_BUFFER_BIT);
885 EXPECT_GL_NO_ERROR();
886 glDrawArrays(GL_TRIANGLES, 0, 3);
887 EXPECT_GL_NO_ERROR();
888
889 glGenQueriesEXT(1, &query);
890 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
891
892 glDrawArrays(GL_TRIANGLES, 0, 3);
893 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
894
895 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
896 glDrawArrays(GL_TRIANGLES, 0, 3);
897 EXPECT_GL_NO_ERROR();
898
899 glDeleteQueries(1, &query);
900 }
Martin Radevffe754b2017-07-31 10:38:07 +0300901}
902
Martin Radev8f276e22017-05-30 12:05:52 +0300903// The test checks that glDrawArrays can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300904TEST_P(MultiviewRenderDualViewTest, DrawArrays)
Martin Radev8f276e22017-05-30 12:05:52 +0300905{
Jamie Madill3a256222018-12-08 09:56:39 -0500906 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
907
Martin Radev8f276e22017-05-30 12:05:52 +0300908 drawQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
909 ASSERT_GL_NO_ERROR();
910
911 checkOutput();
912}
913
914// The test checks that glDrawElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300915TEST_P(MultiviewRenderDualViewTest, DrawElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300916{
Jamie Madill3a256222018-12-08 09:56:39 -0500917 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
918
Martin Radev8f276e22017-05-30 12:05:52 +0300919 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
920 ASSERT_GL_NO_ERROR();
921
922 checkOutput();
923}
924
925// The test checks that glDrawRangeElements can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300926TEST_P(MultiviewRenderDualViewTest, DrawRangeElements)
Martin Radev8f276e22017-05-30 12:05:52 +0300927{
Jamie Madill3a256222018-12-08 09:56:39 -0500928 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
929
Martin Radev8f276e22017-05-30 12:05:52 +0300930 drawIndexedQuad(mProgram, "vPosition", 0.0f, 1.0f, true, true);
931 ASSERT_GL_NO_ERROR();
932
933 checkOutput();
934}
935
936// The test checks that glDrawArrays can be used to render into four views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300937TEST_P(MultiviewRenderTest, DrawArraysFourViews)
Martin Radev8f276e22017-05-30 12:05:52 +0300938{
Jamie Madill3a256222018-12-08 09:56:39 -0500939 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev8f276e22017-05-30 12:05:52 +0300940
Jamie Madill35cd7332018-12-02 12:03:33 -0500941 constexpr char kVS[] =
Martin Radev8f276e22017-05-30 12:05:52 +0300942 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300943 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300944 "layout(num_views = 4) in;\n"
945 "in vec4 vPosition;\n"
946 "void main()\n"
947 "{\n"
948 " if (gl_ViewID_OVR == 0u) {\n"
949 " gl_Position.x = vPosition.x*0.25 - 0.75;\n"
950 " } else if (gl_ViewID_OVR == 1u) {\n"
951 " gl_Position.x = vPosition.x*0.25 - 0.25;\n"
952 " } else if (gl_ViewID_OVR == 2u) {\n"
953 " gl_Position.x = vPosition.x*0.25 + 0.25;\n"
954 " } else {\n"
955 " gl_Position.x = vPosition.x*0.25 + 0.75;\n"
956 " }"
957 " gl_Position.yzw = vPosition.yzw;\n"
958 "}\n";
959
Jamie Madill35cd7332018-12-02 12:03:33 -0500960 constexpr char kFS[] =
Martin Radev8f276e22017-05-30 12:05:52 +0300961 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +0300962 "#extension GL_OVR_multiview : require\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300963 "precision mediump float;\n"
964 "out vec4 col;\n"
965 "void main()\n"
966 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +0300967 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +0300968 "}\n";
969
Olli Etuaho4836acc2018-08-20 15:23:18 +0300970 updateFBOs(4, 1, 4);
Jamie Madill35cd7332018-12-02 12:03:33 -0500971 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev8f276e22017-05-30 12:05:52 +0300972
973 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
974 ASSERT_GL_NO_ERROR();
975
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300976 resolveMultisampledFBO();
Martin Radev8f276e22017-05-30 12:05:52 +0300977 for (int i = 0; i < 4; ++i)
978 {
979 for (int j = 0; j < 4; ++j)
980 {
Martin Radev8f276e22017-05-30 12:05:52 +0300981 if (i == j)
982 {
Martin Radev67a8a012017-09-08 13:03:52 +0300983 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300984 }
985 else
986 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300987 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(j, 0, i));
Martin Radev8f276e22017-05-30 12:05:52 +0300988 }
989 }
990 }
991 EXPECT_GL_NO_ERROR();
992}
993
994// The test checks that glDrawArraysInstanced can be used to render into two views.
Martin Radev3c25ad02017-08-22 17:36:53 +0300995TEST_P(MultiviewRenderTest, DrawArraysInstanced)
Martin Radev8f276e22017-05-30 12:05:52 +0300996{
Jamie Madill3a256222018-12-08 09:56:39 -0500997 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev8f276e22017-05-30 12:05:52 +0300998
Jamie Madill35cd7332018-12-02 12:03:33 -0500999 constexpr char kVS[] =
Martin Radev8f276e22017-05-30 12:05:52 +03001000 "#version 300 es\n"
1001 "#extension GL_OVR_multiview : require\n"
1002 "layout(num_views = 2) in;\n"
1003 "in vec4 vPosition;\n"
1004 "void main()\n"
1005 "{\n"
1006 " vec4 p = vPosition;\n"
1007 " if (gl_InstanceID == 1){\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001008 " p.y = p.y * 0.5 + 0.5;\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001009 " } else {\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001010 " p.y = p.y * 0.5 - 0.5;\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001011 " }\n"
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001012 " 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 +03001013 " gl_Position.yzw = p.yzw;\n"
1014 "}\n";
1015
Jamie Madill35cd7332018-12-02 12:03:33 -05001016 constexpr char kFS[] =
Martin Radev8f276e22017-05-30 12:05:52 +03001017 "#version 300 es\n"
1018 "#extension GL_OVR_multiview : require\n"
1019 "precision mediump float;\n"
1020 "out vec4 col;\n"
1021 "void main()\n"
1022 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001023 " col = vec4(0,1,0,1);\n"
Martin Radev8f276e22017-05-30 12:05:52 +03001024 "}\n";
1025
Martin Radev3c25ad02017-08-22 17:36:53 +03001026 const int kViewWidth = 2;
1027 const int kViewHeight = 2;
1028 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001029 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001030 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev8f276e22017-05-30 12:05:52 +03001031
Martin Radev67a8a012017-09-08 13:03:52 +03001032 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 2u);
Martin Radev8f276e22017-05-30 12:05:52 +03001033 ASSERT_GL_NO_ERROR();
1034
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001035 resolveMultisampledFBO();
1036
Martin Radev67a8a012017-09-08 13:03:52 +03001037 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {{{0, 255}, {0, 255}},
1038 {{255, 0}, {255, 0}}};
Martin Radev3c25ad02017-08-22 17:36:53 +03001039
1040 for (int view = 0; view < 2; ++view)
Martin Radev8f276e22017-05-30 12:05:52 +03001041 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001042 for (int y = 0; y < 2; ++y)
Martin Radev8f276e22017-05-30 12:05:52 +03001043 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001044 for (int x = 0; x < 2; ++x)
1045 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001046 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][y][x], 0,
1047 expectedGreenChannel[view][y][x]),
Martin Radev3c25ad02017-08-22 17:36:53 +03001048 GetViewColor(x, y, view));
1049 }
Martin Radev8f276e22017-05-30 12:05:52 +03001050 }
1051 }
1052}
1053
Martin Radev553590a2017-07-31 16:40:39 +03001054// The test verifies that the attribute divisor is correctly adjusted when drawing with a multi-view
1055// program. The test draws 4 instances of a quad each of which covers a single pixel. The x and y
1056// offset of each quad are passed as separate attributes which are indexed based on the
1057// corresponding attribute divisors. A divisor of 1 is used for the y offset to have all quads
1058// drawn vertically next to each other. A divisor of 3 is used for the x offset to have the last
1059// quad offsetted by one pixel to the right. Note that the number of views is divisible by 1, but
1060// not by 3.
Martin Radev3c25ad02017-08-22 17:36:53 +03001061TEST_P(MultiviewRenderTest, AttribDivisor)
Martin Radev553590a2017-07-31 16:40:39 +03001062{
Jamie Madill3a256222018-12-08 09:56:39 -05001063 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev553590a2017-07-31 16:40:39 +03001064
Corentin Wallez02cd1522018-08-22 13:46:21 +02001065 // Looks like an incorrect D3D debug layer message is generated on Windows AMD and NVIDIA.
Olli Etuaho44ae8992018-08-20 15:37:09 +03001066 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001067 if (IsWindows() && IsD3D11())
1068 {
1069 ignoreD3D11SDKLayersWarnings();
1070 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001071
Jamie Madill35cd7332018-12-02 12:03:33 -05001072 constexpr char kVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001073 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001074 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001075 "layout(num_views = 2) in;\n"
1076 "in vec3 vPosition;\n"
1077 "in float offsetX;\n"
1078 "in float offsetY;\n"
1079 "void main()\n"
1080 "{\n"
1081 " vec4 p = vec4(vPosition, 1.);\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001082 " p.xy = p.xy * 0.25 - vec2(0.75) + vec2(offsetX, offsetY);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001083 " gl_Position.x = (gl_ViewID_OVR == 0u ? p.x : p.x + 1.0);\n"
1084 " gl_Position.yzw = p.yzw;\n"
1085 "}\n";
1086
Jamie Madill35cd7332018-12-02 12:03:33 -05001087 constexpr char kFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001088 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001089 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001090 "precision mediump float;\n"
1091 "out vec4 col;\n"
1092 "void main()\n"
1093 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001094 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001095 "}\n";
Martin Radev3c25ad02017-08-22 17:36:53 +03001096
1097 const int kViewWidth = 4;
1098 const int kViewHeight = 4;
1099 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001100 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001101 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev553590a2017-07-31 16:40:39 +03001102
1103 GLBuffer xOffsetVBO;
1104 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1105 const GLfloat xOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.0f};
1106 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, xOffsetData, GL_STATIC_DRAW);
1107 GLint xOffsetLoc = glGetAttribLocation(program, "offsetX");
1108 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1109 glVertexAttribDivisor(xOffsetLoc, 3);
1110 glEnableVertexAttribArray(xOffsetLoc);
1111
1112 GLBuffer yOffsetVBO;
1113 glBindBuffer(GL_ARRAY_BUFFER, yOffsetVBO);
1114 const GLfloat yOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1115 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, yOffsetData, GL_STATIC_DRAW);
1116 GLint yOffsetLoc = glGetAttribLocation(program, "offsetY");
1117 glVertexAttribDivisor(yOffsetLoc, 1);
1118 glVertexAttribPointer(yOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1119 glEnableVertexAttribArray(yOffsetLoc);
1120
Martin Radev67a8a012017-09-08 13:03:52 +03001121 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev553590a2017-07-31 16:40:39 +03001122 ASSERT_GL_NO_ERROR();
1123
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001124 resolveMultisampledFBO();
1125
Martin Radev67a8a012017-09-08 13:03:52 +03001126 const GLubyte expectedGreenChannel[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001127 {{255, 0, 0, 0}, {255, 0, 0, 0}, {255, 0, 0, 0}, {0, 255, 0, 0}},
1128 {{0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 255, 0}, {0, 0, 0, 255}}};
1129 for (int view = 0; view < 2; ++view)
Martin Radev553590a2017-07-31 16:40:39 +03001130 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001131 for (int row = 0; row < 4; ++row)
Martin Radev553590a2017-07-31 16:40:39 +03001132 {
Martin Radev3c25ad02017-08-22 17:36:53 +03001133 for (int col = 0; col < 4; ++col)
1134 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001135 EXPECT_EQ(GLColor(0, expectedGreenChannel[view][row][col], 0,
1136 expectedGreenChannel[view][row][col]),
Martin Radev3c25ad02017-08-22 17:36:53 +03001137 GetViewColor(col, row, view));
1138 }
Martin Radev553590a2017-07-31 16:40:39 +03001139 }
1140 }
1141}
1142
1143// Test that different sequences of vertexAttribDivisor, useProgram and bindVertexArray in a
1144// multi-view context propagate the correct divisor to the driver.
Martin Radev3c25ad02017-08-22 17:36:53 +03001145TEST_P(MultiviewRenderTest, DivisorOrderOfOperation)
Martin Radev553590a2017-07-31 16:40:39 +03001146{
Jamie Madill3a256222018-12-08 09:56:39 -05001147 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
Martin Radev553590a2017-07-31 16:40:39 +03001148
Olli Etuaho4836acc2018-08-20 15:23:18 +03001149 updateFBOs(1, 1, 2);
Martin Radev553590a2017-07-31 16:40:39 +03001150
1151 // Create multiview program.
Jamie Madill35cd7332018-12-02 12:03:33 -05001152 constexpr char kVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001153 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001154 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001155 "layout(num_views = 2) in;\n"
1156 "layout(location = 0) in vec2 vPosition;\n"
1157 "layout(location = 1) in float offsetX;\n"
1158 "void main()\n"
1159 "{\n"
1160 " vec4 p = vec4(vPosition, 0.0, 1.0);\n"
1161 " p.x += offsetX;\n"
1162 " gl_Position = p;\n"
1163 "}\n";
1164
Jamie Madill35cd7332018-12-02 12:03:33 -05001165 constexpr char kFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001166 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001167 "#extension GL_OVR_multiview : require\n"
Martin Radev553590a2017-07-31 16:40:39 +03001168 "precision mediump float;\n"
1169 "out vec4 col;\n"
1170 "void main()\n"
1171 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001172 " col = vec4(0,1,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001173 "}\n";
1174
Jamie Madill35cd7332018-12-02 12:03:33 -05001175 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev553590a2017-07-31 16:40:39 +03001176
Jamie Madill35cd7332018-12-02 12:03:33 -05001177 constexpr char kDummyVS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001178 "#version 300 es\n"
1179 "layout(location = 0) in vec2 vPosition;\n"
1180 "layout(location = 1) in float offsetX;\n"
1181 "void main()\n"
1182 "{\n"
1183 " gl_Position = vec4(vPosition, 0.0, 1.0);\n"
1184 "}\n";
1185
Jamie Madill35cd7332018-12-02 12:03:33 -05001186 constexpr char kDummyFS[] =
Martin Radev553590a2017-07-31 16:40:39 +03001187 "#version 300 es\n"
1188 "precision mediump float;\n"
1189 "out vec4 col;\n"
1190 "void main()\n"
1191 "{\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001192 " col = vec4(0,0,0,1);\n"
Martin Radev553590a2017-07-31 16:40:39 +03001193 "}\n";
1194
Jamie Madill35cd7332018-12-02 12:03:33 -05001195 ANGLE_GL_PROGRAM(dummyProgram, kDummyVS, kDummyFS);
Martin Radev553590a2017-07-31 16:40:39 +03001196
1197 GLBuffer xOffsetVBO;
1198 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1199 const GLfloat xOffsetData[12] = {0.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f,
1200 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f};
1201 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 12, xOffsetData, GL_STATIC_DRAW);
1202
1203 GLBuffer vertexVBO;
1204 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1205 Vector2 kQuadVertices[6] = {Vector2(-1.f, -1.f), Vector2(1.f, -1.f), Vector2(1.f, 1.f),
1206 Vector2(-1.f, -1.f), Vector2(1.f, 1.f), Vector2(-1.f, 1.f)};
1207 glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
1208
1209 GLVertexArray vao[2];
1210 for (size_t i = 0u; i < 2u; ++i)
1211 {
1212 glBindVertexArray(vao[i]);
1213
1214 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
1215 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
1216 glEnableVertexAttribArray(0);
1217
1218 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1219 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
1220 glEnableVertexAttribArray(1);
1221 }
1222 ASSERT_GL_NO_ERROR();
1223
1224 glViewport(0, 0, 1, 1);
1225 glScissor(0, 0, 1, 1);
Martin Radeveef80e42017-08-11 14:44:57 +03001226 glEnable(GL_SCISSOR_TEST);
Martin Radev61bd9992017-08-11 13:10:55 +03001227 glClearColor(0, 0, 0, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001228
1229 // Clear the buffers, propagate divisor to the driver, bind the vao and keep it active.
1230 // It is necessary to call draw, so that the divisor is propagated and to guarantee that dirty
1231 // bits are cleared.
1232 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001233 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1234 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001235 glBindVertexArray(vao[0]);
1236 glVertexAttribDivisor(1, 0);
1237 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1238 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001239 ASSERT_GL_NO_ERROR();
1240
1241 // Check that vertexAttribDivisor uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001242 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001243 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001244 glUseProgram(program);
1245 glVertexAttribDivisor(1, 1);
1246 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001247
1248 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001249 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1250 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001251
1252 // Clear the buffers and propagate divisor to the driver.
1253 // We keep the vao active and propagate the divisor to guarantee that there are no unresolved
1254 // dirty bits when useProgram is called.
1255 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001256 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1257 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001258 glVertexAttribDivisor(1, 1);
1259 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1260 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001261 ASSERT_GL_NO_ERROR();
1262
1263 // Check that useProgram uses the number of views to update the divisor.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001264 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001265 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001266 glUseProgram(program);
1267 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001268
1269 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001270 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1271 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001272
1273 // We go through similar steps as before.
1274 glUseProgram(dummyProgram);
Martin Radevda8e2572017-09-12 17:21:16 +03001275 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1276 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001277 glVertexAttribDivisor(1, 1);
1278 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
1279 glUseProgram(0);
Martin Radev553590a2017-07-31 16:40:39 +03001280 ASSERT_GL_NO_ERROR();
1281
1282 // Check that bindVertexArray uses the number of views to update the divisor.
1283 {
1284 // Call useProgram with vao[1] being active to guarantee that useProgram will adjust the
1285 // divisor for vao[1] only.
Olli Etuaho4836acc2018-08-20 15:23:18 +03001286 bindMemberDrawFramebuffer();
Martin Radevda8e2572017-09-12 17:21:16 +03001287 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001288 glBindVertexArray(vao[1]);
1289 glUseProgram(program);
1290 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Martin Radev553590a2017-07-31 16:40:39 +03001291 glBindVertexArray(0);
1292 ASSERT_GL_NO_ERROR();
1293 }
1294 // Bind vao[0] after useProgram is called to ensure that bindVertexArray is the call which
1295 // adjusts the divisor.
Martin Radevda8e2572017-09-12 17:21:16 +03001296 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev553590a2017-07-31 16:40:39 +03001297 glBindVertexArray(vao[0]);
1298 glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001299
1300 resolveMultisampledFBO();
Martin Radev67a8a012017-09-08 13:03:52 +03001301 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
1302 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev553590a2017-07-31 16:40:39 +03001303}
1304
Martin Radev0d671c92017-08-10 16:41:52 +03001305// Test that no fragments pass the occlusion query for a multi-view vertex shader which always
1306// transforms geometry to be outside of the clip region.
Martin Radev3c25ad02017-08-22 17:36:53 +03001307TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryNothingVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001308{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001309 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1310 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001311
Jamie Madill35cd7332018-12-02 12:03:33 -05001312 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001313 "#version 300 es\n"
1314 "#extension GL_OVR_multiview : require\n"
1315 "layout(num_views = 2) in;\n"
1316 "in vec3 vPosition;\n"
1317 "void main()\n"
1318 "{\n"
1319 " gl_Position.x = 2.0;\n"
1320 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1321 "}\n";
1322
Jamie Madill35cd7332018-12-02 12:03:33 -05001323 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001324 "#version 300 es\n"
1325 "#extension GL_OVR_multiview : require\n"
1326 "precision mediump float;\n"
1327 "out vec4 col;\n"
1328 "void main()\n"
1329 "{\n"
1330 " col = vec4(1,0,0,0);\n"
1331 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001332 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001333 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001334
1335 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1336 ASSERT_GL_NO_ERROR();
1337 EXPECT_GL_FALSE(result);
1338}
1339
1340// Test that there are fragments passing the occlusion query if only view 0 can produce
1341// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001342TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyLeftVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001343{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001344 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1345 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001346
Jamie Madill35cd7332018-12-02 12:03:33 -05001347 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001348 "#version 300 es\n"
1349 "#extension GL_OVR_multiview : require\n"
1350 "layout(num_views = 2) in;\n"
1351 "in vec3 vPosition;\n"
1352 "void main()\n"
1353 "{\n"
1354 " gl_Position.x = gl_ViewID_OVR == 0u ? vPosition.x : 2.0;\n"
1355 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1356 "}\n";
1357
Jamie Madill35cd7332018-12-02 12:03:33 -05001358 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001359 "#version 300 es\n"
1360 "#extension GL_OVR_multiview : require\n"
1361 "precision mediump float;\n"
1362 "out vec4 col;\n"
1363 "void main()\n"
1364 "{\n"
1365 " col = vec4(1,0,0,0);\n"
1366 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001367 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001368 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001369
1370 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1371 ASSERT_GL_NO_ERROR();
1372 EXPECT_GL_TRUE(result);
1373}
1374
1375// Test that there are fragments passing the occlusion query if only view 1 can produce
1376// output.
Martin Radev3c25ad02017-08-22 17:36:53 +03001377TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyRightVisible)
Martin Radev0d671c92017-08-10 16:41:52 +03001378{
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001379 ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
1380 ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
Martin Radev0d671c92017-08-10 16:41:52 +03001381
Jamie Madill35cd7332018-12-02 12:03:33 -05001382 constexpr char kVS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001383 "#version 300 es\n"
1384 "#extension GL_OVR_multiview : require\n"
1385 "layout(num_views = 2) in;\n"
1386 "in vec3 vPosition;\n"
1387 "void main()\n"
1388 "{\n"
1389 " gl_Position.x = gl_ViewID_OVR == 1u ? vPosition.x : 2.0;\n"
1390 " gl_Position.yzw = vec3(vPosition.yz, 1.);\n"
1391 "}\n";
1392
Jamie Madill35cd7332018-12-02 12:03:33 -05001393 constexpr char kFS[] =
Martin Radev0d671c92017-08-10 16:41:52 +03001394 "#version 300 es\n"
1395 "#extension GL_OVR_multiview : require\n"
1396 "precision mediump float;\n"
1397 "out vec4 col;\n"
1398 "void main()\n"
1399 "{\n"
1400 " col = vec4(1,0,0,0);\n"
1401 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001402 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001403 updateFBOs(1, 1, 2);
Martin Radev0d671c92017-08-10 16:41:52 +03001404
1405 GLuint result = drawAndRetrieveOcclusionQueryResult(program);
1406 ASSERT_GL_NO_ERROR();
1407 EXPECT_GL_TRUE(result);
1408}
1409
Martin Radev41ac68e2017-06-06 12:16:58 +03001410// Test that a simple multi-view program which doesn't use gl_ViewID_OVR in neither VS nor FS
1411// compiles and links without an error.
1412TEST_P(MultiviewProgramGenerationTest, SimpleProgram)
1413{
1414 if (!requestMultiviewExtension())
1415 {
1416 return;
1417 }
1418
Jamie Madill35cd7332018-12-02 12:03:33 -05001419 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001420 "#version 300 es\n"
1421 "#extension GL_OVR_multiview : require\n"
1422 "layout(num_views = 2) in;\n"
1423 "void main()\n"
1424 "{\n"
1425 "}\n";
1426
Jamie Madill35cd7332018-12-02 12:03:33 -05001427 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001428 "#version 300 es\n"
1429 "#extension GL_OVR_multiview : require\n"
1430 "precision mediump float;\n"
1431 "void main()\n"
1432 "{\n"
1433 "}\n";
1434
Jamie Madill35cd7332018-12-02 12:03:33 -05001435 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001436 glUseProgram(program);
1437
1438 EXPECT_GL_NO_ERROR();
1439}
1440
1441// Test that a simple multi-view program which uses gl_ViewID_OVR only in VS compiles and links
1442// without an error.
1443TEST_P(MultiviewProgramGenerationTest, UseViewIDInVertexShader)
1444{
1445 if (!requestMultiviewExtension())
1446 {
1447 return;
1448 }
1449
Jamie Madill35cd7332018-12-02 12:03:33 -05001450 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001451 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001452 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001453 "layout(num_views = 2) in;\n"
1454 "void main()\n"
1455 "{\n"
1456 " if (gl_ViewID_OVR == 0u) {\n"
1457 " gl_Position = vec4(1,0,0,1);\n"
1458 " } else {\n"
1459 " gl_Position = vec4(-1,0,0,1);\n"
1460 " }\n"
1461 "}\n";
1462
Jamie Madill35cd7332018-12-02 12:03:33 -05001463 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001464 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001465 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001466 "precision mediump float;\n"
1467 "void main()\n"
1468 "{\n"
1469 "}\n";
1470
Jamie Madill35cd7332018-12-02 12:03:33 -05001471 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001472 glUseProgram(program);
1473
1474 EXPECT_GL_NO_ERROR();
1475}
1476
1477// Test that a simple multi-view program which uses gl_ViewID_OVR only in FS compiles and links
1478// without an error.
1479TEST_P(MultiviewProgramGenerationTest, UseViewIDInFragmentShader)
1480{
1481 if (!requestMultiviewExtension())
1482 {
1483 return;
1484 }
1485
Jamie Madill35cd7332018-12-02 12:03:33 -05001486 constexpr char kVS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001487 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001488 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001489 "layout(num_views = 2) in;\n"
1490 "void main()\n"
1491 "{\n"
1492 "}\n";
1493
Jamie Madill35cd7332018-12-02 12:03:33 -05001494 constexpr char kFS[] =
Martin Radev41ac68e2017-06-06 12:16:58 +03001495 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001496 "#extension GL_OVR_multiview : require\n"
Martin Radev41ac68e2017-06-06 12:16:58 +03001497 "precision mediump float;\n"
1498 "out vec4 col;\n"
1499 "void main()\n"
1500 "{\n"
1501 " if (gl_ViewID_OVR == 0u) {\n"
1502 " col = vec4(1,0,0,1);\n"
1503 " } else {\n"
1504 " col = vec4(-1,0,0,1);\n"
1505 " }\n"
1506 "}\n";
1507
Jamie Madill35cd7332018-12-02 12:03:33 -05001508 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev41ac68e2017-06-06 12:16:58 +03001509 glUseProgram(program);
1510
1511 EXPECT_GL_NO_ERROR();
1512}
1513
Martin Radev61bd9992017-08-11 13:10:55 +03001514// The test checks that GL_POINTS is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001515TEST_P(MultiviewRenderPrimitiveTest, Points)
Martin Radev61bd9992017-08-11 13:10:55 +03001516{
1517 if (!requestMultiviewExtension())
1518 {
1519 return;
1520 }
1521
Geoff Lang25858162017-11-06 11:25:58 -05001522 // Test failing on P400 graphics card (anglebug.com/2228)
1523 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1524
Jamie Madill35cd7332018-12-02 12:03:33 -05001525 constexpr char kVS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001526 "#version 300 es\n"
1527 "#extension GL_OVR_multiview : require\n"
1528 "layout(num_views = 2) in;\n"
1529 "layout(location=0) in vec2 vPosition;\n"
1530 "void main()\n"
1531 "{\n"
1532 " gl_PointSize = 1.0;\n"
1533 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1534 "}\n";
1535
Jamie Madill35cd7332018-12-02 12:03:33 -05001536 constexpr char kFS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001537 "#version 300 es\n"
1538 "#extension GL_OVR_multiview : require\n"
1539 "precision mediump float;\n"
1540 "out vec4 col;\n"
1541 "void main()\n"
1542 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03001543 " col = vec4(0,1,0,1);\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001544 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001545 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev61bd9992017-08-11 13:10:55 +03001546 glUseProgram(program);
1547
Martin Radev3c25ad02017-08-22 17:36:53 +03001548 const int kViewWidth = 4;
1549 const int kViewHeight = 2;
1550 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001551 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001552
1553 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 1)};
1554 std::vector<Vector2> vertexDataInClipSpace =
1555 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1556 setupGeometry(vertexDataInClipSpace);
1557
1558 glDrawArrays(GL_POINTS, 0, 2);
1559
Martin Radev67a8a012017-09-08 13:03:52 +03001560 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001561 {{255, 0, 0, 0}, {0, 0, 0, 255}}, {{255, 0, 0, 0}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001562 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001563}
1564
1565// The test checks that GL_LINES is correctly rendered.
1566// The behavior of this test is not guaranteed by the spec:
1567// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1568// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1569// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1570// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001571TEST_P(MultiviewRenderPrimitiveTest, Lines)
Martin Radev61bd9992017-08-11 13:10:55 +03001572{
1573 if (!requestMultiviewExtension())
1574 {
1575 return;
1576 }
1577
Martin Radevced5c862017-08-17 16:05:29 +03001578 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001579 ASSERT_NE(program, 0u);
1580 glUseProgram(program);
1581 ASSERT_GL_NO_ERROR();
1582
Martin Radev3c25ad02017-08-22 17:36:53 +03001583 const int kViewWidth = 4;
1584 const int kViewHeight = 2;
1585 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001586 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001587
1588 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(4, 0)};
1589 std::vector<Vector2> vertexDataInClipSpace =
1590 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1591 setupGeometry(vertexDataInClipSpace);
1592
1593 glDrawArrays(GL_LINES, 0, 2);
1594
Martin Radev67a8a012017-09-08 13:03:52 +03001595 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001596 {{255, 255, 255, 255}, {0, 0, 0, 0}}, {{255, 255, 255, 255}, {0, 0, 0, 0}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001597 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001598
1599 glDeleteProgram(program);
1600}
1601
1602// The test checks that GL_LINE_STRIP is correctly rendered.
1603// The behavior of this test is not guaranteed by the spec:
1604// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1605// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1606// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1607// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001608TEST_P(MultiviewRenderPrimitiveTest, LineStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001609{
1610 if (!requestMultiviewExtension())
1611 {
1612 return;
1613 }
1614
Martin Radevced5c862017-08-17 16:05:29 +03001615 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001616 ASSERT_NE(program, 0u);
1617 glUseProgram(program);
1618 ASSERT_GL_NO_ERROR();
1619
Martin Radev3c25ad02017-08-22 17:36:53 +03001620 const int kViewWidth = 4;
1621 const int kViewHeight = 2;
1622 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001623 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001624
1625 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 2)};
1626 std::vector<Vector2> vertexDataInClipSpace =
1627 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 2);
1628 setupGeometry(vertexDataInClipSpace);
1629
1630 glDrawArrays(GL_LINE_STRIP, 0, 3);
1631
Martin Radev67a8a012017-09-08 13:03:52 +03001632 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001633 {{255, 255, 255, 255}, {0, 0, 0, 255}}, {{255, 255, 255, 255}, {0, 0, 0, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001634 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001635
1636 glDeleteProgram(program);
1637}
1638
1639// The test checks that GL_LINE_LOOP is correctly rendered.
1640// The behavior of this test is not guaranteed by the spec:
1641// OpenGL ES 3.0.5 (November 3, 2016), Section 3.5.1 Basic Line Segment Rasterization:
1642// "The coordinates of a fragment produced by the algorithm may not deviate by more than one unit in
1643// either x or y window coordinates from a corresponding fragment produced by the diamond-exit
1644// rule."
Martin Radev3c25ad02017-08-22 17:36:53 +03001645TEST_P(MultiviewRenderPrimitiveTest, LineLoop)
Martin Radev61bd9992017-08-11 13:10:55 +03001646{
1647 if (!requestMultiviewExtension())
1648 {
1649 return;
1650 }
1651
Martin Radevced5c862017-08-17 16:05:29 +03001652 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001653 ASSERT_NE(program, 0u);
1654 glUseProgram(program);
1655 ASSERT_GL_NO_ERROR();
1656
Martin Radev3c25ad02017-08-22 17:36:53 +03001657 const int kViewWidth = 4;
1658 const int kViewHeight = 4;
1659 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001660 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001661
1662 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(3, 0), Vector2I(3, 3),
1663 Vector2I(0, 3)};
1664 std::vector<Vector2> vertexDataInClipSpace =
1665 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 4);
1666 setupGeometry(vertexDataInClipSpace);
1667
1668 glDrawArrays(GL_LINE_LOOP, 0, 4);
1669
Martin Radev67a8a012017-09-08 13:03:52 +03001670 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
Martin Radev3c25ad02017-08-22 17:36:53 +03001671 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}},
1672 {{255, 255, 255, 255}, {255, 0, 0, 255}, {255, 0, 0, 255}, {255, 255, 255, 255}}};
Martin Radev67a8a012017-09-08 13:03:52 +03001673 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001674
1675 glDeleteProgram(program);
1676}
1677
1678// The test checks that GL_TRIANGLE_STRIP is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001679TEST_P(MultiviewRenderPrimitiveTest, TriangleStrip)
Martin Radev61bd9992017-08-11 13:10:55 +03001680{
1681 if (!requestMultiviewExtension())
1682 {
1683 return;
1684 }
1685
Martin Radevced5c862017-08-17 16:05:29 +03001686 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001687 ASSERT_NE(program, 0u);
1688 glUseProgram(program);
1689 ASSERT_GL_NO_ERROR();
1690
1691 std::vector<Vector2> vertexDataInClipSpace = {Vector2(1.0f, 0.0f), Vector2(0.0f, 0.0f),
1692 Vector2(1.0f, 1.0f), Vector2(0.0f, 1.0f)};
1693 setupGeometry(vertexDataInClipSpace);
1694
Martin Radev3c25ad02017-08-22 17:36:53 +03001695 const int kViewWidth = 2;
1696 const int kViewHeight = 2;
1697 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001698 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001699
1700 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1701
Martin Radev67a8a012017-09-08 13:03:52 +03001702 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1703 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1704 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001705
1706 glDeleteProgram(program);
1707}
1708
1709// The test checks that GL_TRIANGLE_FAN is correctly rendered.
Martin Radev3c25ad02017-08-22 17:36:53 +03001710TEST_P(MultiviewRenderPrimitiveTest, TriangleFan)
Martin Radev61bd9992017-08-11 13:10:55 +03001711{
1712 if (!requestMultiviewExtension())
1713 {
1714 return;
1715 }
1716
Martin Radevced5c862017-08-17 16:05:29 +03001717 GLuint program = CreateSimplePassthroughProgram(2);
Martin Radev61bd9992017-08-11 13:10:55 +03001718 ASSERT_NE(program, 0u);
1719 glUseProgram(program);
1720 ASSERT_GL_NO_ERROR();
1721
1722 std::vector<Vector2> vertexDataInClipSpace = {Vector2(0.0f, 0.0f), Vector2(0.0f, 1.0f),
1723 Vector2(1.0f, 1.0f), Vector2(1.0f, 0.0f)};
1724 setupGeometry(vertexDataInClipSpace);
1725
Martin Radev3c25ad02017-08-22 17:36:53 +03001726 const int kViewWidth = 2;
1727 const int kViewHeight = 2;
1728 const int kNumViews = 2;
Olli Etuaho4836acc2018-08-20 15:23:18 +03001729 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev61bd9992017-08-11 13:10:55 +03001730
1731 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1732
Martin Radev67a8a012017-09-08 13:03:52 +03001733 const GLubyte expectedGreenChannelData[kNumViews][kViewHeight][kViewWidth] = {
1734 {{0, 0}, {0, 255}}, {{0, 0}, {0, 255}}};
1735 checkGreenChannel(expectedGreenChannelData[0][0]);
Martin Radev61bd9992017-08-11 13:10:55 +03001736
1737 glDeleteProgram(program);
1738}
1739
1740// Test that rendering enlarged points and lines does not leak fragments outside of the views'
1741// bounds. The test does not rely on the actual line width being greater than 1.0.
Martin Radev3c25ad02017-08-22 17:36:53 +03001742TEST_P(MultiviewSideBySideRenderTest, NoLeakingFragments)
Martin Radev61bd9992017-08-11 13:10:55 +03001743{
1744 if (!requestMultiviewExtension())
1745 {
1746 return;
1747 }
1748
Olli Etuaho9259fd02018-08-22 12:12:00 +03001749 GLTexture colorTexture;
Martin Radev61bd9992017-08-11 13:10:55 +03001750
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001751 CreateMultiviewBackingTextures(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0, 2, 1, 2,
Olli Etuaho9259fd02018-08-22 12:12:00 +03001752 colorTexture, 0u, 0u);
1753
1754 GLFramebuffer drawFramebuffer;
1755 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFramebuffer);
Martin Radev61bd9992017-08-11 13:10:55 +03001756 GLint viewportOffsets[4] = {1, 0, 3, 0};
1757 glFramebufferTextureMultiviewSideBySideANGLE(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
Olli Etuaho9259fd02018-08-22 12:12:00 +03001758 colorTexture, 0, 2, &viewportOffsets[0]);
1759
1760 GLFramebuffer readFramebuffer;
1761 glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
1762 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
1763 0);
1764
1765 ASSERT_GL_NO_ERROR();
Martin Radev61bd9992017-08-11 13:10:55 +03001766
1767 glViewport(0, 0, 1, 1);
1768 glScissor(0, 0, 1, 1);
1769 glEnable(GL_SCISSOR_TEST);
1770
Jamie Madill35cd7332018-12-02 12:03:33 -05001771 constexpr char kVS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001772 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001773 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001774 "layout(num_views = 2) in;\n"
1775 "layout(location=0) in vec2 vPosition;\n"
1776 "void main()\n"
1777 "{\n"
1778 " gl_PointSize = 10.0;\n"
1779 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
1780 "}\n";
1781
Jamie Madill35cd7332018-12-02 12:03:33 -05001782 constexpr char kFS[] =
Martin Radev61bd9992017-08-11 13:10:55 +03001783 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001784 "#extension GL_OVR_multiview : require\n"
Martin Radev61bd9992017-08-11 13:10:55 +03001785 "precision mediump float;\n"
1786 "out vec4 col;\n"
1787 "void main()\n"
1788 "{\n"
1789 " if (gl_ViewID_OVR == 0u) {\n"
1790 " col = vec4(1,0,0,1);\n"
1791 " } else {\n"
1792 " col = vec4(0,1,0,1);\n"
1793 " }\n"
1794 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -05001795 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev61bd9992017-08-11 13:10:55 +03001796 glUseProgram(program);
1797
1798 const std::vector<Vector2I> &windowCoordinates = {Vector2I(0, 0), Vector2I(2, 0)};
1799 const std::vector<Vector2> &vertexDataInClipSpace =
1800 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 1, 1);
Martin Radev3c25ad02017-08-22 17:36:53 +03001801
1802 GLBuffer vbo;
1803 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1804 glBufferData(GL_ARRAY_BUFFER, vertexDataInClipSpace.size() * sizeof(Vector2),
1805 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
1806 glEnableVertexAttribArray(0);
Luc Ferronadcf0ae2018-01-24 08:27:37 -05001807 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
Martin Radev61bd9992017-08-11 13:10:55 +03001808
1809 // Test rendering points.
1810 {
1811 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1812 glDrawArrays(GL_POINTS, 0, 2);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001813 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001814 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001815 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001816 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1817 }
1818
1819 // Test rendering lines.
1820 {
1821 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1822 glLineWidth(10.f);
1823 glDrawArrays(GL_LINES, 0, 2);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001824 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001825 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::red);
Olli Etuahoa7b35c32018-08-21 16:32:24 +03001826 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::transparentBlack);
Martin Radev61bd9992017-08-11 13:10:55 +03001827 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
1828 }
1829}
1830
Martin Radev0abb7a22017-08-28 15:34:45 +03001831// Verify that re-linking a program adjusts the attribute divisor.
1832// The test uses instacing to draw for each view a strips of two red quads and two blue quads next
1833// to each other. The quads' position and color depend on the corresponding attribute divisors.
1834TEST_P(MultiviewRenderTest, ProgramRelinkUpdatesAttribDivisor)
1835{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001836 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev0abb7a22017-08-28 15:34:45 +03001837 {
1838 return;
1839 }
1840
Corentin Wallez02cd1522018-08-22 13:46:21 +02001841 // Looks like an incorrect D3D debug layer message is generated on Windows AMD and NVIDIA.
Olli Etuaho44ae8992018-08-20 15:37:09 +03001842 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001843 if (IsWindows() && IsD3D11())
1844 {
1845 ignoreD3D11SDKLayersWarnings();
1846 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001847
Martin Radev0abb7a22017-08-28 15:34:45 +03001848 const int kViewWidth = 4;
1849 const int kViewHeight = 1;
1850 const int kNumViews = 2;
1851
Jamie Madill35cd7332018-12-02 12:03:33 -05001852 constexpr char kFS[] =
Martin Radev0abb7a22017-08-28 15:34:45 +03001853 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001854 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001855 "precision mediump float;\n"
1856 "in vec4 oColor;\n"
1857 "out vec4 col;\n"
1858 "void main()\n"
1859 "{\n"
1860 " col = oColor;\n"
1861 "}\n";
1862
1863 auto generateVertexShaderSource = [](int numViews) -> std::string {
1864 std::string source =
1865 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03001866 "#extension GL_OVR_multiview : require\n"
Martin Radev0abb7a22017-08-28 15:34:45 +03001867 "layout(num_views = " +
1868 ToString(numViews) +
1869 ") in;\n"
1870 "in vec3 vPosition;\n"
1871 "in float vOffsetX;\n"
1872 "in vec4 vColor;\n"
1873 "out vec4 oColor;\n"
1874 "void main()\n"
1875 "{\n"
1876 " vec4 p = vec4(vPosition, 1.);\n"
1877 " p.x = p.x * 0.25 - 0.75 + vOffsetX;\n"
1878 " oColor = vColor;\n"
1879 " gl_Position = p;\n"
1880 "}\n";
1881 return source;
1882 };
1883
1884 std::string vsSource = generateVertexShaderSource(kNumViews);
Jamie Madill35cd7332018-12-02 12:03:33 -05001885 ANGLE_GL_PROGRAM(program, vsSource.c_str(), kFS);
Martin Radev0abb7a22017-08-28 15:34:45 +03001886 glUseProgram(program);
1887
1888 GLint positionLoc;
1889 GLBuffer xOffsetVBO;
1890 GLint xOffsetLoc;
1891 GLBuffer colorVBO;
1892 GLint colorLoc;
1893
1894 {
1895 // Initialize buffers and setup attributes.
1896 glBindBuffer(GL_ARRAY_BUFFER, xOffsetVBO);
1897 const GLfloat kXOffsetData[4] = {0.0f, 0.5f, 1.0f, 1.5f};
1898 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, kXOffsetData, GL_STATIC_DRAW);
1899 xOffsetLoc = glGetAttribLocation(program, "vOffsetX");
1900 glVertexAttribPointer(xOffsetLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
1901 glVertexAttribDivisor(xOffsetLoc, 1);
1902 glEnableVertexAttribArray(xOffsetLoc);
1903
1904 glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
1905 const GLColor kColors[2] = {GLColor::red, GLColor::blue};
1906 glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 2, kColors, GL_STATIC_DRAW);
1907 colorLoc = glGetAttribLocation(program, "vColor");
1908 glVertexAttribDivisor(colorLoc, 2);
1909 glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
1910 glEnableVertexAttribArray(colorLoc);
1911
1912 positionLoc = glGetAttribLocation(program, "vPosition");
1913 }
1914
1915 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03001916 updateFBOs(kViewWidth, kViewHeight, kNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001917
Martin Radev67a8a012017-09-08 13:03:52 +03001918 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001919 ASSERT_GL_NO_ERROR();
1920
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001921 resolveMultisampledFBO();
Martin Radev0abb7a22017-08-28 15:34:45 +03001922 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
1923 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, 0));
1924 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, 0));
1925 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, 0));
1926 }
1927
1928 {
1929 const int kNewNumViews = 3;
1930 vsSource = generateVertexShaderSource(kNewNumViews);
Olli Etuaho4836acc2018-08-20 15:23:18 +03001931 updateFBOs(kViewWidth, kViewHeight, kNewNumViews);
Martin Radev0abb7a22017-08-28 15:34:45 +03001932
Jamie Madill35cd7332018-12-02 12:03:33 -05001933 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource.c_str());
Martin Radev0abb7a22017-08-28 15:34:45 +03001934 ASSERT_NE(0u, vs);
Jamie Madill35cd7332018-12-02 12:03:33 -05001935 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
Martin Radev0abb7a22017-08-28 15:34:45 +03001936 ASSERT_NE(0u, fs);
1937
1938 GLint numAttachedShaders = 0;
1939 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
1940
1941 GLuint attachedShaders[2] = {0u};
1942 glGetAttachedShaders(program, numAttachedShaders, nullptr, attachedShaders);
1943 for (int i = 0; i < 2; ++i)
1944 {
1945 glDetachShader(program, attachedShaders[i]);
1946 }
1947
1948 glAttachShader(program, vs);
1949 glDeleteShader(vs);
1950
1951 glAttachShader(program, fs);
1952 glDeleteShader(fs);
1953
1954 glBindAttribLocation(program, positionLoc, "vPosition");
1955 glBindAttribLocation(program, xOffsetLoc, "vOffsetX");
1956 glBindAttribLocation(program, colorLoc, "vColor");
1957
1958 glLinkProgram(program);
1959
Martin Radev67a8a012017-09-08 13:03:52 +03001960 drawQuadInstanced(program, "vPosition", 0.0f, 1.0f, true, 4u);
Martin Radev0abb7a22017-08-28 15:34:45 +03001961 ASSERT_GL_NO_ERROR();
1962
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001963 resolveMultisampledFBO();
Martin Radev0abb7a22017-08-28 15:34:45 +03001964 for (int i = 0; i < kNewNumViews; ++i)
1965 {
1966 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, i));
1967 EXPECT_EQ(GLColor::red, GetViewColor(1, 0, i));
1968 EXPECT_EQ(GLColor::blue, GetViewColor(2, 0, i));
1969 EXPECT_EQ(GLColor::blue, GetViewColor(3, 0, i));
1970 }
1971 }
1972}
1973
Martin Radevced5c862017-08-17 16:05:29 +03001974// Test that useProgram applies the number of views in computing the final value of the attribute
1975// divisor.
1976TEST_P(MultiviewRenderTest, DivisorUpdatedOnProgramChange)
1977{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03001978 if (!requestMultiviewExtension(isMultisampled()))
Martin Radevced5c862017-08-17 16:05:29 +03001979 {
1980 return;
1981 }
1982
Geoff Lang25858162017-11-06 11:25:58 -05001983 // Test failing on P400 graphics card (anglebug.com/2228)
1984 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11() && IsNVIDIA());
1985
Olli Etuaho44ae8992018-08-20 15:37:09 +03001986 // Looks like an incorrect D3D debug layer message is generated on Windows / AMD.
1987 // May be specific to Windows 7 / Windows Server 2008. http://anglebug.com/2778
Olli Etuaho4b4197a2018-08-22 15:24:41 +03001988 if (IsWindows() && IsD3D11())
1989 {
1990 ignoreD3D11SDKLayersWarnings();
1991 }
Olli Etuaho44ae8992018-08-20 15:37:09 +03001992
Martin Radevced5c862017-08-17 16:05:29 +03001993 GLVertexArray vao;
1994 glBindVertexArray(vao);
1995 GLBuffer vbo;
1996 glBindBuffer(GL_ARRAY_BUFFER, vbo);
1997 std::vector<Vector2I> windowCoordinates = {Vector2I(0, 0), Vector2I(1, 0), Vector2I(2, 0),
1998 Vector2I(3, 0)};
1999 std::vector<Vector2> vertexDataInClipSpace =
2000 ConvertPixelCoordinatesToClipSpace(windowCoordinates, 4, 1);
2001 // Fill with x positions so that the resulting clip space coordinate fails the clip test.
2002 glBufferData(GL_ARRAY_BUFFER, sizeof(Vector2) * vertexDataInClipSpace.size(),
2003 vertexDataInClipSpace.data(), GL_STATIC_DRAW);
2004 glEnableVertexAttribArray(0);
2005 glVertexAttribPointer(0, 2, GL_FLOAT, 0, 0, nullptr);
2006 glVertexAttribDivisor(0, 1);
2007 ASSERT_GL_NO_ERROR();
2008
2009 // Create a program and fbo with N views and draw N instances of a point horizontally.
2010 for (int numViews = 2; numViews <= 4; ++numViews)
2011 {
Olli Etuaho4836acc2018-08-20 15:23:18 +03002012 updateFBOs(4, 1, numViews);
Martin Radevced5c862017-08-17 16:05:29 +03002013 ASSERT_GL_NO_ERROR();
2014
2015 GLuint program = CreateSimplePassthroughProgram(numViews);
2016 ASSERT_NE(program, 0u);
2017 glUseProgram(program);
2018 ASSERT_GL_NO_ERROR();
2019
2020 glDrawArraysInstanced(GL_POINTS, 0, 1, numViews);
2021
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002022 resolveMultisampledFBO();
Martin Radevced5c862017-08-17 16:05:29 +03002023 for (int view = 0; view < numViews; ++view)
2024 {
2025 for (int j = 0; j < numViews; ++j)
2026 {
Martin Radev67a8a012017-09-08 13:03:52 +03002027 EXPECT_EQ(GLColor::green, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03002028 }
2029 for (int j = numViews; j < 4; ++j)
2030 {
Olli Etuahoa7b35c32018-08-21 16:32:24 +03002031 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(j, 0, view));
Martin Radevced5c862017-08-17 16:05:29 +03002032 }
2033 }
2034
2035 glDeleteProgram(program);
2036 }
2037}
2038
Martin Radev72b4e1e2017-08-31 15:42:56 +03002039// The test checks that gl_ViewID_OVR is correctly propagated to the fragment shader.
2040TEST_P(MultiviewRenderTest, SelectColorBasedOnViewIDOVR)
2041{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002042 if (!requestMultiviewExtension(isMultisampled()))
Martin Radev72b4e1e2017-08-31 15:42:56 +03002043 {
2044 return;
2045 }
2046
Jamie Madill35cd7332018-12-02 12:03:33 -05002047 constexpr char kVS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002048 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002049 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002050 "layout(num_views = 3) in;\n"
2051 "in vec3 vPosition;\n"
2052 "void main()\n"
2053 "{\n"
2054 " gl_Position = vec4(vPosition, 1.);\n"
2055 "}\n";
2056
Jamie Madill35cd7332018-12-02 12:03:33 -05002057 constexpr char kFS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002058 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002059 "#extension GL_OVR_multiview : require\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002060 "precision mediump float;\n"
2061 "out vec4 col;\n"
2062 "void main()\n"
2063 "{\n"
2064 " if (gl_ViewID_OVR == 0u) {\n"
2065 " col = vec4(1,0,0,1);\n"
2066 " } else if (gl_ViewID_OVR == 1u) {\n"
2067 " col = vec4(0,1,0,1);\n"
2068 " } else if (gl_ViewID_OVR == 2u) {\n"
2069 " col = vec4(0,0,1,1);\n"
2070 " } else {\n"
2071 " col = vec4(0,0,0,0);\n"
2072 " }\n"
2073 "}\n";
2074
Olli Etuaho4836acc2018-08-20 15:23:18 +03002075 updateFBOs(1, 1, 3);
Jamie Madill35cd7332018-12-02 12:03:33 -05002076 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev72b4e1e2017-08-31 15:42:56 +03002077
2078 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2079 ASSERT_GL_NO_ERROR();
2080
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002081 resolveMultisampledFBO();
Martin Radev72b4e1e2017-08-31 15:42:56 +03002082 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2083 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2084 EXPECT_EQ(GLColor::blue, GetViewColor(0, 0, 2));
2085}
2086
2087// The test checks that the inactive layers of a 2D texture array are not written to by a
2088// multi-view program.
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002089TEST_P(MultiviewLayeredRenderTest, RenderToSubrangeOfLayers)
Martin Radev72b4e1e2017-08-31 15:42:56 +03002090{
2091 if (!requestMultiviewExtension())
2092 {
2093 return;
2094 }
2095
Jamie Madill35cd7332018-12-02 12:03:33 -05002096 constexpr char kVS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002097 "#version 300 es\n"
2098 "#extension GL_OVR_multiview : require\n"
2099 "layout(num_views = 2) in;\n"
2100 "in vec3 vPosition;\n"
2101 "void main()\n"
2102 "{\n"
2103 " gl_Position = vec4(vPosition, 1.);\n"
2104 "}\n";
2105
Jamie Madill35cd7332018-12-02 12:03:33 -05002106 constexpr char kFS[] =
Martin Radev72b4e1e2017-08-31 15:42:56 +03002107 "#version 300 es\n"
2108 "#extension GL_OVR_multiview : require\n"
2109 "precision mediump float;\n"
2110 "out vec4 col;\n"
2111 "void main()\n"
2112 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002113 " col = vec4(0,1,0,1);\n"
Martin Radev72b4e1e2017-08-31 15:42:56 +03002114 "}\n";
2115
Olli Etuaho4836acc2018-08-20 15:23:18 +03002116 updateFBOs(1, 1, 2, 4, 1);
Jamie Madill35cd7332018-12-02 12:03:33 -05002117 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev72b4e1e2017-08-31 15:42:56 +03002118
2119 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2120 ASSERT_GL_NO_ERROR();
2121
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002122 resolveMultisampledFBO();
Martin Radev72b4e1e2017-08-31 15:42:56 +03002123 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 0));
Martin Radev67a8a012017-09-08 13:03:52 +03002124 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2125 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 2));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002126 EXPECT_EQ(GLColor::transparentBlack, GetViewColor(0, 0, 3));
2127}
2128
Martin Radevc1d4e552017-08-21 12:01:10 +03002129// The D3D11 renderer uses a GS whenever the varyings are flat interpolated which can cause
2130// potential bugs if the view is selected in the VS. The test contains a program in which the
2131// gl_InstanceID is passed as a flat varying to the fragment shader where it is used to discard the
2132// fragment if its value is negative. The gl_InstanceID should never be negative and that branch is
2133// never taken. One quad is drawn and the color is selected based on the ViewID - red for view 0 and
2134// green for view 1.
2135TEST_P(MultiviewRenderTest, FlatInterpolation)
Martin Radev3c25ad02017-08-22 17:36:53 +03002136{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002137 if (!requestMultiviewExtension(isMultisampled()))
Martin Radevc1d4e552017-08-21 12:01:10 +03002138 {
2139 return;
2140 }
2141
Jamie Madill35cd7332018-12-02 12:03:33 -05002142 constexpr char kVS[] =
Martin Radevc1d4e552017-08-21 12:01:10 +03002143 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002144 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002145 "layout(num_views = 2) in;\n"
2146 "in vec3 vPosition;\n"
2147 "flat out int oInstanceID;\n"
2148 "void main()\n"
2149 "{\n"
2150 " gl_Position = vec4(vPosition, 1.);\n"
2151 " oInstanceID = gl_InstanceID;\n"
2152 "}\n";
2153
Jamie Madill35cd7332018-12-02 12:03:33 -05002154 constexpr char kFS[] =
Martin Radevc1d4e552017-08-21 12:01:10 +03002155 "#version 300 es\n"
Olli Etuahoec3a9cb2017-09-07 12:18:01 +03002156 "#extension GL_OVR_multiview : require\n"
Martin Radevc1d4e552017-08-21 12:01:10 +03002157 "precision mediump float;\n"
2158 "flat in int oInstanceID;\n"
2159 "out vec4 col;\n"
2160 "void main()\n"
2161 "{\n"
2162 " if (oInstanceID < 0) {\n"
2163 " discard;\n"
2164 " }\n"
2165 " if (gl_ViewID_OVR == 0u) {\n"
2166 " col = vec4(1,0,0,1);\n"
2167 " } else {\n"
2168 " col = vec4(0,1,0,1);\n"
2169 " }\n"
2170 "}\n";
2171
Olli Etuaho4836acc2018-08-20 15:23:18 +03002172 updateFBOs(1, 1, 2);
Jamie Madill35cd7332018-12-02 12:03:33 -05002173 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radevc1d4e552017-08-21 12:01:10 +03002174
2175 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2176 ASSERT_GL_NO_ERROR();
2177
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002178 resolveMultisampledFBO();
Martin Radevc1d4e552017-08-21 12:01:10 +03002179 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2180 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev3c25ad02017-08-22 17:36:53 +03002181}
2182
Olli Etuaho604d8732018-07-20 11:02:43 +03002183// This test assigns gl_ViewID_OVR to a flat int varying and then sets the color based on that
2184// varying in the fragment shader.
2185TEST_P(MultiviewRenderTest, FlatInterpolation2)
2186{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002187 if (!requestMultiviewExtension(isMultisampled()))
Olli Etuaho604d8732018-07-20 11:02:43 +03002188 {
2189 return;
2190 }
2191
Jamie Madill35cd7332018-12-02 12:03:33 -05002192 constexpr char kVS[] =
Olli Etuaho604d8732018-07-20 11:02:43 +03002193 "#version 300 es\n"
2194 "#extension GL_OVR_multiview : require\n"
2195 "layout(num_views = 2) in;\n"
2196 "in vec3 vPosition;\n"
2197 "flat out int flatVarying;\n"
2198 "void main()\n"
2199 "{\n"
2200 " gl_Position = vec4(vPosition, 1.);\n"
2201 " flatVarying = int(gl_ViewID_OVR);\n"
2202 "}\n";
2203
Jamie Madill35cd7332018-12-02 12:03:33 -05002204 constexpr char kFS[] =
Olli Etuaho604d8732018-07-20 11:02:43 +03002205 "#version 300 es\n"
2206 "#extension GL_OVR_multiview : require\n"
2207 "precision mediump float;\n"
2208 "flat in int flatVarying;\n"
2209 "out vec4 col;\n"
2210 "void main()\n"
2211 "{\n"
2212 " if (flatVarying == 0) {\n"
2213 " col = vec4(1,0,0,1);\n"
2214 " } else {\n"
2215 " col = vec4(0,1,0,1);\n"
2216 " }\n"
2217 "}\n";
2218
Olli Etuaho4836acc2018-08-20 15:23:18 +03002219 updateFBOs(1, 1, 2);
Jamie Madill35cd7332018-12-02 12:03:33 -05002220 ANGLE_GL_PROGRAM(program, kVS, kFS);
Olli Etuaho604d8732018-07-20 11:02:43 +03002221
2222 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
2223 ASSERT_GL_NO_ERROR();
2224
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002225 resolveMultisampledFBO();
Olli Etuaho604d8732018-07-20 11:02:43 +03002226 EXPECT_EQ(GLColor::red, GetViewColor(0, 0, 0));
2227 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
2228}
2229
Martin Radev265a6d42017-09-12 16:51:37 +03002230// The test is added to cover a bug which resulted in the viewport/scissor and viewport offsets not
2231// being correctly applied.
2232TEST_P(MultiviewSideBySideRenderTest, ViewportOffsetsAppliedBugCoverage)
2233{
2234 if (!requestMultiviewExtension())
2235 {
2236 return;
2237 }
2238
Olli Etuaho4836acc2018-08-20 15:23:18 +03002239 updateFBOs(1, 1, 2);
Martin Radev265a6d42017-09-12 16:51:37 +03002240
2241 // Create multiview program.
Jamie Madill35cd7332018-12-02 12:03:33 -05002242 constexpr char kVS[] =
Martin Radev265a6d42017-09-12 16:51:37 +03002243 "#version 300 es\n"
2244 "#extension GL_OVR_multiview : require\n"
2245 "layout(num_views = 2) in;\n"
2246 "layout(location = 0) in vec3 vPosition;\n"
2247 "void main()\n"
2248 "{\n"
2249 " gl_Position = vec4(vPosition, 1.0);\n"
2250 "}\n";
2251
Jamie Madill35cd7332018-12-02 12:03:33 -05002252 constexpr char kFS[] =
Martin Radev265a6d42017-09-12 16:51:37 +03002253 "#version 300 es\n"
2254 "#extension GL_OVR_multiview : require\n"
2255 "precision mediump float;\n"
2256 "out vec4 col;\n"
2257 "void main()\n"
2258 "{\n"
Martin Radev67a8a012017-09-08 13:03:52 +03002259 " col = vec4(0,1,0,1);\n"
Martin Radev265a6d42017-09-12 16:51:37 +03002260 "}\n";
2261
Jamie Madill35cd7332018-12-02 12:03:33 -05002262 ANGLE_GL_PROGRAM(program, kVS, kFS);
Martin Radev265a6d42017-09-12 16:51:37 +03002263
2264 glViewport(0, 0, 1, 1);
2265 glScissor(0, 0, 1, 1);
2266 glEnable(GL_SCISSOR_TEST);
2267 glClearColor(0, 0, 0, 1);
2268
2269 // Bind the default FBO and make sure that the state is synchronized.
2270 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2271 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2272 ASSERT_GL_NO_ERROR();
2273
2274 // Draw and check that both views are rendered to.
Olli Etuaho4836acc2018-08-20 15:23:18 +03002275 bindMemberDrawFramebuffer();
Martin Radev265a6d42017-09-12 16:51:37 +03002276 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Martin Radev67a8a012017-09-08 13:03:52 +03002277
Martin Radev265a6d42017-09-12 16:51:37 +03002278 drawQuad(program, "vPosition", 0.0f, 1.0f, true);
Martin Radev67a8a012017-09-08 13:03:52 +03002279 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 0));
2280 EXPECT_EQ(GLColor::green, GetViewColor(0, 0, 1));
Martin Radev265a6d42017-09-12 16:51:37 +03002281}
2282
Olli Etuahof26b27e2018-08-17 11:01:19 +03002283MultiviewRenderTestParams SideBySideVertexShaderOpenGL(GLint majorVersion = 3,
2284 GLint minorVersion = 0)
Martin Radev3c25ad02017-08-22 17:36:53 +03002285{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002286 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002287 VertexShaderOpenGL(majorVersion, minorVersion));
Martin Radev3c25ad02017-08-22 17:36:53 +03002288}
2289
Olli Etuahof26b27e2018-08-17 11:01:19 +03002290MultiviewRenderTestParams LayeredVertexShaderOpenGL()
Martin Radev3c25ad02017-08-22 17:36:53 +03002291{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002292 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002293 VertexShaderOpenGL(3, 0));
Martin Radev3c25ad02017-08-22 17:36:53 +03002294}
2295
Olli Etuahof26b27e2018-08-17 11:01:19 +03002296MultiviewRenderTestParams SideBySideGeomShaderD3D11()
Martin Radev72b4e1e2017-08-31 15:42:56 +03002297{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002298 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002299 GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002300}
2301
Olli Etuahof26b27e2018-08-17 11:01:19 +03002302MultiviewRenderTestParams LayeredGeomShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002303{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002304 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
2305 GeomShaderD3D11(3, 0));
Martin Radevc1d4e552017-08-21 12:01:10 +03002306}
2307
Olli Etuahof26b27e2018-08-17 11:01:19 +03002308MultiviewRenderTestParams SideBySideVertexShaderD3D11(GLint majorVersion = 3,
2309 GLint minorVersion = 0)
Martin Radevc1d4e552017-08-21 12:01:10 +03002310{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002311 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002312 VertexShaderD3D11(majorVersion, minorVersion));
Martin Radevc1d4e552017-08-21 12:01:10 +03002313}
2314
Olli Etuahof26b27e2018-08-17 11:01:19 +03002315MultiviewRenderTestParams LayeredVertexShaderD3D11()
Martin Radevc1d4e552017-08-21 12:01:10 +03002316{
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002317 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 0,
Olli Etuahof26b27e2018-08-17 11:01:19 +03002318 VertexShaderD3D11(3, 0));
Martin Radev72b4e1e2017-08-31 15:42:56 +03002319}
2320
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002321MultiviewRenderTestParams LayeredMultisampledVertexShaderOpenGL()
2322{
2323 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 2,
2324 VertexShaderOpenGL(3, 1));
2325}
2326
2327MultiviewRenderTestParams LayeredMultisampledVertexShaderD3D11()
2328{
2329 return MultiviewRenderTestParams(GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE, 2,
2330 VertexShaderD3D11(3, 1));
2331}
2332
Jamie Madill04c084d2018-08-08 15:49:28 -04002333ANGLE_INSTANTIATE_TEST(MultiviewDrawValidationTest,
Olli Etuaho44ae8992018-08-20 15:37:09 +03002334 VertexShaderOpenGL(3, 1),
2335 VertexShaderD3D11(3, 1));
Martin Radevced5c862017-08-17 16:05:29 +03002336ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002337 SideBySideVertexShaderOpenGL(),
2338 LayeredVertexShaderOpenGL(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002339 LayeredMultisampledVertexShaderOpenGL(),
Martin Radevc1d4e552017-08-21 12:01:10 +03002340 SideBySideGeomShaderD3D11(),
2341 SideBySideVertexShaderD3D11(),
2342 LayeredGeomShaderD3D11(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002343 LayeredVertexShaderD3D11(),
2344 LayeredMultisampledVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002345ANGLE_INSTANTIATE_TEST(MultiviewRenderTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002346 SideBySideVertexShaderOpenGL(),
2347 LayeredVertexShaderOpenGL(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002348 LayeredMultisampledVertexShaderOpenGL(),
Martin Radevc1d4e552017-08-21 12:01:10 +03002349 SideBySideGeomShaderD3D11(),
2350 SideBySideVertexShaderD3D11(),
2351 LayeredGeomShaderD3D11(),
Olli Etuaho2c8f0842018-09-12 14:44:55 +03002352 LayeredVertexShaderD3D11(),
2353 LayeredMultisampledVertexShaderD3D11());
Martin Radevced5c862017-08-17 16:05:29 +03002354ANGLE_INSTANTIATE_TEST(MultiviewOcclusionQueryTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002355 SideBySideVertexShaderOpenGL(),
2356 LayeredVertexShaderOpenGL(),
2357 SideBySideGeomShaderD3D11(),
2358 SideBySideVertexShaderD3D11(),
2359 LayeredGeomShaderD3D11(),
2360 LayeredVertexShaderD3D11());
Martin Radev72b4e1e2017-08-31 15:42:56 +03002361ANGLE_INSTANTIATE_TEST(MultiviewProgramGenerationTest,
Olli Etuaho4bcaf992018-08-17 17:18:28 +03002362 VertexShaderOpenGL(3, 0),
2363 GeomShaderD3D11(3, 0),
2364 VertexShaderD3D11(3, 0));
Martin Radevced5c862017-08-17 16:05:29 +03002365ANGLE_INSTANTIATE_TEST(MultiviewRenderPrimitiveTest,
Martin Radevc1d4e552017-08-21 12:01:10 +03002366 SideBySideVertexShaderOpenGL(),
2367 LayeredVertexShaderOpenGL(),
2368 SideBySideGeomShaderD3D11(),
2369 SideBySideVertexShaderD3D11(),
2370 LayeredGeomShaderD3D11(),
2371 LayeredVertexShaderD3D11());
Jamie Madill04c084d2018-08-08 15:49:28 -04002372ANGLE_INSTANTIATE_TEST(MultiviewSideBySideRenderTest,
2373 VertexShaderOpenGL(3, 0),
2374 GeomShaderD3D11(3, 0));
2375ANGLE_INSTANTIATE_TEST(MultiviewLayeredRenderTest, VertexShaderOpenGL(3, 0), GeomShaderD3D11(3, 0));