• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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__anonb885855e0111::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__anonb885855e0111::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 &params)
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         !IsGLExtensionEnabled("GL_KHR_parallel_shader_compile"))
113     {
114         skipTest("non-single-thread but missing GL_KHR_parallel_shader_compile");
115         return;
116     }
117 
118     if (IsGLExtensionEnabled("GL_KHR_parallel_shader_compile") &&
119         GetParam().threadOption == ThreadOption::SingleThread)
120     {
121         glMaxShaderCompilerThreadsKHR(0);
122     }
123 
124     std::array<Vector3, 6> vertices = {{Vector3(-1.0f, 1.0f, 0.5f), Vector3(-1.0f, -1.0f, 0.5f),
125                                         Vector3(1.0f, -1.0f, 0.5f), Vector3(-1.0f, 1.0f, 0.5f),
126                                         Vector3(1.0f, -1.0f, 0.5f), Vector3(1.0f, 1.0f, 0.5f)}};
127 
128     glGenBuffers(1, &mVertexBuffer);
129     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
130     glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vector3), vertices.data(),
131                  GL_STATIC_DRAW);
132 }
133 
destroyBenchmark()134 void LinkProgramBenchmark::destroyBenchmark()
135 {
136     glDeleteBuffers(1, &mVertexBuffer);
137 }
138 
drawBenchmark()139 void LinkProgramBenchmark::drawBenchmark()
140 {
141     static const char *vertexShader =
142         "attribute vec2 position;\n"
143         "void main() {\n"
144         "    gl_Position = vec4(position, 0, 1);\n"
145         "}";
146     static const char *fragmentShader =
147         "precision mediump float;\n"
148         "void main() {\n"
149         "    gl_FragColor = vec4(1, 0, 0, 1);\n"
150         "}";
151     GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
152     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
153 
154     ASSERT_NE(0u, vs);
155     ASSERT_NE(0u, fs);
156     if (GetParam().taskOption == TaskOption::CompileOnly)
157     {
158         glDeleteShader(vs);
159         glDeleteShader(fs);
160         return;
161     }
162 
163     GLuint program = glCreateProgram();
164     ASSERT_NE(0u, program);
165 
166     glAttachShader(program, vs);
167     glDeleteShader(vs);
168     glAttachShader(program, fs);
169     glDeleteShader(fs);
170     glLinkProgram(program);
171     glUseProgram(program);
172 
173     GLint positionLoc = glGetAttribLocation(program, "position");
174     glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
175     glEnableVertexAttribArray(positionLoc);
176 
177     // Draw with the program to ensure the shader gets compiled and used.
178     glDrawArrays(GL_TRIANGLES, 0, 6);
179 
180     glDeleteProgram(program);
181 }
182 
183 using namespace egl_platform;
184 
LinkProgramD3D11Params(TaskOption taskOption,ThreadOption threadOption)185 LinkProgramParams LinkProgramD3D11Params(TaskOption taskOption, ThreadOption threadOption)
186 {
187     LinkProgramParams params(taskOption, threadOption);
188     params.eglParameters = D3D11();
189     return params;
190 }
191 
LinkProgramOpenGLOrGLESParams(TaskOption taskOption,ThreadOption threadOption)192 LinkProgramParams LinkProgramOpenGLOrGLESParams(TaskOption taskOption, ThreadOption threadOption)
193 {
194     LinkProgramParams params(taskOption, threadOption);
195     params.eglParameters = OPENGL_OR_GLES();
196     return params;
197 }
198 
LinkProgramVulkanParams(TaskOption taskOption,ThreadOption threadOption)199 LinkProgramParams LinkProgramVulkanParams(TaskOption taskOption, ThreadOption threadOption)
200 {
201     LinkProgramParams params(taskOption, threadOption);
202     params.eglParameters = VULKAN();
203     return params;
204 }
205 
TEST_P(LinkProgramBenchmark,Run)206 TEST_P(LinkProgramBenchmark, Run)
207 {
208     run();
209 }
210 
211 ANGLE_INSTANTIATE_TEST(
212     LinkProgramBenchmark,
213     LinkProgramD3D11Params(TaskOption::CompileOnly, ThreadOption::MultiThread),
214     LinkProgramOpenGLOrGLESParams(TaskOption::CompileOnly, ThreadOption::MultiThread),
215     LinkProgramVulkanParams(TaskOption::CompileOnly, ThreadOption::MultiThread),
216     LinkProgramD3D11Params(TaskOption::CompileAndLink, ThreadOption::MultiThread),
217     LinkProgramOpenGLOrGLESParams(TaskOption::CompileAndLink, ThreadOption::MultiThread),
218     LinkProgramVulkanParams(TaskOption::CompileAndLink, ThreadOption::MultiThread),
219     LinkProgramD3D11Params(TaskOption::CompileOnly, ThreadOption::SingleThread),
220     LinkProgramOpenGLOrGLESParams(TaskOption::CompileOnly, ThreadOption::SingleThread),
221     LinkProgramVulkanParams(TaskOption::CompileOnly, ThreadOption::SingleThread),
222     LinkProgramD3D11Params(TaskOption::CompileAndLink, ThreadOption::SingleThread),
223     LinkProgramOpenGLOrGLESParams(TaskOption::CompileAndLink, ThreadOption::SingleThread),
224     LinkProgramVulkanParams(TaskOption::CompileAndLink, ThreadOption::SingleThread));
225 
226 }  // anonymous namespace
227