Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/gl_tests/BlendFuncExtendedTest.cpp
1693 views
1
//
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
// BlendFuncExtendedTest
7
// Test EXT_blend_func_extended
8
9
#include "test_utils/ANGLETest.h"
10
#include "test_utils/gl_raii.h"
11
12
#include "util/shader_utils.h"
13
14
#include <algorithm>
15
#include <cmath>
16
#include <fstream>
17
18
using namespace angle;
19
20
namespace
21
{
22
23
// Partial implementation of weight function for GLES 2 blend equation that
24
// is dual-source aware.
25
template <int factor, int index>
26
float Weight(const float /*dst*/[4], const float src[4], const float src1[4])
27
{
28
if (factor == GL_SRC_COLOR)
29
return src[index];
30
if (factor == GL_SRC_ALPHA)
31
return src[3];
32
if (factor == GL_SRC1_COLOR_EXT)
33
return src1[index];
34
if (factor == GL_SRC1_ALPHA_EXT)
35
return src1[3];
36
if (factor == GL_ONE_MINUS_SRC1_COLOR_EXT)
37
return 1.0f - src1[index];
38
if (factor == GL_ONE_MINUS_SRC1_ALPHA_EXT)
39
return 1.0f - src1[3];
40
return 0.0f;
41
}
42
43
GLubyte ScaleChannel(float weight)
44
{
45
return static_cast<GLubyte>(std::floor(std::max(0.0f, std::min(1.0f, weight)) * 255.0f));
46
}
47
48
// Implementation of GLES 2 blend equation that is dual-source aware.
49
template <int RGBs, int RGBd, int As, int Ad>
50
void BlendEquationFuncAdd(const float dst[4],
51
const float src[4],
52
const float src1[4],
53
angle::GLColor *result)
54
{
55
float r[4];
56
r[0] = src[0] * Weight<RGBs, 0>(dst, src, src1) + dst[0] * Weight<RGBd, 0>(dst, src, src1);
57
r[1] = src[1] * Weight<RGBs, 1>(dst, src, src1) + dst[1] * Weight<RGBd, 1>(dst, src, src1);
58
r[2] = src[2] * Weight<RGBs, 2>(dst, src, src1) + dst[2] * Weight<RGBd, 2>(dst, src, src1);
59
r[3] = src[3] * Weight<As, 3>(dst, src, src1) + dst[3] * Weight<Ad, 3>(dst, src, src1);
60
61
result->R = ScaleChannel(r[0]);
62
result->G = ScaleChannel(r[1]);
63
result->B = ScaleChannel(r[2]);
64
result->A = ScaleChannel(r[3]);
65
}
66
67
void CheckPixels(GLint x,
68
GLint y,
69
GLsizei width,
70
GLsizei height,
71
GLint tolerance,
72
const angle::GLColor &color)
73
{
74
for (GLint yy = 0; yy < height; ++yy)
75
{
76
for (GLint xx = 0; xx < width; ++xx)
77
{
78
const auto px = x + xx;
79
const auto py = y + yy;
80
EXPECT_PIXEL_COLOR_NEAR(px, py, color, 1);
81
}
82
}
83
}
84
85
const GLuint kWidth = 100;
86
const GLuint kHeight = 100;
87
88
class EXTBlendFuncExtendedTest : public ANGLETest
89
{};
90
91
class EXTBlendFuncExtendedTestES3 : public ANGLETest
92
{};
93
94
class EXTBlendFuncExtendedDrawTest : public ANGLETest
95
{
96
protected:
97
EXTBlendFuncExtendedDrawTest() : mProgram(0)
98
{
99
setWindowWidth(kWidth);
100
setWindowHeight(kHeight);
101
setConfigRedBits(8);
102
setConfigGreenBits(8);
103
setConfigBlueBits(8);
104
setConfigAlphaBits(8);
105
}
106
107
void testSetUp() override
108
{
109
glGenBuffers(1, &mVBO);
110
glBindBuffer(GL_ARRAY_BUFFER, mVBO);
111
112
static const float vertices[] = {
113
1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
114
};
115
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
116
117
ASSERT_GL_NO_ERROR();
118
}
119
120
void testTearDown() override
121
{
122
glDeleteBuffers(1, &mVBO);
123
if (mProgram)
124
{
125
glDeleteProgram(mProgram);
126
}
127
128
ASSERT_GL_NO_ERROR();
129
}
130
131
void makeProgram(const char *vertSource, const char *fragSource)
132
{
133
mProgram = CompileProgram(vertSource, fragSource);
134
135
ASSERT_NE(0u, mProgram);
136
}
137
138
virtual GLint getVertexAttribLocation(const char *name)
139
{
140
return glGetAttribLocation(mProgram, name);
141
}
142
143
virtual GLint getFragmentUniformLocation(const char *name)
144
{
145
return glGetUniformLocation(mProgram, name);
146
}
147
148
virtual void setUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
149
{
150
glUniform4f(location, v0, v1, v2, v3);
151
}
152
153
void drawTest()
154
{
155
glUseProgram(mProgram);
156
157
GLint position = getVertexAttribLocation(essl1_shaders::PositionAttrib());
158
GLint src0 = getFragmentUniformLocation("src0");
159
GLint src1 = getFragmentUniformLocation("src1");
160
ASSERT_GL_NO_ERROR();
161
162
glBindBuffer(GL_ARRAY_BUFFER, mVBO);
163
glEnableVertexAttribArray(position);
164
glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
165
ASSERT_GL_NO_ERROR();
166
167
static const float kDst[4] = {0.5f, 0.5f, 0.5f, 0.5f};
168
static const float kSrc0[4] = {1.0f, 1.0f, 1.0f, 1.0f};
169
static const float kSrc1[4] = {0.3f, 0.6f, 0.9f, 0.7f};
170
171
setUniform4f(src0, kSrc0[0], kSrc0[1], kSrc0[2], kSrc0[3]);
172
setUniform4f(src1, kSrc1[0], kSrc1[1], kSrc1[2], kSrc1[3]);
173
ASSERT_GL_NO_ERROR();
174
175
glEnable(GL_BLEND);
176
glBlendEquation(GL_FUNC_ADD);
177
glViewport(0, 0, kWidth, kHeight);
178
glClearColor(kDst[0], kDst[1], kDst[2], kDst[3]);
179
ASSERT_GL_NO_ERROR();
180
181
{
182
glBlendFuncSeparate(GL_SRC1_COLOR_EXT, GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_COLOR_EXT,
183
GL_ONE_MINUS_SRC1_ALPHA_EXT);
184
185
glClear(GL_COLOR_BUFFER_BIT);
186
glDrawArrays(GL_TRIANGLES, 0, 6);
187
ASSERT_GL_NO_ERROR();
188
189
// verify
190
angle::GLColor color;
191
BlendEquationFuncAdd<GL_SRC1_COLOR_EXT, GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_COLOR_EXT,
192
GL_ONE_MINUS_SRC1_ALPHA_EXT>(kDst, kSrc0, kSrc1, &color);
193
194
CheckPixels(kWidth / 4, (3 * kHeight) / 4, 1, 1, 1, color);
195
CheckPixels(kWidth - 1, 0, 1, 1, 1, color);
196
}
197
198
{
199
glBlendFuncSeparate(GL_ONE_MINUS_SRC1_COLOR_EXT, GL_ONE_MINUS_SRC_ALPHA,
200
GL_ONE_MINUS_SRC_COLOR, GL_SRC1_ALPHA_EXT);
201
202
glClear(GL_COLOR_BUFFER_BIT);
203
glDrawArrays(GL_TRIANGLES, 0, 6);
204
ASSERT_GL_NO_ERROR();
205
206
// verify
207
angle::GLColor color;
208
BlendEquationFuncAdd<GL_ONE_MINUS_SRC1_COLOR_EXT, GL_ONE_MINUS_SRC_ALPHA,
209
GL_ONE_MINUS_SRC_COLOR, GL_SRC1_ALPHA_EXT>(kDst, kSrc0, kSrc1,
210
&color);
211
212
CheckPixels(kWidth / 4, (3 * kHeight) / 4, 1, 1, 1, color);
213
CheckPixels(kWidth - 1, 0, 1, 1, 1, color);
214
}
215
}
216
217
GLuint mVBO;
218
GLuint mProgram;
219
};
220
221
class EXTBlendFuncExtendedDrawTestES3 : public EXTBlendFuncExtendedDrawTest
222
{
223
protected:
224
EXTBlendFuncExtendedDrawTestES3() : EXTBlendFuncExtendedDrawTest(), mIsES31OrNewer(false) {}
225
226
void testSetUp() override
227
{
228
EXTBlendFuncExtendedDrawTest::testSetUp();
229
if (getClientMajorVersion() > 3 ||
230
(getClientMajorVersion() == 3 && getClientMinorVersion() >= 1))
231
{
232
mIsES31OrNewer = true;
233
}
234
}
235
236
virtual void checkOutputIndexQuery(const char *name, GLint expectedIndex)
237
{
238
GLint index = glGetFragDataIndexEXT(mProgram, name);
239
EXPECT_EQ(expectedIndex, index);
240
if (mIsES31OrNewer)
241
{
242
index = glGetProgramResourceLocationIndexEXT(mProgram, GL_PROGRAM_OUTPUT, name);
243
EXPECT_EQ(expectedIndex, index);
244
}
245
else
246
{
247
glGetProgramResourceLocationIndexEXT(mProgram, GL_PROGRAM_OUTPUT, name);
248
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
249
}
250
}
251
252
void LinkProgram()
253
{
254
glLinkProgram(mProgram);
255
GLint linked = 0;
256
glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
257
EXPECT_NE(0, linked);
258
glUseProgram(mProgram);
259
return;
260
}
261
262
private:
263
bool mIsES31OrNewer;
264
};
265
266
class EXTBlendFuncExtendedDrawTestES31 : public EXTBlendFuncExtendedDrawTestES3
267
{
268
protected:
269
EXTBlendFuncExtendedDrawTestES31()
270
: EXTBlendFuncExtendedDrawTestES3(), mPipeline(0), mVertexProgram(0), mFragProgram(0)
271
{}
272
273
GLint getVertexAttribLocation(const char *name) override
274
{
275
return glGetAttribLocation(mVertexProgram, name);
276
}
277
278
GLint getFragmentUniformLocation(const char *name) override
279
{
280
return glGetUniformLocation(mFragProgram, name);
281
}
282
283
void setUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) override
284
{
285
glActiveShaderProgram(mPipeline, mFragProgram);
286
EXTBlendFuncExtendedDrawTest::setUniform4f(location, v0, v1, v2, v3);
287
}
288
289
void checkOutputIndexQuery(const char *name, GLint expectedIndex) override
290
{
291
GLint index = glGetFragDataIndexEXT(mFragProgram, name);
292
EXPECT_EQ(expectedIndex, index);
293
index = glGetProgramResourceLocationIndexEXT(mFragProgram, GL_PROGRAM_OUTPUT, name);
294
EXPECT_EQ(expectedIndex, index);
295
}
296
297
void setupProgramPipeline(const char *vertexSource, const char *fragmentSource)
298
{
299
mVertexProgram = createShaderProgram(GL_VERTEX_SHADER, vertexSource);
300
ASSERT_NE(mVertexProgram, 0u);
301
mFragProgram = createShaderProgram(GL_FRAGMENT_SHADER, fragmentSource);
302
ASSERT_NE(mFragProgram, 0u);
303
304
// Generate a program pipeline and attach the programs to their respective stages
305
glGenProgramPipelines(1, &mPipeline);
306
EXPECT_GL_NO_ERROR();
307
glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertexProgram);
308
EXPECT_GL_NO_ERROR();
309
glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProgram);
310
EXPECT_GL_NO_ERROR();
311
glBindProgramPipeline(mPipeline);
312
EXPECT_GL_NO_ERROR();
313
}
314
315
GLuint createShaderProgram(GLenum type, const GLchar *shaderString)
316
{
317
GLShader shader(type);
318
if (!shader.get())
319
{
320
return 0;
321
}
322
323
glShaderSource(shader, 1, &shaderString, nullptr);
324
glCompileShader(shader);
325
326
GLuint program = glCreateProgram();
327
328
if (program)
329
{
330
GLint compiled;
331
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
332
glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
333
if (compiled)
334
{
335
glAttachShader(program, shader);
336
glLinkProgram(program);
337
glDetachShader(program, shader);
338
}
339
}
340
341
EXPECT_GL_NO_ERROR();
342
343
return program;
344
}
345
346
void testTearDown() override
347
{
348
EXTBlendFuncExtendedDrawTest::testTearDown();
349
if (mVertexProgram)
350
{
351
glDeleteProgram(mVertexProgram);
352
}
353
if (mFragProgram)
354
{
355
glDeleteProgram(mFragProgram);
356
}
357
if (mPipeline)
358
{
359
glDeleteProgramPipelines(1, &mPipeline);
360
}
361
362
ASSERT_GL_NO_ERROR();
363
}
364
365
GLuint mPipeline;
366
GLuint mVertexProgram;
367
GLuint mFragProgram;
368
};
369
} // namespace
370
371
// Test EXT_blend_func_extended related gets.
372
TEST_P(EXTBlendFuncExtendedTest, TestMaxDualSourceDrawBuffers)
373
{
374
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
375
376
GLint maxDualSourceDrawBuffers = 0;
377
glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers);
378
EXPECT_GT(maxDualSourceDrawBuffers, 0);
379
380
ASSERT_GL_NO_ERROR();
381
}
382
383
// Test a shader with EXT_blend_func_extended and gl_SecondaryFragColorEXT.
384
// Outputs to primary color buffer using primary and secondary colors.
385
TEST_P(EXTBlendFuncExtendedDrawTest, FragColor)
386
{
387
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
388
389
const char *kFragColorShader =
390
"#extension GL_EXT_blend_func_extended : require\n"
391
"precision mediump float;\n"
392
"uniform vec4 src0;\n"
393
"uniform vec4 src1;\n"
394
"void main() {\n"
395
" gl_FragColor = src0;\n"
396
" gl_SecondaryFragColorEXT = src1;\n"
397
"}\n";
398
399
makeProgram(essl1_shaders::vs::Simple(), kFragColorShader);
400
401
drawTest();
402
}
403
404
// Test a shader with EXT_blend_func_extended and gl_FragData.
405
// Outputs to a color buffer using primary and secondary frag data.
406
TEST_P(EXTBlendFuncExtendedDrawTest, FragData)
407
{
408
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
409
410
// Suspected VK driver bug http://anglebug.com/5523
411
ANGLE_SKIP_TEST_IF(IsVulkan() && (IsNVIDIA() || IsPixel2()));
412
413
// Suspected AMD VK driver bug http://anglebug.com/5537
414
ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
415
416
const char *kFragColorShader =
417
"#extension GL_EXT_blend_func_extended : require\n"
418
"precision mediump float;\n"
419
"uniform vec4 src0;\n"
420
"uniform vec4 src1;\n"
421
"void main() {\n"
422
" gl_FragData[0] = src0;\n"
423
" gl_SecondaryFragDataEXT[0] = src1;\n"
424
"}\n";
425
426
makeProgram(essl1_shaders::vs::Simple(), kFragColorShader);
427
428
drawTest();
429
}
430
431
// Test an ESSL 3.00 shader that uses two fragment outputs with locations specified in the shader.
432
TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentOutputLocationsInShader)
433
{
434
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
435
436
const char *kFragColorShader = R"(#version 300 es
437
#extension GL_EXT_blend_func_extended : require
438
precision mediump float;
439
uniform vec4 src0;
440
uniform vec4 src1;
441
layout(location = 0, index = 1) out vec4 outSrc1;
442
layout(location = 0, index = 0) out vec4 outSrc0;
443
void main() {
444
outSrc0 = src0;
445
outSrc1 = src1;
446
})";
447
448
makeProgram(essl3_shaders::vs::Simple(), kFragColorShader);
449
450
checkOutputIndexQuery("outSrc0", 0);
451
checkOutputIndexQuery("outSrc1", 1);
452
453
drawTest();
454
}
455
456
// Test an ESSL 3.00 shader that uses two fragment outputs with locations specified through the API.
457
TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentOutputLocationAPI)
458
{
459
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
460
461
constexpr char kFS[] = R"(#version 300 es
462
#extension GL_EXT_blend_func_extended : require
463
precision mediump float;
464
uniform vec4 src0;
465
uniform vec4 src1;
466
out vec4 outSrc1;
467
out vec4 outSrc0;
468
void main() {
469
outSrc0 = src0;
470
outSrc1 = src1;
471
})";
472
473
mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFS, [](GLuint program) {
474
glBindFragDataLocationIndexedEXT(program, 0, 0, "outSrc0");
475
glBindFragDataLocationIndexedEXT(program, 0, 1, "outSrc1");
476
});
477
478
ASSERT_NE(0u, mProgram);
479
480
checkOutputIndexQuery("outSrc0", 0);
481
checkOutputIndexQuery("outSrc1", 1);
482
483
drawTest();
484
}
485
486
// Test an ESSL 3.00 shader that uses two fragment outputs, with location for one specified through
487
// the API and location for another being set automatically.
488
TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentOutputLocationsAPIAndAutomatic)
489
{
490
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
491
492
constexpr char kFS[] = R"(#version 300 es
493
#extension GL_EXT_blend_func_extended : require
494
precision mediump float;
495
uniform vec4 src0;
496
uniform vec4 src1;
497
out vec4 outSrc1;
498
out vec4 outSrc0;
499
void main() {
500
outSrc0 = src0;
501
outSrc1 = src1;
502
})";
503
504
mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFS, [](GLuint program) {
505
glBindFragDataLocationIndexedEXT(program, 0, 1, "outSrc1");
506
});
507
508
ASSERT_NE(0u, mProgram);
509
510
checkOutputIndexQuery("outSrc0", 0);
511
checkOutputIndexQuery("outSrc1", 1);
512
513
drawTest();
514
}
515
516
// Test an ESSL 3.00 shader that uses two array fragment outputs with locations specified through
517
// the API.
518
TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentArrayOutputLocationsAPI)
519
{
520
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
521
522
// TODO: Investigate this mac-only failure. http://angleproject.com/1085
523
ANGLE_SKIP_TEST_IF(IsOSX());
524
525
// Suspected VK driver bug http://anglebug.com/5523
526
ANGLE_SKIP_TEST_IF(IsVulkan() && (IsNVIDIA() || IsPixel2()));
527
528
constexpr char kFS[] = R"(#version 300 es
529
#extension GL_EXT_blend_func_extended : require
530
precision mediump float;
531
uniform vec4 src0;
532
uniform vec4 src1;
533
out vec4 outSrc1[1];
534
out vec4 outSrc0[1];
535
void main() {
536
outSrc0[0] = src0;
537
outSrc1[0] = src1;
538
})";
539
540
mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFS, [](GLuint program) {
541
// Specs aren't very clear on what kind of name should be used when binding location for
542
// array variables. We only allow names that do include the "[0]" suffix.
543
glBindFragDataLocationIndexedEXT(program, 0, 0, "outSrc0[0]");
544
glBindFragDataLocationIndexedEXT(program, 0, 1, "outSrc1[0]");
545
});
546
547
ASSERT_NE(0u, mProgram);
548
549
// The extension spec is not very clear on what name can be used for the queries for array
550
// variables. We're checking that the queries work in the same way as specified in OpenGL 4.4
551
// page 107.
552
checkOutputIndexQuery("outSrc0[0]", 0);
553
checkOutputIndexQuery("outSrc1[0]", 1);
554
checkOutputIndexQuery("outSrc0", 0);
555
checkOutputIndexQuery("outSrc1", 1);
556
557
// These queries use an out of range array index so they should return -1.
558
checkOutputIndexQuery("outSrc0[1]", -1);
559
checkOutputIndexQuery("outSrc1[1]", -1);
560
561
drawTest();
562
}
563
564
// Ported from TranslatorVariants/EXTBlendFuncExtendedES3DrawTest
565
// Test that tests glBindFragDataLocationEXT, glBindFragDataLocationIndexedEXT,
566
// glGetFragDataLocation, glGetFragDataIndexEXT work correctly with
567
// GLSL array output variables. The output variable can be bound by
568
// referring to the variable name with or without the first element array
569
// accessor. The getters can query location of the individual elements in
570
// the array. The test does not actually use the base test drawing,
571
// since the drivers at the time of writing do not support multiple
572
// buffers and dual source blending.
573
TEST_P(EXTBlendFuncExtendedDrawTestES3, ES3GettersArray)
574
{
575
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
576
577
// TODO(zmo): Figure out why this fails on AMD. crbug.com/585132.
578
// Also fails on the Intel Mesa driver, see
579
// https://bugs.freedesktop.org/show_bug.cgi?id=96765
580
ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD());
581
ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
582
583
const GLint kTestArraySize = 2;
584
const GLint kFragData0Location = 2;
585
const GLint kFragData1Location = 1;
586
const GLint kUnusedLocation = 5;
587
588
// The test binds kTestArraySize -sized array to location 1 for test purposes.
589
// The GL_MAX_DRAW_BUFFERS must be > kTestArraySize, since an
590
// array will be bound to continuous locations, starting from the first
591
// location.
592
GLint maxDrawBuffers = 0;
593
glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
594
EXPECT_LT(kTestArraySize, maxDrawBuffers);
595
596
constexpr char kFragColorShader[] = R"(#version 300 es
597
#extension GL_EXT_blend_func_extended : require
598
precision mediump float;
599
uniform vec4 src;
600
uniform vec4 src1;
601
out vec4 FragData[2];
602
void main() {
603
FragData[0] = src;
604
FragData[1] = src1;
605
})";
606
607
struct testCase
608
{
609
std::string unusedLocationName;
610
std::string fragData0LocationName;
611
std::string fragData1LocationName;
612
};
613
614
testCase testCases[4]{{"FragData[0]", "FragData", "FragData[1]"},
615
{"FragData", "FragData[0]", "FragData[1]"},
616
{"FragData[0]", "FragData", "FragData[1]"},
617
{"FragData", "FragData[0]", "FragData[1]"}};
618
619
for (const testCase &test : testCases)
620
{
621
mProgram =
622
CompileProgram(essl3_shaders::vs::Simple(), kFragColorShader, [&](GLuint program) {
623
glBindFragDataLocationEXT(program, kUnusedLocation,
624
test.unusedLocationName.c_str());
625
glBindFragDataLocationEXT(program, kFragData0Location,
626
test.fragData0LocationName.c_str());
627
glBindFragDataLocationEXT(program, kFragData1Location,
628
test.fragData1LocationName.c_str());
629
});
630
631
EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
632
LinkProgram();
633
EXPECT_EQ(kFragData0Location, glGetFragDataLocation(mProgram, "FragData"));
634
EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "FragData"));
635
EXPECT_EQ(kFragData0Location, glGetFragDataLocation(mProgram, "FragData[0]"));
636
EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "FragData[0]"));
637
EXPECT_EQ(kFragData1Location, glGetFragDataLocation(mProgram, "FragData[1]"));
638
EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "FragData[1]"));
639
// Index bigger than the GLSL variable array length does not find anything.
640
EXPECT_EQ(-1, glGetFragDataLocation(mProgram, "FragData[3]"));
641
}
642
}
643
644
// Ported from TranslatorVariants/EXTBlendFuncExtendedES3DrawTest
645
TEST_P(EXTBlendFuncExtendedDrawTestES3, ESSL3BindSimpleVarAsArrayNoBind)
646
{
647
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
648
649
constexpr char kFragDataShader[] = R"(#version 300 es
650
#extension GL_EXT_blend_func_extended : require
651
precision mediump float;
652
uniform vec4 src;
653
uniform vec4 src1;
654
out vec4 FragData;
655
out vec4 SecondaryFragData;
656
void main() {
657
FragData = src;
658
SecondaryFragData = src1;
659
})";
660
661
mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFragDataShader, [](GLuint program) {
662
glBindFragDataLocationEXT(program, 0, "FragData[0]");
663
glBindFragDataLocationIndexedEXT(program, 0, 1, "SecondaryFragData[0]");
664
});
665
666
LinkProgram();
667
668
EXPECT_EQ(-1, glGetFragDataLocation(mProgram, "FragData[0]"));
669
EXPECT_EQ(0, glGetFragDataLocation(mProgram, "FragData"));
670
EXPECT_EQ(1, glGetFragDataLocation(mProgram, "SecondaryFragData"));
671
// Did not bind index.
672
EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "SecondaryFragData"));
673
674
glBindFragDataLocationEXT(mProgram, 0, "FragData");
675
glBindFragDataLocationIndexedEXT(mProgram, 0, 1, "SecondaryFragData");
676
LinkProgram();
677
}
678
679
// Test an ESSL 3.00 program with a link-time fragment output location conflict.
680
TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputLocationConflict)
681
{
682
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
683
684
constexpr char kFS[] = R"(#version 300 es
685
#extension GL_EXT_blend_func_extended : require
686
precision mediump float;
687
uniform vec4 src0;
688
uniform vec4 src1;
689
out vec4 out0;
690
out vec4 out1;
691
void main() {
692
out0 = src0;
693
out1 = src1;
694
})";
695
696
GLuint vs = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
697
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
698
ASSERT_NE(0u, vs);
699
ASSERT_NE(0u, fs);
700
701
GLuint program = glCreateProgram();
702
glAttachShader(program, vs);
703
glDeleteShader(vs);
704
glAttachShader(program, fs);
705
glDeleteShader(fs);
706
707
glBindFragDataLocationIndexedEXT(program, 0, 0, "out0");
708
glBindFragDataLocationIndexedEXT(program, 0, 0, "out1");
709
710
// The program should fail to link.
711
glLinkProgram(program);
712
GLint linkStatus;
713
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
714
EXPECT_EQ(0, linkStatus);
715
716
glDeleteProgram(program);
717
}
718
719
// Test an ESSL 3.00 program with some bindings set for nonexistent variables. These should not
720
// create link-time conflicts.
721
TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputLocationForNonexistentOutput)
722
{
723
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
724
725
constexpr char kFS[] = R"(#version 300 es
726
#extension GL_EXT_blend_func_extended : require
727
precision mediump float;
728
uniform vec4 src0;
729
out vec4 out0;
730
void main() {
731
out0 = src0;
732
})";
733
734
GLuint vs = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
735
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
736
ASSERT_NE(0u, vs);
737
ASSERT_NE(0u, fs);
738
739
GLuint program = glCreateProgram();
740
glAttachShader(program, vs);
741
glDeleteShader(vs);
742
glAttachShader(program, fs);
743
glDeleteShader(fs);
744
745
glBindFragDataLocationIndexedEXT(program, 0, 0, "out0");
746
glBindFragDataLocationIndexedEXT(program, 0, 0, "out1");
747
glBindFragDataLocationIndexedEXT(program, 0, 0, "out2[0]");
748
749
// The program should link successfully - conflicting location for nonexistent variables out1 or
750
// out2 should not be an issue.
751
glLinkProgram(program);
752
GLint linkStatus;
753
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
754
EXPECT_NE(0, linkStatus);
755
756
glDeleteProgram(program);
757
}
758
759
// Test mixing shader-assigned and automatic output locations.
760
TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputLocationsPartiallyAutomatic)
761
{
762
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
763
764
GLint maxDrawBuffers;
765
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
766
ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4);
767
768
constexpr char kFS[] = R"(#version 300 es
769
#extension GL_EXT_blend_func_extended : require
770
precision mediump float;
771
uniform vec4 src0;
772
uniform vec4 src1;
773
uniform vec4 src2;
774
uniform vec4 src3;
775
layout(location=0) out vec4 out0;
776
layout(location=3) out vec4 out3;
777
out vec4 out12[2];
778
void main() {
779
out0 = src0;
780
out12[0] = src1;
781
out12[1] = src2;
782
out3 = src3;
783
})";
784
785
GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
786
ASSERT_NE(0u, program);
787
788
GLint location = glGetFragDataLocation(program, "out0");
789
EXPECT_EQ(0, location);
790
location = glGetFragDataLocation(program, "out12");
791
EXPECT_EQ(1, location);
792
location = glGetFragDataLocation(program, "out3");
793
EXPECT_EQ(3, location);
794
795
glDeleteProgram(program);
796
}
797
798
// Test a fragment output array that doesn't fit because contiguous locations are not available.
799
TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputArrayDoesntFit)
800
{
801
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
802
803
GLint maxDrawBuffers;
804
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
805
ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4);
806
807
std::stringstream fragShader;
808
fragShader << R"(#version 300 es
809
#extension GL_EXT_blend_func_extended : require
810
precision mediump float;
811
layout(location=2) out vec4 out0;
812
out vec4 outArray[)"
813
<< (maxDrawBuffers - 1) << R"(];
814
void main() {
815
out0 = vec4(1.0);
816
outArray[0] = vec4(1.0);
817
})";
818
819
GLuint vs = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
820
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragShader.str().c_str());
821
ASSERT_NE(0u, vs);
822
ASSERT_NE(0u, fs);
823
824
GLuint program = glCreateProgram();
825
glAttachShader(program, vs);
826
glDeleteShader(vs);
827
glAttachShader(program, fs);
828
glDeleteShader(fs);
829
830
// The program should not link - there's no way to fit "outArray" into available output
831
// locations.
832
glLinkProgram(program);
833
GLint linkStatus;
834
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
835
EXPECT_EQ(0, linkStatus);
836
837
glDeleteProgram(program);
838
}
839
840
// Use a program pipeline with EXT_blend_func_extended
841
TEST_P(EXTBlendFuncExtendedDrawTestES31, UseProgramPipeline)
842
{
843
// Only the Vulkan backend supports PPO
844
ANGLE_SKIP_TEST_IF(!IsVulkan());
845
846
// Create two separable program objects from a
847
// single source string respectively (vertSrc and fragSrc)
848
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
849
850
const char *kFragColorShader = R"(#version 300 es
851
#extension GL_EXT_blend_func_extended : require
852
precision mediump float;
853
uniform vec4 src0;
854
uniform vec4 src1;
855
layout(location = 0, index = 1) out vec4 outSrc1;
856
layout(location = 0, index = 0) out vec4 outSrc0;
857
void main() {
858
outSrc0 = src0;
859
outSrc1 = src1;
860
})";
861
862
setupProgramPipeline(essl3_shaders::vs::Simple(), kFragColorShader);
863
864
checkOutputIndexQuery("outSrc0", 0);
865
checkOutputIndexQuery("outSrc1", 1);
866
867
ASSERT_EQ(mProgram, 0u);
868
drawTest();
869
870
ASSERT_GL_NO_ERROR();
871
}
872
873
// Use program pipeline where the fragment program is changed
874
TEST_P(EXTBlendFuncExtendedDrawTestES31, UseTwoProgramStages)
875
{
876
// Only the Vulkan backend supports PPO
877
ANGLE_SKIP_TEST_IF(!IsVulkan());
878
879
// Create two separable program objects from a
880
// single source string respectively (vertSrc and fragSrc)
881
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
882
883
const char *kFragColorShaderFlipped = R"(#version 300 es
884
#extension GL_EXT_blend_func_extended : require
885
precision mediump float;
886
uniform vec4 src0;
887
uniform vec4 src1;
888
layout(location = 0, index = 0) out vec4 outSrc1;
889
layout(location = 0, index = 1) out vec4 outSrc0;
890
void main() {
891
outSrc0 = src0;
892
outSrc1 = src1;
893
})";
894
895
const char *kFragColorShader = R"(#version 300 es
896
#extension GL_EXT_blend_func_extended : require
897
precision mediump float;
898
uniform vec4 src0;
899
uniform vec4 src1;
900
layout(location = 0, index = 1) out vec4 outSrc1;
901
layout(location = 0, index = 0) out vec4 outSrc0;
902
void main() {
903
outSrc0 = src0;
904
outSrc1 = src1;
905
})";
906
907
setupProgramPipeline(essl3_shaders::vs::Simple(), kFragColorShaderFlipped);
908
909
// Check index values frag shader with the "flipped" index values
910
checkOutputIndexQuery("outSrc0", 1);
911
checkOutputIndexQuery("outSrc1", 0);
912
913
GLuint previousProgram = mFragProgram;
914
mFragProgram = createShaderProgram(GL_FRAGMENT_SHADER, kFragColorShader);
915
ASSERT_NE(mFragProgram, 0u);
916
917
// Change the Fragment program of the pipeline
918
glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProgram);
919
EXPECT_GL_NO_ERROR();
920
921
checkOutputIndexQuery("outSrc0", 0);
922
checkOutputIndexQuery("outSrc1", 1);
923
924
ASSERT_EQ(mProgram, 0u);
925
drawTest();
926
927
if (previousProgram)
928
{
929
glDeleteProgram(previousProgram);
930
}
931
ASSERT_GL_NO_ERROR();
932
}
933
934
ANGLE_INSTANTIATE_TEST_ES2(EXTBlendFuncExtendedTest);
935
936
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EXTBlendFuncExtendedTestES3);
937
ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(EXTBlendFuncExtendedTestES3);
938
939
ANGLE_INSTANTIATE_TEST_ES2(EXTBlendFuncExtendedDrawTest);
940
941
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EXTBlendFuncExtendedDrawTestES3);
942
ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(EXTBlendFuncExtendedDrawTestES3);
943
944
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EXTBlendFuncExtendedDrawTestES31);
945
ANGLE_INSTANTIATE_TEST_ES31(EXTBlendFuncExtendedDrawTestES31);
946
947