1 //
2 // Copyright 2016 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 // LinkProgramPerfTest:
7 // Performance tests compiling a lot of shaders.
8 //
9
10 #include "ANGLEPerfTest.h"
11
12 #include <array>
13
14 #include "common/vector_utils.h"
15 #include "util/shader_utils.h"
16
17 using namespace angle;
18
19 namespace
20 {
21
22 enum class TaskOption
23 {
24 CompileOnly,
25 CompileAndLink,
26
27 Unspecified
28 };
29
30 enum class ThreadOption
31 {
32 SingleThread,
33 MultiThread,
34
35 Unspecified
36 };
37
38 struct LinkProgramParams final : public RenderTestParams
39 {
LinkProgramParams__anon8c249fff0111::LinkProgramParams40 LinkProgramParams(TaskOption taskOptionIn, ThreadOption threadOptionIn)
41 {
42 iterationsPerStep = 1;
43
44 majorVersion = 2;
45 minorVersion = 0;
46 windowWidth = 256;
47 windowHeight = 256;
48 taskOption = taskOptionIn;
49 threadOption = threadOptionIn;
50 }
51
story__anon8c249fff0111::LinkProgramParams52 std::string story() const override
53 {
54 std::stringstream strstr;
55 strstr << RenderTestParams::story();
56
57 if (taskOption == TaskOption::CompileOnly)
58 {
59 strstr << "_compile_only";
60 }
61 else if (taskOption == TaskOption::CompileAndLink)
62 {
63 strstr << "_compile_and_link";
64 }
65
66 if (threadOption == ThreadOption::SingleThread)
67 {
68 strstr << "_single_thread";
69 }
70 else if (threadOption == ThreadOption::MultiThread)
71 {
72 strstr << "_multi_thread";
73 }
74
75 if (eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
76 {
77 strstr << "_null";
78 }
79
80 return strstr.str();
81 }
82
83 TaskOption taskOption;
84 ThreadOption threadOption;
85 };
86
operator <<(std::ostream & os,const LinkProgramParams & params)87 std::ostream &operator<<(std::ostream &os, const LinkProgramParams ¶ms)
88 {
89 os << params.backendAndStory().substr(1);
90 return os;
91 }
92
93 class LinkProgramBenchmark : public ANGLERenderTest,
94 public ::testing::WithParamInterface<LinkProgramParams>
95 {
96 public:
97 LinkProgramBenchmark();
98
99 void initializeBenchmark() override;
100 void destroyBenchmark() override;
101 void drawBenchmark() override;
102
103 protected:
104 GLuint mVertexBuffer = 0;
105 };
106
LinkProgramBenchmark()107 LinkProgramBenchmark::LinkProgramBenchmark() : ANGLERenderTest("LinkProgram", GetParam()) {}
108
initializeBenchmark()109 void LinkProgramBenchmark::initializeBenchmark()
110 {
111 if (GetParam().threadOption == ThreadOption::SingleThread)
112 {
113 glMaxShaderCompilerThreadsKHR(0);
114 }
115
116 std::array<Vector3, 6> vertices = {{Vector3(-1.0f, 1.0f, 0.5f), Vector3(-1.0f, -1.0f, 0.5f),
117 Vector3(1.0f, -1.0f, 0.5f), Vector3(-1.0f, 1.0f, 0.5f),
118 Vector3(1.0f, -1.0f, 0.5f), Vector3(1.0f, 1.0f, 0.5f)}};
119
120 glGenBuffers(1, &mVertexBuffer);
121 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
122 glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vector3), vertices.data(),
123 GL_STATIC_DRAW);
124 }
125
destroyBenchmark()126 void LinkProgramBenchmark::destroyBenchmark()
127 {
128 glDeleteBuffers(1, &mVertexBuffer);
129 }
130
drawBenchmark()131 void LinkProgramBenchmark::drawBenchmark()
132 {
133 static const char *vertexShader =
134 "attribute vec2 position;\n"
135 "void main() {\n"
136 " gl_Position = vec4(position, 0, 1);\n"
137 "}";
138 static const char *fragmentShader =
139 "precision mediump float;\n"
140 "void main() {\n"
141 " gl_FragColor = vec4(1, 0, 0, 1);\n"
142 "}";
143 GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
144 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
145
146 ASSERT_NE(0u, vs);
147 ASSERT_NE(0u, fs);
148 if (GetParam().taskOption == TaskOption::CompileOnly)
149 {
150 glDeleteShader(vs);
151 glDeleteShader(fs);
152 return;
153 }
154
155 GLuint program = glCreateProgram();
156 ASSERT_NE(0u, program);
157
158 glAttachShader(program, vs);
159 glDeleteShader(vs);
160 glAttachShader(program, fs);
161 glDeleteShader(fs);
162 glLinkProgram(program);
163 glUseProgram(program);
164
165 GLint positionLoc = glGetAttribLocation(program, "position");
166 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
167 glEnableVertexAttribArray(positionLoc);
168
169 // Draw with the program to ensure the shader gets compiled and used.
170 glDrawArrays(GL_TRIANGLES, 0, 6);
171
172 glDeleteProgram(program);
173 }
174
175 using namespace egl_platform;
176
LinkProgramD3D11Params(TaskOption taskOption,ThreadOption threadOption)177 LinkProgramParams LinkProgramD3D11Params(TaskOption taskOption, ThreadOption threadOption)
178 {
179 LinkProgramParams params(taskOption, threadOption);
180 params.eglParameters = D3D11();
181 return params;
182 }
183
LinkProgramOpenGLOrGLESParams(TaskOption taskOption,ThreadOption threadOption)184 LinkProgramParams LinkProgramOpenGLOrGLESParams(TaskOption taskOption, ThreadOption threadOption)
185 {
186 LinkProgramParams params(taskOption, threadOption);
187 params.eglParameters = OPENGL_OR_GLES();
188 return params;
189 }
190
LinkProgramVulkanParams(TaskOption taskOption,ThreadOption threadOption)191 LinkProgramParams LinkProgramVulkanParams(TaskOption taskOption, ThreadOption threadOption)
192 {
193 LinkProgramParams params(taskOption, threadOption);
194 params.eglParameters = VULKAN();
195 return params;
196 }
197
TEST_P(LinkProgramBenchmark,Run)198 TEST_P(LinkProgramBenchmark, Run)
199 {
200 run();
201 }
202
203 ANGLE_INSTANTIATE_TEST(
204 LinkProgramBenchmark,
205 LinkProgramD3D11Params(TaskOption::CompileOnly, ThreadOption::MultiThread),
206 LinkProgramOpenGLOrGLESParams(TaskOption::CompileOnly, ThreadOption::MultiThread),
207 LinkProgramVulkanParams(TaskOption::CompileOnly, ThreadOption::MultiThread),
208 LinkProgramD3D11Params(TaskOption::CompileAndLink, ThreadOption::MultiThread),
209 LinkProgramOpenGLOrGLESParams(TaskOption::CompileAndLink, ThreadOption::MultiThread),
210 LinkProgramVulkanParams(TaskOption::CompileAndLink, ThreadOption::MultiThread),
211 LinkProgramD3D11Params(TaskOption::CompileOnly, ThreadOption::SingleThread),
212 LinkProgramOpenGLOrGLESParams(TaskOption::CompileOnly, ThreadOption::SingleThread),
213 LinkProgramVulkanParams(TaskOption::CompileOnly, ThreadOption::SingleThread),
214 LinkProgramD3D11Params(TaskOption::CompileAndLink, ThreadOption::SingleThread),
215 LinkProgramOpenGLOrGLESParams(TaskOption::CompileAndLink, ThreadOption::SingleThread),
216 LinkProgramVulkanParams(TaskOption::CompileAndLink, ThreadOption::SingleThread));
217
218 } // anonymous namespace
219