Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/perf_tests/UniformsPerf.cpp
1693 views
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
// UniformsBenchmark:
7
// Performance test for setting uniform data.
8
//
9
10
#include "ANGLEPerfTest.h"
11
12
#include <array>
13
#include <iostream>
14
#include <random>
15
#include <sstream>
16
17
#include "common/debug.h"
18
#include "util/Matrix.h"
19
#include "util/shader_utils.h"
20
21
using namespace angle;
22
23
namespace
24
{
25
constexpr unsigned int kIterationsPerStep = 4;
26
27
// Controls when we call glUniform, if the data is the same as last frame.
28
enum DataMode
29
{
30
UPDATE,
31
REPEAT,
32
};
33
34
// TODO(jmadill): Use an ANGLE enum for this?
35
enum DataType
36
{
37
VEC4,
38
MAT3x3,
39
MAT3x4,
40
MAT4x4,
41
};
42
43
// Determines if we state change the program between draws.
44
// This covers a performance problem in ANGLE where calling UseProgram reuploads uniform data.
45
enum ProgramMode
46
{
47
SINGLE,
48
MULTIPLE,
49
};
50
51
enum MatrixLayout
52
{
53
TRANSPOSE,
54
NO_TRANSPOSE,
55
};
56
57
struct UniformsParams final : public RenderTestParams
58
{
59
UniformsParams()
60
{
61
iterationsPerStep = kIterationsPerStep;
62
63
// Common default params
64
majorVersion = 3;
65
minorVersion = 0;
66
windowWidth = 720;
67
windowHeight = 720;
68
}
69
70
std::string story() const override;
71
size_t numVertexUniforms = 200;
72
size_t numFragmentUniforms = 200;
73
74
DataType dataType = DataType::VEC4;
75
DataMode dataMode = DataMode::REPEAT;
76
MatrixLayout matrixLayout = MatrixLayout::NO_TRANSPOSE;
77
ProgramMode programMode = ProgramMode::SINGLE;
78
};
79
80
std::ostream &operator<<(std::ostream &os, const UniformsParams &params)
81
{
82
os << params.backendAndStory().substr(1);
83
return os;
84
}
85
86
std::string UniformsParams::story() const
87
{
88
std::stringstream strstr;
89
90
strstr << RenderTestParams::story();
91
92
if (dataType == DataType::VEC4)
93
{
94
strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_vec4";
95
}
96
else if (dataType == DataType::MAT3x3)
97
{
98
strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat3x3";
99
}
100
else if (dataType == DataType::MAT3x4)
101
{
102
strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat3x4";
103
}
104
else
105
{
106
strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat4x4";
107
}
108
109
if (matrixLayout == MatrixLayout::TRANSPOSE)
110
{
111
strstr << "_transpose";
112
}
113
114
if (programMode == ProgramMode::MULTIPLE)
115
{
116
strstr << "_multiprogram";
117
}
118
119
if (dataMode == DataMode::REPEAT)
120
{
121
strstr << "_repeating";
122
}
123
124
return strstr.str();
125
}
126
127
class UniformsBenchmark : public ANGLERenderTest,
128
public ::testing::WithParamInterface<UniformsParams>
129
{
130
public:
131
UniformsBenchmark();
132
133
void initializeBenchmark() override;
134
void destroyBenchmark() override;
135
void drawBenchmark() override;
136
137
private:
138
void initShaders();
139
140
template <bool MultiProgram, typename SetUniformFunc>
141
void drawLoop(const SetUniformFunc &setUniformsFunc);
142
143
std::array<GLuint, 2> mPrograms;
144
std::vector<GLuint> mUniformLocations;
145
146
using MatrixData = std::array<std::vector<Matrix4>, 2>;
147
MatrixData mMatrixData;
148
};
149
150
std::vector<Matrix4> GenMatrixData(size_t count, int parity)
151
{
152
std::vector<Matrix4> data;
153
154
// Very simple matrix data allocation scheme.
155
for (size_t index = 0; index < count; ++index)
156
{
157
Matrix4 mat;
158
for (int row = 0; row < 4; ++row)
159
{
160
for (int col = 0; col < 4; ++col)
161
{
162
mat.data[row * 4 + col] = (row * col + parity) % 2 == 0 ? 1.0f : -1.0f;
163
}
164
}
165
166
data.push_back(mat);
167
}
168
169
return data;
170
}
171
172
UniformsBenchmark::UniformsBenchmark() : ANGLERenderTest("Uniforms", GetParam()), mPrograms({})
173
{
174
// Fails on Windows7 NVIDIA Vulkan, presumably due to old drivers. http://crbug.com/1096510
175
if (IsWindows7() && IsNVIDIA() &&
176
GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
177
{
178
mSkipTest = true;
179
}
180
}
181
182
void UniformsBenchmark::initializeBenchmark()
183
{
184
const auto &params = GetParam();
185
186
// Verify the uniform counts are within the limits
187
GLint maxVertexUniformVectors, maxFragmentUniformVectors;
188
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors);
189
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors);
190
191
GLint vectorCountPerUniform;
192
bool isMatrix;
193
switch (params.dataType)
194
{
195
case DataType::MAT3x3:
196
vectorCountPerUniform = 3;
197
isMatrix = true;
198
break;
199
case DataType::MAT3x4:
200
// depends on transpose, conservatively set to 4
201
vectorCountPerUniform = 4;
202
isMatrix = true;
203
break;
204
case DataType::MAT4x4:
205
vectorCountPerUniform = 4;
206
isMatrix = true;
207
break;
208
default:
209
vectorCountPerUniform = 1;
210
isMatrix = false;
211
break;
212
}
213
214
GLint numVertexUniformVectors =
215
static_cast<GLint>(params.numVertexUniforms) * vectorCountPerUniform;
216
GLint numFragmentUniformVectors =
217
static_cast<GLint>(params.numFragmentUniforms) * vectorCountPerUniform;
218
219
if (numVertexUniformVectors > maxVertexUniformVectors)
220
{
221
FAIL() << "Vertex uniform vector count (" << numVertexUniformVectors << ")"
222
<< " exceeds maximum vertex uniform vector count: " << maxVertexUniformVectors
223
<< std::endl;
224
}
225
if (numFragmentUniformVectors > maxFragmentUniformVectors)
226
{
227
FAIL() << "Fragment uniform vector count (" << numFragmentUniformVectors << ")"
228
<< " exceeds maximum fragment uniform vector count: " << maxFragmentUniformVectors
229
<< std::endl;
230
}
231
232
initShaders();
233
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
234
glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
235
236
if (isMatrix)
237
{
238
size_t count = params.numVertexUniforms + params.numFragmentUniforms;
239
240
mMatrixData[0] = GenMatrixData(count, 0);
241
if (params.dataMode == DataMode::REPEAT)
242
{
243
mMatrixData[1] = GenMatrixData(count, 0);
244
}
245
else
246
{
247
mMatrixData[1] = GenMatrixData(count, 1);
248
}
249
}
250
251
GLint attribLocation = glGetAttribLocation(mPrograms[0], "pos");
252
ASSERT_NE(-1, attribLocation);
253
ASSERT_EQ(attribLocation, glGetAttribLocation(mPrograms[1], "pos"));
254
glVertexAttrib4f(attribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
255
256
ASSERT_GL_NO_ERROR();
257
}
258
259
std::string GetUniformLocationName(size_t idx, bool vertexShader)
260
{
261
std::stringstream strstr;
262
strstr << (vertexShader ? "vs" : "fs") << "_u_" << idx;
263
return strstr.str();
264
}
265
266
void UniformsBenchmark::initShaders()
267
{
268
const auto &params = GetParam();
269
270
const std::string kUniformVarPlaceHolder = "%s";
271
std::string typeString;
272
std::string uniformOperationTemplate;
273
switch (params.dataType)
274
{
275
case DataType::VEC4:
276
typeString = "vec4";
277
uniformOperationTemplate = kUniformVarPlaceHolder;
278
break;
279
case DataType::MAT3x3:
280
typeString = "mat3";
281
uniformOperationTemplate =
282
"mat4(" + kUniformVarPlaceHolder + ") * vec4(1.0, 1.0, 1.0, 1.0)";
283
break;
284
case DataType::MAT3x4:
285
typeString = "mat3x4";
286
uniformOperationTemplate =
287
"mat4(" + kUniformVarPlaceHolder + ") * vec4(1.0, 1.0, 1.0, 1.0)";
288
break;
289
case DataType::MAT4x4:
290
typeString = "mat4";
291
uniformOperationTemplate = kUniformVarPlaceHolder + "* vec4(1.0, 1.0, 1.0, 1.0)";
292
break;
293
default:
294
UNREACHABLE();
295
}
296
297
std::stringstream vstrstr;
298
vstrstr << "#version 300 es\n";
299
vstrstr << "precision mediump float;\n";
300
vstrstr << "in vec4 pos;\n";
301
302
for (size_t i = 0; i < params.numVertexUniforms; i++)
303
{
304
vstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, true) << ";\n";
305
}
306
307
vstrstr << "void main()\n"
308
"{\n"
309
" gl_Position = pos;\n";
310
for (size_t i = 0; i < params.numVertexUniforms; i++)
311
{
312
std::string uniformOperation = uniformOperationTemplate;
313
std::size_t pos = uniformOperation.find(kUniformVarPlaceHolder);
314
ASSERT(pos != std::string::npos);
315
uniformOperation.replace(pos, kUniformVarPlaceHolder.size(),
316
GetUniformLocationName(i, true));
317
vstrstr << " gl_Position += ";
318
vstrstr << uniformOperation;
319
vstrstr << ";\n";
320
}
321
vstrstr << "}";
322
323
std::stringstream fstrstr;
324
fstrstr << "#version 300 es\n";
325
fstrstr << "precision mediump float;\n";
326
fstrstr << "out vec4 fragColor;\n";
327
328
for (size_t i = 0; i < params.numFragmentUniforms; i++)
329
{
330
fstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, false) << ";\n";
331
}
332
fstrstr << "void main()\n"
333
"{\n"
334
" fragColor = vec4(0, 0, 0, 0);\n";
335
for (size_t i = 0; i < params.numFragmentUniforms; i++)
336
{
337
std::string uniformOperation = uniformOperationTemplate;
338
std::size_t pos = uniformOperation.find(kUniformVarPlaceHolder);
339
ASSERT(pos != std::string::npos);
340
uniformOperation.replace(pos, kUniformVarPlaceHolder.size(),
341
GetUniformLocationName(i, false));
342
fstrstr << " fragColor += ";
343
fstrstr << uniformOperation;
344
fstrstr << ";\n";
345
}
346
fstrstr << "}";
347
348
mPrograms[0] = CompileProgram(vstrstr.str().c_str(), fstrstr.str().c_str());
349
ASSERT_NE(0u, mPrograms[0]);
350
mPrograms[1] = CompileProgram(vstrstr.str().c_str(), fstrstr.str().c_str());
351
ASSERT_NE(0u, mPrograms[1]);
352
353
for (size_t i = 0; i < params.numVertexUniforms; ++i)
354
{
355
std::string name = GetUniformLocationName(i, true);
356
GLint location = glGetUniformLocation(mPrograms[0], name.c_str());
357
ASSERT_NE(-1, location);
358
ASSERT_EQ(location, glGetUniformLocation(mPrograms[1], name.c_str()));
359
mUniformLocations.push_back(location);
360
}
361
for (size_t i = 0; i < params.numFragmentUniforms; ++i)
362
{
363
std::string name = GetUniformLocationName(i, false);
364
GLint location = glGetUniformLocation(mPrograms[0], name.c_str());
365
ASSERT_NE(-1, location);
366
ASSERT_EQ(location, glGetUniformLocation(mPrograms[1], name.c_str()));
367
mUniformLocations.push_back(location);
368
}
369
370
// Use the program object
371
glUseProgram(mPrograms[0]);
372
}
373
374
void UniformsBenchmark::destroyBenchmark()
375
{
376
glDeleteProgram(mPrograms[0]);
377
glDeleteProgram(mPrograms[1]);
378
}
379
380
// Hopefully the compiler is smart enough to inline the lambda setUniformsFunc.
381
template <bool MultiProgram, typename SetUniformFunc>
382
void UniformsBenchmark::drawLoop(const SetUniformFunc &setUniformsFunc)
383
{
384
const auto &params = GetParam();
385
386
size_t frameIndex = 0;
387
388
for (size_t it = 0; it < params.iterationsPerStep; ++it, frameIndex = (frameIndex == 0 ? 1 : 0))
389
{
390
if (MultiProgram)
391
{
392
glUseProgram(mPrograms[frameIndex]);
393
}
394
if (params.dataMode == DataMode::UPDATE)
395
{
396
for (size_t uniform = 0; uniform < mUniformLocations.size(); ++uniform)
397
{
398
setUniformsFunc(mUniformLocations, mMatrixData, uniform, frameIndex);
399
}
400
}
401
glDrawArrays(GL_TRIANGLES, 0, 3);
402
}
403
}
404
405
void UniformsBenchmark::drawBenchmark()
406
{
407
const auto &params = GetParam();
408
409
GLboolean transpose = static_cast<GLboolean>(params.matrixLayout == MatrixLayout::TRANSPOSE);
410
411
switch (params.dataType)
412
{
413
case DataType::MAT4x4:
414
{
415
auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,
416
size_t uniform, size_t frameIndex) {
417
glUniformMatrix4fv(locations[uniform], 1, transpose,
418
matrixData[frameIndex][uniform].data);
419
};
420
421
drawLoop<false>(setFunc);
422
break;
423
}
424
case DataType::MAT3x4:
425
{
426
auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,
427
size_t uniform, size_t frameIndex) {
428
glUniformMatrix3x4fv(locations[uniform], 1, transpose,
429
matrixData[frameIndex][uniform].data);
430
};
431
432
drawLoop<false>(setFunc);
433
break;
434
}
435
case DataType::MAT3x3:
436
{
437
auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,
438
size_t uniform, size_t frameIndex) {
439
glUniformMatrix3fv(locations[uniform], 1, transpose,
440
matrixData[frameIndex][uniform].data);
441
};
442
443
drawLoop<false>(setFunc);
444
break;
445
}
446
case DataType::VEC4:
447
{
448
auto setFunc = [](const std::vector<GLuint> &locations, const MatrixData &matrixData,
449
size_t uniform, size_t frameIndex) {
450
float value = static_cast<float>(uniform);
451
glUniform4f(locations[uniform], value, value, value, value);
452
};
453
454
if (params.programMode == ProgramMode::MULTIPLE)
455
{
456
drawLoop<true>(setFunc);
457
}
458
else
459
{
460
drawLoop<false>(setFunc);
461
}
462
break;
463
}
464
default:
465
UNREACHABLE();
466
}
467
468
ASSERT_GL_NO_ERROR();
469
}
470
471
using namespace egl_platform;
472
473
UniformsParams VectorUniforms(const EGLPlatformParameters &egl,
474
DataMode dataMode,
475
ProgramMode programMode = ProgramMode::SINGLE)
476
{
477
UniformsParams params;
478
params.eglParameters = egl;
479
params.dataMode = dataMode;
480
params.programMode = programMode;
481
return params;
482
}
483
484
UniformsParams MatrixUniforms(const EGLPlatformParameters &egl,
485
DataMode dataMode,
486
DataType dataType,
487
MatrixLayout matrixLayout)
488
{
489
UniformsParams params;
490
params.eglParameters = egl;
491
params.dataType = dataType;
492
params.dataMode = dataMode;
493
params.matrixLayout = matrixLayout;
494
495
// Reduce the number of uniforms to fit within smaller upper limits on some configs.
496
params.numVertexUniforms = 55;
497
params.numFragmentUniforms = 55;
498
499
return params;
500
}
501
502
} // anonymous namespace
503
504
TEST_P(UniformsBenchmark, Run)
505
{
506
run();
507
}
508
509
ANGLE_INSTANTIATE_TEST(
510
UniformsBenchmark,
511
VectorUniforms(D3D11(), DataMode::REPEAT),
512
VectorUniforms(D3D11(), DataMode::UPDATE),
513
VectorUniforms(D3D11_NULL(), DataMode::UPDATE),
514
VectorUniforms(OPENGL_OR_GLES(), DataMode::UPDATE),
515
VectorUniforms(OPENGL_OR_GLES(), DataMode::REPEAT),
516
VectorUniforms(OPENGL_OR_GLES_NULL(), DataMode::UPDATE),
517
MatrixUniforms(D3D11(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
518
MatrixUniforms(OPENGL_OR_GLES(),
519
DataMode::UPDATE,
520
DataType::MAT4x4,
521
MatrixLayout::NO_TRANSPOSE),
522
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
523
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::TRANSPOSE),
524
MatrixUniforms(VULKAN_NULL(), DataMode::REPEAT, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
525
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT3x4, MatrixLayout::NO_TRANSPOSE),
526
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT3x3, MatrixLayout::TRANSPOSE),
527
MatrixUniforms(VULKAN_NULL(), DataMode::REPEAT, DataType::MAT3x3, MatrixLayout::TRANSPOSE),
528
MatrixUniforms(VULKAN(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
529
MatrixUniforms(VULKAN(), DataMode::REPEAT, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
530
MatrixUniforms(VULKAN(), DataMode::UPDATE, DataType::MAT3x3, MatrixLayout::NO_TRANSPOSE),
531
MatrixUniforms(VULKAN(), DataMode::REPEAT, DataType::MAT3x3, MatrixLayout::NO_TRANSPOSE),
532
VectorUniforms(D3D11_NULL(), DataMode::REPEAT, ProgramMode::MULTIPLE));
533
534