blob: e3b7b669260495f125847ec58772ba68cd8ba5ca [file] [log] [blame]
Olli Etuaho1436d432018-01-24 14:38:22 +02001//
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// CompilerPerfTest:
7// Performance test for the shader translator. The test initializes the compiler once and then
8// compiles the same shader repeatedly. There are different variations of the tests using
9// different shaders.
10//
11
12#include "ANGLEPerfTest.h"
13
14#include "GLSLANG/ShaderLang.h"
15#include "compiler/translator/Compiler.h"
16#include "compiler/translator/InitializeGlobals.h"
17#include "compiler/translator/PoolAlloc.h"
18
19namespace
20{
21
22const char *kSimpleESSL100FragSource = R"(
23precision mediump float;
24void main()
25{
26 gl_FragColor = vec4(0, 1, 0, 1);
27}
28)";
29
30const char *kSimpleESSL100Id = "SimpleESSL100";
31
32const char *kSimpleESSL300FragSource = R"(#version 300 es
33precision highp float;
34out vec4 outColor;
35void main()
36{
37 outColor = vec4(0, 1, 0, 1);
38}
39)";
40
41const char *kSimpleESSL300Id = "SimpleESSL300";
42
43const char *kRealWorldESSL100FragSource = R"(precision highp float;
44precision highp sampler2D;
45precision highp int;
46varying vec2 vPixelCoords; // in pixels
47uniform int uCircleCount;
48uniform sampler2D uCircleParameters;
49uniform sampler2D uBrushTex;
50void main(void)
51{
52 float destAlpha = 0.0;
53 for (int i = 0; i < 32; ++i)
54 {
55 vec4 parameterColor = texture2D(uCircleParameters,vec2(0.25, (float(i) + 0.5) / 32.0));
56 vec2 center = parameterColor.xy;
57 float circleRadius = parameterColor.z;
58 float circleFlowAlpha = parameterColor.w;
59 vec4 parameterColor2 = texture2D(uCircleParameters,vec2(0.75, (float(i) + 0.5) / 32.0));
60 float circleRotation = parameterColor2.x;
61 vec2 centerDiff = vPixelCoords - center;
62 float radius = max(circleRadius, 0.5);
63 float flowAlpha = (circleRadius < 0.5) ? circleFlowAlpha * circleRadius * circleRadius * 4.0: circleFlowAlpha;
64 float antialiasMult = clamp((radius + 1.0 - length(centerDiff)) * 0.5, 0.0, 1.0);
65 mat2 texRotation = mat2(cos(circleRotation), -sin(circleRotation), sin(circleRotation), cos(circleRotation));
66 vec2 texCoords = texRotation * centerDiff / radius * 0.5 + 0.5;
67 float texValue = texture2D(uBrushTex, texCoords).r;
68 float circleAlpha = flowAlpha * antialiasMult * texValue;
69 if (i < uCircleCount)
70 {
71 destAlpha = clamp(circleAlpha + (1.0 - circleAlpha) * destAlpha, 0.0, 1.0);
72 }
73 }
74 gl_FragColor = vec4(0.0, 0.0, 0.0, destAlpha);
75})";
76
77const char *kRealWorldESSL100Id = "RealWorldESSL100";
78
Olli Etuahobfeed4d2018-02-06 16:39:29 +020079// This shader is intended to trigger many AST transformations, particularly on the HLSL backend.
80const char *kTrickyESSL300FragSource = R"(#version 300 es
81precision highp float;
82precision highp sampler2D;
83precision highp isampler2D;
84precision highp int;
85
86float globalF;
87
88uniform ivec4 uivec;
89uniform int ui;
90
91struct SS
92{
93 int iField;
94 float fField;
95 vec2 f2Field;
96 sampler2D sField;
97 isampler2D isField;
98};
99uniform SS us;
100
101out vec4 my_FragColor;
102
103float[3] sideEffectArray()
104{
105 globalF += 1.0;
106 return float[3](globalF, globalF * 2.0, globalF * 3.0);
107}
108
109// This struct is unused and can be pruned.
110struct SUnused
111{
112 vec2 fField;
113};
114
115void main()
116{
117 struct S2
118 {
119 float fField;
120 } s2;
121 vec4 foo = vec4(ui);
122 mat4 fooM = mat4(foo.x);
123
124 // Some unused variables that can be pruned.
125 float fUnused, fUnused2;
126 ivec4 iUnused, iUnused2;
127
128 globalF = us.fField;
129 s2.fField = us.fField;
130
131 float[3] fa = sideEffectArray();
132
133 globalF -= us.fField;
134 if (fa == sideEffectArray())
135 {
136 globalF += us.fField * sin(2.0);
137 }
138
139 // Switch with fall-through.
140 switch (ui)
141 {
142 case 0:
143 // Sequence operator and matrix and vector dynamic indexing.
144 (globalF += 1.0, fooM[ui][ui] += fooM[ui - 1][uivec[ui] + 1]);
145 case 1:
146 // Built-in emulation.
147 foo[3] = tanh(foo[1]);
148 default:
149 // Sequence operator and length of an array expression with side effects.
150 foo[2] += (globalF -= 1.0, float((sideEffectArray()).length() * 2));
151 }
152 int i = 0;
153 do
154 {
155 s2.fField = us.fField * us.f2Field.x;
156 // Sequence operator and short-circuiting operator with side effects on the right hand side.
157 } while ((++i, i < int(us.fField) && ++i <= ui || ++i < ui * 2 - 3));
158 // Samplers in structures and integer texture sampling.
159 foo += texture(us.sField, us.f2Field) + intBitsToFloat(texture(us.isField, us.f2Field + 4.0));
160 my_FragColor = foo * s2.fField * globalF + fooM[ui];
161})";
162
163const char *kTrickyESSL300Id = "TrickyESSL300";
164
Jamie Madillf3acb8c2018-11-14 16:24:25 -0500165constexpr int kNumIterationsPerStep = 4;
Jamie Madill3402d522018-10-30 15:14:52 -0400166
Olli Etuaho1436d432018-01-24 14:38:22 +0200167struct CompilerPerfParameters final : public angle::CompilerParameters
168{
169 CompilerPerfParameters(ShShaderOutput output,
170 const char *shaderSource,
171 const char *shaderSourceId)
172 : angle::CompilerParameters(output), shaderSource(shaderSource)
173 {
174 testId = shaderSourceId;
175 testId += "_";
176 testId += angle::CompilerParameters::str();
177 }
178
179 const char *shaderSource;
180 std::string testId;
181};
182
183std::ostream &operator<<(std::ostream &stream, const CompilerPerfParameters &p)
184{
185 stream << p.testId;
186 return stream;
187}
188
189class CompilerPerfTest : public ANGLEPerfTest,
190 public ::testing::WithParamInterface<CompilerPerfParameters>
191{
192 public:
193 CompilerPerfTest();
194
195 void step() override;
196
197 void SetUp() override;
198 void TearDown() override;
199
200 protected:
201 void setTestShader(const char *str) { mTestShader = str; }
202
203 private:
204 const char *mTestShader;
205
206 ShBuiltInResources mResources;
207 TPoolAllocator mAllocator;
208 sh::TCompiler *mTranslator;
209};
210
Jamie Madill3402d522018-10-30 15:14:52 -0400211CompilerPerfTest::CompilerPerfTest()
212 : ANGLEPerfTest("CompilerPerf", GetParam().testId, kNumIterationsPerStep)
Jamie Madillb980c562018-11-27 11:34:27 -0500213{}
Olli Etuaho1436d432018-01-24 14:38:22 +0200214
215void CompilerPerfTest::SetUp()
216{
217 ANGLEPerfTest::SetUp();
218
219 InitializePoolIndex();
220 mAllocator.push();
221 SetGlobalPoolAllocator(&mAllocator);
222
223 const auto &params = GetParam();
224
225 mTranslator = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL2_SPEC, params.output);
226 sh::InitBuiltInResources(&mResources);
227 mResources.FragmentPrecisionHigh = true;
228 if (!mTranslator->Init(mResources))
229 {
230 SafeDelete(mTranslator);
231 }
232
233 setTestShader(params.shaderSource);
234}
235
236void CompilerPerfTest::TearDown()
237{
238 SafeDelete(mTranslator);
239
240 SetGlobalPoolAllocator(nullptr);
241 mAllocator.pop();
242
243 FreePoolIndex();
244
245 ANGLEPerfTest::TearDown();
246}
247
248void CompilerPerfTest::step()
249{
250 const char *shaderStrings[] = {mTestShader};
251
252 ShCompileOptions compileOptions = SH_OBJECT_CODE | SH_VARIABLES |
253 SH_INITIALIZE_UNINITIALIZED_LOCALS | SH_INIT_OUTPUT_VARIABLES;
254
Olli Etuaho1436d432018-01-24 14:38:22 +0200255#if !defined(NDEBUG)
256 // Make sure that compilation succeeds and print the info log if it doesn't in debug mode.
257 if (!mTranslator->compile(shaderStrings, 1, compileOptions))
258 {
259 std::cout << "Compiling perf test shader failed with log:\n"
260 << mTranslator->getInfoSink().info.c_str();
261 }
262#endif
263
264 for (unsigned int iteration = 0; iteration < kNumIterationsPerStep; ++iteration)
265 {
266 mTranslator->compile(shaderStrings, 1, compileOptions);
267 }
268}
269
270TEST_P(CompilerPerfTest, Run)
271{
272 run();
273}
274
275ANGLE_INSTANTIATE_TEST(
276 CompilerPerfTest,
277 CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kSimpleESSL100FragSource, kSimpleESSL100Id),
278 CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kSimpleESSL300FragSource, kSimpleESSL300Id),
279 CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kRealWorldESSL100FragSource, kRealWorldESSL100Id),
Olli Etuahobfeed4d2018-02-06 16:39:29 +0200280 CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kTrickyESSL300FragSource, kTrickyESSL300Id),
Olli Etuaho1436d432018-01-24 14:38:22 +0200281 CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT, kSimpleESSL100FragSource, kSimpleESSL100Id),
282 CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT, kSimpleESSL300FragSource, kSimpleESSL300Id),
283 CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT,
284 kRealWorldESSL100FragSource,
285 kRealWorldESSL100Id),
Olli Etuahobfeed4d2018-02-06 16:39:29 +0200286 CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT, kTrickyESSL300FragSource, kTrickyESSL300Id),
Olli Etuaho1436d432018-01-24 14:38:22 +0200287 CompilerPerfParameters(SH_ESSL_OUTPUT, kSimpleESSL100FragSource, kSimpleESSL100Id),
288 CompilerPerfParameters(SH_ESSL_OUTPUT, kSimpleESSL300FragSource, kSimpleESSL300Id),
Olli Etuahobfeed4d2018-02-06 16:39:29 +0200289 CompilerPerfParameters(SH_ESSL_OUTPUT, kRealWorldESSL100FragSource, kRealWorldESSL100Id),
290 CompilerPerfParameters(SH_ESSL_OUTPUT, kTrickyESSL300FragSource, kTrickyESSL300Id));
Olli Etuaho1436d432018-01-24 14:38:22 +0200291
292} // anonymous namespace