1 //
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/autogen/FeaturesD3D_autogen.h"
12 #include "test_utils/gl_raii.h"
13
14 namespace angle
15 {
16
CreateSimplePassthroughProgram(int numViews,ExtensionName multiviewExtension)17 GLuint CreateSimplePassthroughProgram(int numViews, ExtensionName multiviewExtension)
18 {
19 std::string ext;
20 switch (multiviewExtension)
21 {
22 case multiview:
23 ext = "GL_OVR_multiview";
24 break;
25 case multiview2:
26 ext = "GL_OVR_multiview2";
27 break;
28 default:
29 // Unknown extension.
30 break;
31 }
32
33 const std::string vsSource =
34 "#version 300 es\n"
35 "#extension " +
36 ext +
37 " : require\n"
38 "layout(num_views = " +
39 ToString(numViews) +
40 ") in;\n"
41 "layout(location=0) in vec2 vPosition;\n"
42 "void main()\n"
43 "{\n"
44 " gl_PointSize = 1.;\n"
45 " gl_Position = vec4(vPosition.xy, 0.0, 1.0);\n"
46 "}\n";
47
48 const std::string fsSource =
49 "#version 300 es\n"
50 "#extension " +
51 ext +
52 " : require\n"
53 "precision mediump float;\n"
54 "out vec4 col;\n"
55 "void main()\n"
56 "{\n"
57 " col = vec4(0,1,0,1);\n"
58 "}\n";
59 return CompileProgram(vsSource.c_str(), fsSource.c_str());
60 }
61
CreateMultiviewBackingTextures(int samples,int viewWidth,int height,int numLayers,std::vector<GLuint> colorTextures,GLuint depthTexture,GLuint depthStencilTexture)62 void CreateMultiviewBackingTextures(int samples,
63 int viewWidth,
64 int height,
65 int numLayers,
66 std::vector<GLuint> colorTextures,
67 GLuint depthTexture,
68 GLuint depthStencilTexture)
69 {
70 // The same zero data is used to initialize both color and depth/stencil textures.
71 std::vector<GLubyte> textureData;
72 textureData.resize(viewWidth * height * numLayers * 4, 0u);
73
74 // We can't upload data to multisample textures, so we clear them using a temporary framebuffer
75 // instead. The current framebuffer binding is stored so we can restore it once we're done with
76 // using the temporary framebuffers.
77 GLint restoreDrawFramebuffer;
78 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &restoreDrawFramebuffer);
79
80 // Create color and depth textures.
81 GLenum texTarget = (samples > 0) ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES : GL_TEXTURE_2D_ARRAY;
82 for (auto colorTexture : colorTextures)
83 {
84 glBindTexture(texTarget, colorTexture);
85 if (samples > 0)
86 {
87 glTexStorage3DMultisampleOES(texTarget, samples, GL_RGBA8, viewWidth, height, numLayers,
88 false);
89
90 GLFramebuffer tempFbo;
91 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFbo);
92 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
93 for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex)
94 {
95 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture,
96 0, layerIndex);
97 glClear(GL_COLOR_BUFFER_BIT);
98 }
99 }
100 else
101 {
102 glTexImage3D(texTarget, 0, GL_RGBA8, viewWidth, height, numLayers, 0, GL_RGBA,
103 GL_UNSIGNED_BYTE, textureData.data());
104 glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
105 glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
106 }
107 }
108
109 if (depthTexture != 0)
110 {
111 glBindTexture(texTarget, depthTexture);
112 if (samples > 0)
113 {
114 glTexStorage3DMultisampleOES(texTarget, samples, GL_DEPTH_COMPONENT32F, viewWidth,
115 height, numLayers, false);
116
117 GLFramebuffer tempFbo;
118 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFbo);
119 glClearDepthf(0.0f);
120 for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex)
121 {
122 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0,
123 layerIndex);
124 glClear(GL_DEPTH_BUFFER_BIT);
125 }
126 }
127 else
128 {
129 glTexImage3D(texTarget, 0, GL_DEPTH_COMPONENT32F, viewWidth, height, numLayers, 0,
130 GL_DEPTH_COMPONENT, GL_FLOAT, textureData.data());
131 }
132 }
133 if (depthStencilTexture != 0)
134 {
135 glBindTexture(texTarget, depthStencilTexture);
136 if (samples > 0)
137 {
138 glTexStorage3DMultisampleOES(texTarget, samples, GL_DEPTH24_STENCIL8, viewWidth, height,
139 numLayers, false);
140
141 GLFramebuffer tempFbo;
142 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFbo);
143 glClearDepthf(0.0f);
144 glClearStencil(0);
145 for (int layerIndex = 0; layerIndex < numLayers; ++layerIndex)
146 {
147 glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
148 depthTexture, 0, layerIndex);
149 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
150 }
151 }
152 else
153 {
154 glTexImage3D(texTarget, 0, GL_DEPTH24_STENCIL8, viewWidth, height, numLayers, 0,
155 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, textureData.data());
156 }
157 }
158 glBindTexture(texTarget, 0);
159 ASSERT_GL_NO_ERROR();
160
161 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, restoreDrawFramebuffer);
162 }
163
CreateMultiviewBackingTextures(int samples,int viewWidth,int height,int numLayers,GLuint colorTexture,GLuint depthTexture,GLuint depthStencilTexture)164 void CreateMultiviewBackingTextures(int samples,
165 int viewWidth,
166 int height,
167 int numLayers,
168 GLuint colorTexture,
169 GLuint depthTexture,
170 GLuint depthStencilTexture)
171 {
172 ASSERT_TRUE(colorTexture != 0u);
173 std::vector<GLuint> colorTextures(1, colorTexture);
174 CreateMultiviewBackingTextures(samples, viewWidth, height, numLayers, colorTextures,
175 depthTexture, depthStencilTexture);
176 }
177
AttachMultiviewTextures(GLenum target,int viewWidth,int numViews,int baseViewIndex,std::vector<GLuint> colorTextures,GLuint depthTexture,GLuint depthStencilTexture)178 void AttachMultiviewTextures(GLenum target,
179 int viewWidth,
180 int numViews,
181 int baseViewIndex,
182 std::vector<GLuint> colorTextures,
183 GLuint depthTexture,
184 GLuint depthStencilTexture)
185 {
186 ASSERT_TRUE(depthTexture == 0u || depthStencilTexture == 0u);
187 for (size_t i = 0; i < colorTextures.size(); ++i)
188 {
189 GLenum attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i);
190 glFramebufferTextureMultiviewOVR(target, attachment, colorTextures[i], 0, baseViewIndex,
191 numViews);
192 }
193 if (depthTexture)
194 {
195 glFramebufferTextureMultiviewOVR(target, GL_DEPTH_ATTACHMENT, depthTexture, 0,
196 baseViewIndex, numViews);
197 }
198 if (depthStencilTexture)
199 {
200 glFramebufferTextureMultiviewOVR(target, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilTexture,
201 0, baseViewIndex, numViews);
202 }
203 }
204
AttachMultiviewTextures(GLenum target,int viewWidth,int numViews,int baseViewIndex,GLuint colorTexture,GLuint depthTexture,GLuint depthStencilTexture)205 void AttachMultiviewTextures(GLenum target,
206 int viewWidth,
207 int numViews,
208 int baseViewIndex,
209 GLuint colorTexture,
210 GLuint depthTexture,
211 GLuint depthStencilTexture)
212 {
213 ASSERT_TRUE(colorTexture != 0u);
214 std::vector<GLuint> colorTextures(1, colorTexture);
215 AttachMultiviewTextures(target, viewWidth, numViews, baseViewIndex, colorTextures, depthTexture,
216 depthStencilTexture);
217 }
218
operator <<(std::ostream & os,const MultiviewImplementationParams & params)219 std::ostream &operator<<(std::ostream &os, const MultiviewImplementationParams ¶ms)
220 {
221 const PlatformParameters &base = static_cast<const PlatformParameters &>(params);
222 os << base << "_";
223 if (params.mMultiviewExtension)
224 {
225 os << "_multiview";
226 }
227 else
228 {
229 os << "_multiview2";
230 }
231 return os;
232 }
233
VertexShaderOpenGL(EGLenum clientType,GLint majorVersion,GLint minorVersion,EGLint profileMask,ExtensionName multiviewExtension)234 MultiviewImplementationParams VertexShaderOpenGL(EGLenum clientType,
235 GLint majorVersion,
236 GLint minorVersion,
237 EGLint profileMask,
238 ExtensionName multiviewExtension)
239 {
240 return MultiviewImplementationParams(clientType, majorVersion, minorVersion, profileMask,
241 egl_platform::OPENGL(), multiviewExtension);
242 }
243
VertexShaderVulkan(EGLenum clientType,GLint majorVersion,GLint minorVersion,EGLint profileMask,ExtensionName multiviewExtension)244 MultiviewImplementationParams VertexShaderVulkan(EGLenum clientType,
245 GLint majorVersion,
246 GLint minorVersion,
247 EGLint profileMask,
248 ExtensionName multiviewExtension)
249 {
250 return MultiviewImplementationParams(clientType, majorVersion, minorVersion, profileMask,
251 egl_platform::VULKAN(), multiviewExtension);
252 }
253
VertexShaderD3D11(EGLenum clientType,GLint majorVersion,GLint minorVersion,EGLint profileMask,ExtensionName multiviewExtension)254 MultiviewImplementationParams VertexShaderD3D11(EGLenum clientType,
255 GLint majorVersion,
256 GLint minorVersion,
257 EGLint profileMask,
258 ExtensionName multiviewExtension)
259 {
260 return MultiviewImplementationParams(clientType, majorVersion, minorVersion, profileMask,
261 egl_platform::D3D11(), multiviewExtension);
262 }
263
GeomShaderD3D11(EGLenum clientType,GLint majorVersion,GLint minorVersion,EGLint profileMask,ExtensionName multiviewExtension)264 MultiviewImplementationParams GeomShaderD3D11(EGLenum clientType,
265 GLint majorVersion,
266 GLint minorVersion,
267 EGLint profileMask,
268 ExtensionName multiviewExtension)
269 {
270 return MultiviewImplementationParams(
271 clientType, majorVersion, minorVersion, profileMask,
272 egl_platform::D3D11().enable(Feature::SelectViewInGeometryShader), multiviewExtension);
273 }
274
275 } // namespace angle
276