blob: 6d29e74b19feed956dc6f16dbb17235ed0034919 [file] [log] [blame]
Olli Etuahof26b27e2018-08-17 11:01:19 +03001//
2// Copyright 2018 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// MultiviewTest:
7// Implementation of helpers for multiview testing.
8//
9
10#include "test_utils/MultiviewTest.h"
11#include "platform/WorkaroundsD3D.h"
Olli Etuaho2c8f0842018-09-12 14:44:55 +030012#include "test_utils/gl_raii.h"
Olli Etuahof26b27e2018-08-17 11:01:19 +030013
14namespace angle
15{
16
17GLuint CreateSimplePassthroughProgram(int numViews)
18{
19 const std::string vsSource =
20 "#version 300 es\n"
21 "#extension GL_OVR_multiview : require\n"
22 "layout(num_views = " +
23 ToString(numViews) +
24 ") in;\n"
25 "layout(location=0) in vec2 vPosition;\n"
26 "void main()\n"
27 "{\n"
28 " gl_PointSize = 1.;\n"
29 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
30 "}\n";
31
Jamie Madill35cd7332018-12-02 12:03:33 -050032 constexpr char kFS[] =
Olli Etuahof26b27e2018-08-17 11:01:19 +030033 "#version 300 es\n"
34 "#extension GL_OVR_multiview : require\n"
35 "precision mediump float;\n"
36 "out vec4 col;\n"
37 "void main()\n"
38 "{\n"
39 " col = vec4(0,1,0,1);\n"
40 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -050041 return CompileProgram(vsSource.c_str(), kFS);
Olli Etuahof26b27e2018-08-17 11:01:19 +030042}
43
Olli Etuahoa7b35c32018-08-21 16:32:24 +030044void CreateMultiviewBackingTextures(GLenum multiviewLayout,
Olli Etuaho2c8f0842018-09-12 14:44:55 +030045 int samples,
Olli Etuahoa7b35c32018-08-21 16:32:24 +030046 int viewWidth,
47 int height,
48 int numLayers,
49 std::vector<GLuint> colorTextures,
50 GLuint depthTexture,
51 GLuint depthStencilTexture)
52{
53 // The same zero data is used to initialize both color and depth/stencil textures.
54 std::vector<GLubyte> textureData;
55 textureData.resize(viewWidth * height * numLayers * 4, 0u);
56
Olli Etuaho2c8f0842018-09-12 14:44:55 +030057 // Multisampling is only supported for layered framebuffers.
Yuly Novikov9f088622018-12-29 20:46:15 +000058 ASSERT((samples == 0) || multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE);
Olli Etuaho2c8f0842018-09-12 14:44:55 +030059
60 // We can't upload data to multisample textures, so we clear them using a temporary framebuffer
61 // instead. The current framebuffer binding is stored so we can restore it once we're done with
62 // using the temporary framebuffers.
63 GLint restoreDrawFramebuffer;
64 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &restoreDrawFramebuffer);
65
Olli Etuahoa7b35c32018-08-21 16:32:24 +030066 // Create color and depth textures.
67 switch (multiviewLayout)
68 {
69 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
70 {
71 int textureWidth = viewWidth * numLayers;
72 for (auto colorTexture : colorTextures)
73 {
74 glBindTexture(GL_TEXTURE_2D, colorTexture);
75 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, height, 0, GL_RGBA,
76 GL_UNSIGNED_BYTE, textureData.data());
77 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
78 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
79 }
80
81 if (depthTexture != 0)
82 {
83 glBindTexture(GL_TEXTURE_2D, depthTexture);
84 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, textureWidth, height, 0,
85 GL_DEPTH_COMPONENT, GL_FLOAT, textureData.data());
86 }
87 if (depthStencilTexture != 0)
88 {
89 glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
90 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, textureWidth, height, 0,
91 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, textureData.data());
92 }
93 glBindTexture(GL_TEXTURE_2D, 0);
94 break;
95 }
96 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Olli Etuaho2c8f0842018-09-12 14:44:55 +030097 {
98 GLenum texTarget =
99 (samples > 0) ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES : GL_TEXTURE_2D_ARRAY;
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300100 for (auto colorTexture : colorTextures)
101 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300102 glBindTexture(texTarget, colorTexture);
103 if (samples > 0)
104 {
105 glTexStorage3DMultisampleOES(texTarget, samples, GL_RGBA8, viewWidth, height,
106 numLayers, false);
107
108 GLFramebuffer tempFbo;
109 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFbo);
110 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
111 for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex)
112 {
113 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
114 colorTexture, 0, layerIndex);
115 glClear(GL_COLOR_BUFFER_BIT);
116 }
117 }
118 else
119 {
120 glTexImage3D(texTarget, 0, GL_RGBA8, viewWidth, height, numLayers, 0, GL_RGBA,
121 GL_UNSIGNED_BYTE, textureData.data());
122 glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
123 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
124 }
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300125 }
126
127 if (depthTexture != 0)
128 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300129 glBindTexture(texTarget, depthTexture);
130 if (samples > 0)
131 {
132 glTexStorage3DMultisampleOES(texTarget, samples, GL_DEPTH_COMPONENT32F,
133 viewWidth, height, numLayers, false);
134
135 GLFramebuffer tempFbo;
136 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFbo);
137 glClearDepthf(0.0f);
138 for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex)
139 {
140 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
141 depthTexture, 0, layerIndex);
142 glClear(GL_DEPTH_BUFFER_BIT);
143 }
144 }
145 else
146 {
147 glTexImage3D(texTarget, 0, GL_DEPTH_COMPONENT32F, viewWidth, height, numLayers,
148 0, GL_DEPTH_COMPONENT, GL_FLOAT, textureData.data());
149 }
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300150 }
151 if (depthStencilTexture != 0)
152 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300153 glBindTexture(texTarget, depthStencilTexture);
154 if (samples > 0)
155 {
156 glTexStorage3DMultisampleOES(texTarget, samples, GL_DEPTH24_STENCIL8, viewWidth,
157 height, numLayers, false);
158
159 GLFramebuffer tempFbo;
160 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFbo);
161 glClearDepthf(0.0f);
162 glClearStencil(0);
163 for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex)
164 {
165 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
166 depthTexture, 0, layerIndex);
167 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
168 }
169 }
170 else
171 {
172 glTexImage3D(texTarget, 0, GL_DEPTH24_STENCIL8, viewWidth, height, numLayers, 0,
173 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, textureData.data());
174 }
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300175 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300176 glBindTexture(texTarget, 0);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300177 break;
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300178 }
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300179 default:
Yuly Novikov9f088622018-12-29 20:46:15 +0000180 UNREACHABLE();
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300181 }
182 ASSERT_GL_NO_ERROR();
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300183
184 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, restoreDrawFramebuffer);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300185}
186
187void CreateMultiviewBackingTextures(GLenum multiviewLayout,
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300188 int samples,
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300189 int viewWidth,
190 int height,
191 int numLayers,
192 GLuint colorTexture,
193 GLuint depthTexture,
194 GLuint depthStencilTexture)
195{
Yuly Novikov9f088622018-12-29 20:46:15 +0000196 ASSERT(colorTexture != 0u);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300197 std::vector<GLuint> colorTextures(1, colorTexture);
Olli Etuaho2c8f0842018-09-12 14:44:55 +0300198 CreateMultiviewBackingTextures(multiviewLayout, samples, viewWidth, height, numLayers,
199 colorTextures, depthTexture, depthStencilTexture);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300200}
201
202void AttachMultiviewTextures(GLenum target,
203 GLenum multiviewLayout,
204 int viewWidth,
205 int numViews,
206 int baseViewIndex,
207 std::vector<GLuint> colorTextures,
208 GLuint depthTexture,
209 GLuint depthStencilTexture)
210{
Yuly Novikov9f088622018-12-29 20:46:15 +0000211 ASSERT(multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE || (baseViewIndex == 0));
212 ASSERT(depthTexture == 0u || depthStencilTexture == 0u);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300213 switch (multiviewLayout)
214 {
215 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
216 {
217 std::vector<GLint> viewportOffsets(numViews * 2);
218 for (int i = 0u; i < numViews; ++i)
219 {
220 viewportOffsets[i * 2] = i * viewWidth;
221 viewportOffsets[i * 2 + 1] = 0;
222 }
223 for (size_t i = 0; i < colorTextures.size(); ++i)
224 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400225 GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
226 glFramebufferTextureMultiviewSideBySideANGLE(target, attachment, colorTextures[i],
227 0, numViews, viewportOffsets.data());
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300228 }
229 if (depthTexture)
230 {
231 glFramebufferTextureMultiviewSideBySideANGLE(
232 target, GL_DEPTH_ATTACHMENT, depthTexture, 0, numViews, viewportOffsets.data());
233 }
234 if (depthStencilTexture)
235 {
236 glFramebufferTextureMultiviewSideBySideANGLE(target, GL_DEPTH_STENCIL_ATTACHMENT,
237 depthStencilTexture, 0, numViews,
238 viewportOffsets.data());
239 }
240 break;
241 }
242 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
243 for (size_t i = 0; i < colorTextures.size(); ++i)
244 {
Shahbaz Youssefic4097442018-08-22 12:14:52 -0400245 GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
246 glFramebufferTextureMultiviewLayeredANGLE(target, attachment, colorTextures[i], 0,
247 baseViewIndex, numViews);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300248 }
249 if (depthTexture)
250 {
251 glFramebufferTextureMultiviewLayeredANGLE(target, GL_DEPTH_ATTACHMENT, depthTexture,
252 0, baseViewIndex, numViews);
253 }
254 if (depthStencilTexture)
255 {
256 glFramebufferTextureMultiviewLayeredANGLE(target, GL_DEPTH_STENCIL_ATTACHMENT,
257 depthStencilTexture, 0, baseViewIndex,
258 numViews);
259 }
260 break;
261 default:
Yuly Novikov9f088622018-12-29 20:46:15 +0000262 UNREACHABLE();
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300263 }
264}
265
266void AttachMultiviewTextures(GLenum target,
267 GLenum multiviewLayout,
268 int viewWidth,
269 int numViews,
270 int baseViewIndex,
271 GLuint colorTexture,
272 GLuint depthTexture,
273 GLuint depthStencilTexture)
274{
Yuly Novikov9f088622018-12-29 20:46:15 +0000275 ASSERT(colorTexture != 0u);
Olli Etuahoa7b35c32018-08-21 16:32:24 +0300276 std::vector<GLuint> colorTextures(1, colorTexture);
277 AttachMultiviewTextures(target, multiviewLayout, viewWidth, numViews, baseViewIndex,
278 colorTextures, depthTexture, depthStencilTexture);
279}
280
Olli Etuahof26b27e2018-08-17 11:01:19 +0300281std::ostream &operator<<(std::ostream &os, const MultiviewImplementationParams &params)
282{
283 const PlatformParameters &base = static_cast<const PlatformParameters &>(params);
284 os << base;
285 if (params.mForceUseGeometryShaderOnD3D)
286 {
287 os << "_force_geom_shader";
288 }
289 else
290 {
291 os << "_vertex_shader";
292 }
293 return os;
294}
295
296MultiviewImplementationParams VertexShaderOpenGL(GLint majorVersion, GLint minorVersion)
297{
298 return MultiviewImplementationParams(majorVersion, minorVersion, false, egl_platform::OPENGL());
299}
300
301MultiviewImplementationParams VertexShaderD3D11(GLint majorVersion, GLint minorVersion)
302{
303 return MultiviewImplementationParams(majorVersion, minorVersion, false, egl_platform::D3D11());
304}
305
306MultiviewImplementationParams GeomShaderD3D11(GLint majorVersion, GLint minorVersion)
307{
308 return MultiviewImplementationParams(majorVersion, minorVersion, true, egl_platform::D3D11());
309}
310
311void MultiviewTest::overrideWorkaroundsD3D(WorkaroundsD3D *workarounds)
312{
313 workarounds->selectViewInGeometryShader = GetParam().mForceUseGeometryShaderOnD3D;
314}
315
316} // namespace angle