Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp
1693 views
1
//
2
// Copyright 2020 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
7
// DrawBaseVertexVariantsTest: Tests variants of drawElements*BaseVertex* call from different
8
// extensions
9
10
#include "gpu_info_util/SystemInfo.h"
11
#include "test_utils/ANGLETest.h"
12
#include "test_utils/gl_raii.h"
13
14
#include <numeric>
15
16
using namespace angle;
17
18
namespace
19
{
20
21
// Create a kWidth * kHeight canvas equally split into kCountX * kCountY tiles
22
// each containing a quad partially covering each tile
23
constexpr uint32_t kWidth = 256;
24
constexpr uint32_t kHeight = 256;
25
constexpr uint32_t kCountX = 8;
26
constexpr uint32_t kCountY = 8;
27
constexpr int kBoxCount = kCountX * kCountY;
28
constexpr uint32_t kIndexPatternRepeatCount = 3;
29
constexpr std::array<GLfloat, 2> kTileSize = {
30
1.f / static_cast<GLfloat>(kCountX),
31
1.f / static_cast<GLfloat>(kCountY),
32
};
33
constexpr std::array<uint32_t, 2> kTilePixelSize = {kWidth / kCountX, kHeight / kCountY};
34
constexpr std::array<GLfloat, 2> kQuadRadius = {0.25f * kTileSize[0], 0.25f * kTileSize[1]};
35
constexpr std::array<uint32_t, 2> kPixelCheckSize = {
36
static_cast<uint32_t>(kQuadRadius[0] * kWidth),
37
static_cast<uint32_t>(kQuadRadius[1] * kHeight)};
38
constexpr GLenum kBufferDataUsage[] = {GL_STATIC_DRAW, GL_DYNAMIC_DRAW, GL_STREAM_DRAW};
39
40
constexpr std::array<GLfloat, 2> GetTileCenter(uint32_t x, uint32_t y)
41
{
42
return {
43
kTileSize[0] * (0.5f + static_cast<GLfloat>(x)),
44
kTileSize[1] * (0.5f + static_cast<GLfloat>(y)),
45
};
46
}
47
constexpr std::array<std::array<GLfloat, 2>, 4> GetQuadVertices(uint32_t x, uint32_t y)
48
{
49
const auto center = GetTileCenter(x, y);
50
return {
51
std::array<GLfloat, 2>{center[0] - kQuadRadius[0], center[1] - kQuadRadius[1]},
52
std::array<GLfloat, 2>{center[0] + kQuadRadius[0], center[1] - kQuadRadius[1]},
53
std::array<GLfloat, 2>{center[0] + kQuadRadius[0], center[1] + kQuadRadius[1]},
54
std::array<GLfloat, 2>{center[0] - kQuadRadius[0], center[1] + kQuadRadius[1]},
55
};
56
}
57
58
enum class DrawCallVariants
59
{
60
DrawElementsBaseVertex,
61
DrawElementsInstancedBaseVertex,
62
DrawRangeElementsBaseVertex,
63
DrawElementsInstancedBaseVertexBaseInstance
64
};
65
66
using DrawBaseVertexVariantsTestParams = std::tuple<angle::PlatformParameters, GLenum>;
67
68
std::string DrawBaseVertexVariantsTestPrint(
69
const ::testing::TestParamInfo<DrawBaseVertexVariantsTestParams> &paramsInfo)
70
{
71
const DrawBaseVertexVariantsTestParams &params = paramsInfo.param;
72
std::ostringstream out;
73
74
out << std::get<0>(params) << "__";
75
76
switch (std::get<1>(params))
77
{
78
case GL_STATIC_DRAW:
79
out << "STATIC_DRAW";
80
break;
81
case GL_DYNAMIC_DRAW:
82
out << "DYNAMIC_DRAW";
83
break;
84
case GL_STREAM_DRAW:
85
out << "STREAM_DRAW";
86
break;
87
default:
88
out << "UPDATE_THIS_SWITCH";
89
break;
90
}
91
92
return out.str();
93
}
94
95
// These tests check correctness of variants of baseVertex draw calls from different extensions
96
97
class DrawBaseVertexVariantsTest : public ANGLETestWithParam<DrawBaseVertexVariantsTestParams>
98
{
99
protected:
100
DrawBaseVertexVariantsTest()
101
{
102
setWindowWidth(kWidth);
103
setWindowHeight(kHeight);
104
setConfigRedBits(8);
105
setConfigGreenBits(8);
106
setConfigBlueBits(8);
107
setConfigAlphaBits(8);
108
109
std::array<GLushort, 6> indices = {0, 1, 2, 0, 2, 3};
110
mIndices.resize(indices.size() * kIndexPatternRepeatCount);
111
for (uint32_t i = 0; i < kIndexPatternRepeatCount; i++)
112
{
113
size_t o = i * indices.size();
114
size_t vo = i * 4; // each quad has 4 vertices, index offset by 4
115
for (size_t j = 0; j < indices.size(); j++)
116
{
117
mIndices[o + j] = vo + indices[j];
118
}
119
}
120
121
mColorPalette = {GLColor(0x7f, 0x7f, 0x7f, 0xff),
122
GLColor::red,
123
GLColor::green,
124
GLColor::yellow,
125
GLColor::blue,
126
GLColor::magenta,
127
GLColor::cyan,
128
GLColor::white};
129
130
for (uint32_t y = 0; y < kCountY; ++y)
131
{
132
for (uint32_t x = 0; x < kCountX; ++x)
133
{
134
// v3 ---- v2
135
// | |
136
// | |
137
// v0 ---- v1
138
139
const auto vs = ::GetQuadVertices(x, y);
140
141
for (const auto &v : vs)
142
{
143
mVertices.insert(mVertices.end(), v.begin(), v.end());
144
}
145
146
const auto &colorPicked = mColorPalette[(x + y) % mColorPalette.size()];
147
for (int i = 0; i < 4; ++i)
148
{
149
mVertexColors.push_back(colorPicked.R);
150
mVertexColors.push_back(colorPicked.G);
151
mVertexColors.push_back(colorPicked.B);
152
mVertexColors.push_back(colorPicked.A);
153
}
154
}
155
}
156
157
mRegularIndices.resize(kCountY * kCountX * mIndices.size());
158
for (uint32_t y = 0; y < kCountY; y++)
159
{
160
for (uint32_t x = 0; x < kCountX; x++)
161
{
162
uint32_t i = x + y * kCountX;
163
uint32_t oi = 6 * i;
164
uint32_t ov = 4 * i;
165
for (uint32_t j = 0; j < 6; j++)
166
{
167
mRegularIndices[oi + j] = mIndices[j] + ov;
168
}
169
}
170
}
171
}
172
173
void setupProgram(GLProgram &program)
174
{
175
constexpr char vs[] = R"(
176
precision mediump float;
177
attribute vec2 vPosition;
178
attribute vec4 vColor;
179
varying vec4 color;
180
void main()
181
{
182
gl_Position = vec4(vec3(vPosition, 1.0) * 2.0 - 1.0, 1.0);
183
color = vColor;
184
})";
185
constexpr char fs[] = R"(
186
precision mediump float;
187
varying vec4 color;
188
void main()
189
{
190
gl_FragColor = color;
191
})";
192
program.makeRaster(vs, fs);
193
EXPECT_GL_NO_ERROR();
194
ASSERT_TRUE(program.valid());
195
glUseProgram(program.get());
196
mPositionLoc = glGetAttribLocation(program.get(), "vPosition");
197
ASSERT_NE(-1, mPositionLoc);
198
mColorLoc = glGetAttribLocation(program.get(), "vColor");
199
ASSERT_NE(-1, mColorLoc);
200
}
201
202
void setupIndexedBuffers(GLBuffer &vertexPositionBuffer,
203
GLBuffer &vertexColorBuffer,
204
GLBuffer &indexBuffer)
205
{
206
GLenum usage = std::get<1>(GetParam());
207
208
glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer);
209
glBufferData(GL_ARRAY_BUFFER, sizeof(GLubyte) * mVertexColors.size(), mVertexColors.data(),
210
usage);
211
212
glEnableVertexAttribArray(mColorLoc);
213
glVertexAttribPointer(mColorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
214
215
glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer);
216
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(), usage);
217
218
glEnableVertexAttribArray(mPositionLoc);
219
glVertexAttribPointer(mPositionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
220
221
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
222
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
223
usage);
224
225
ASSERT_GL_NO_ERROR();
226
}
227
228
void doDrawElementsBaseVertexVariants(DrawCallVariants drawCallType)
229
{
230
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
231
232
int baseRepetition = 0;
233
int i = 0;
234
235
// Start at various repetitions within the patterned index buffer to exercise base
236
// index.
237
238
static_assert(kIndexPatternRepeatCount >= 3, "Repeat pattern count should be at least 3");
239
240
while (i < kBoxCount)
241
{
242
int repetitionCount = std::min(3 - baseRepetition, kBoxCount - i);
243
244
updateVertexColorData(i, repetitionCount);
245
246
switch (drawCallType)
247
{
248
case DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstance:
249
glDrawElementsInstancedBaseVertexBaseInstanceANGLE(
250
GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT,
251
reinterpret_cast<GLvoid *>(
252
static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
253
1, (i - baseRepetition) * 4, 0);
254
break;
255
case DrawCallVariants::DrawElementsBaseVertex:
256
glDrawElementsBaseVertexEXT(
257
GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT,
258
reinterpret_cast<GLvoid *>(
259
static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
260
(i - baseRepetition) * 4);
261
break;
262
case DrawCallVariants::DrawElementsInstancedBaseVertex:
263
glDrawElementsInstancedBaseVertexEXT(
264
GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT,
265
reinterpret_cast<GLvoid *>(
266
static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
267
1, (i - baseRepetition) * 4);
268
break;
269
case DrawCallVariants::DrawRangeElementsBaseVertex:
270
glDrawRangeElementsBaseVertexEXT(
271
GL_TRIANGLES, baseRepetition * 4,
272
(baseRepetition + repetitionCount) * 4 - 1, repetitionCount * 6,
273
GL_UNSIGNED_SHORT,
274
reinterpret_cast<GLvoid *>(
275
static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
276
(i - baseRepetition) * 4);
277
break;
278
default:
279
EXPECT_TRUE(false);
280
break;
281
}
282
283
baseRepetition = (baseRepetition + 1) % 3;
284
i += repetitionCount;
285
}
286
287
EXPECT_GL_NO_ERROR();
288
checkDrawResult();
289
}
290
291
void updateVertexColorData(GLint drawnQuadCount, GLint toDrawQuadCount)
292
{
293
// update the vertex color of the next [count] of quads to draw
294
if (std::get<1>(GetParam()) == GL_STATIC_DRAW)
295
{
296
return;
297
}
298
299
GLint offset = sizeof(GLubyte) * drawnQuadCount * 4 * sizeof(GLColor);
300
301
for (GLint i = 0; i < toDrawQuadCount; i++)
302
{
303
const GLColor &color = mColorPalette[(drawnQuadCount + i) % mColorPalette.size()];
304
for (GLint j = 0; j < 4; j++)
305
{
306
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(GLColor), color.data());
307
offset += sizeof(GLColor);
308
}
309
}
310
}
311
312
void checkDrawResult()
313
{
314
bool dynamicLayout = std::get<1>(GetParam()) == GL_STATIC_DRAW ? false : true;
315
316
for (uint32_t y = 0; y < kCountY; ++y)
317
{
318
for (uint32_t x = 0; x < kCountX; ++x)
319
{
320
uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
321
uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
322
323
const auto &color =
324
mColorPalette[(dynamicLayout ? x : x + y) % mColorPalette.size()];
325
326
EXPECT_PIXEL_NEAR(center_x - kPixelCheckSize[0] / 2,
327
center_y - kPixelCheckSize[1] / 2, color[0], color[1], color[2],
328
color[3], 1);
329
}
330
}
331
}
332
333
bool requestAngleBaseVertexBaseInstanceExtensions()
334
{
335
if (getClientMajorVersion() <= 2)
336
{
337
if (!EnsureGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
338
{
339
return false;
340
}
341
}
342
return EnsureGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance");
343
}
344
345
bool requestNativeBaseVertexExtensions()
346
{
347
return (EnsureGLExtensionEnabled("GL_OES_draw_elements_base_vertex") ||
348
EnsureGLExtensionEnabled("GL_EXT_draw_elements_base_vertex"));
349
}
350
351
std::vector<GLushort> mIndices;
352
std::vector<GLfloat> mVertices;
353
std::vector<GLubyte> mVertexColors;
354
355
std::vector<GLColor> mColorPalette;
356
std::vector<GLushort> mRegularIndices;
357
GLint mPositionLoc;
358
GLint mColorLoc;
359
};
360
361
// Test drawElementsBaseVertex from OES/EXT_draw_elements_base_vertex
362
TEST_P(DrawBaseVertexVariantsTest, DrawElementsBaseVertex)
363
{
364
ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions());
365
366
GLProgram program;
367
setupProgram(program);
368
369
GLBuffer indexBuffer;
370
GLBuffer vertexPositionBuffer;
371
GLBuffer vertexColorBuffer;
372
setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
373
374
// for potential update vertex color later
375
glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer);
376
377
doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsBaseVertex);
378
}
379
380
// Test drawElementsInstancedBaseVertex from OES/EXT_draw_elements_base_vertex
381
TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertex)
382
{
383
ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions());
384
385
GLProgram program;
386
setupProgram(program);
387
388
GLBuffer indexBuffer;
389
GLBuffer vertexPositionBuffer;
390
GLBuffer vertexColorBuffer;
391
setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
392
393
// for potential update vertex color later
394
glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer);
395
396
doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertex);
397
}
398
399
// Test drawRangeElementsBaseVertex from OES/EXT_draw_elements_base_vertex
400
TEST_P(DrawBaseVertexVariantsTest, DrawRangeElementsBaseVertex)
401
{
402
ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions());
403
404
GLProgram program;
405
setupProgram(program);
406
407
GLBuffer indexBuffer;
408
GLBuffer vertexPositionBuffer;
409
GLBuffer vertexColorBuffer;
410
setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
411
412
// for potential update vertex color later
413
glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer);
414
415
doDrawElementsBaseVertexVariants(DrawCallVariants::DrawRangeElementsBaseVertex);
416
}
417
418
// Test drawElementsInstancedBaseVertexBaseInstance from ANGLE_base_vertex_base_instance
419
TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexBaseInstance)
420
{
421
ANGLE_SKIP_TEST_IF(!requestAngleBaseVertexBaseInstanceExtensions());
422
423
GLProgram program;
424
setupProgram(program);
425
426
GLBuffer indexBuffer;
427
GLBuffer vertexPositionBuffer;
428
GLBuffer vertexColorBuffer;
429
setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
430
431
// for potential update vertex color later
432
glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer);
433
434
doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstance);
435
}
436
437
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBaseVertexVariantsTest);
438
ANGLE_INSTANTIATE_TEST_COMBINE_1(DrawBaseVertexVariantsTest,
439
DrawBaseVertexVariantsTestPrint,
440
testing::ValuesIn(kBufferDataUsage),
441
ES3_D3D11(),
442
ES3_OPENGL(),
443
ES3_OPENGLES(),
444
ES3_VULKAN());
445
446
} // namespace
447
448