PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/ThirdParty/ANGLE/src/tests/gl_tests/BlendFuncExtendedTest.cpp

http://github.com/WebKit/webkit
C++ | 715 lines | 535 code | 121 blank | 59 comment | 22 complexity | bf4bf196b7bff0a89dd80d546b1c8471 MD5 | raw file
Possible License(s): MPL-2.0, 0BSD, MPL-2.0-no-copyleft-exception, BSD-3-Clause, AGPL-1.0, MIT, GPL-2.0, GPL-3.0, Unlicense, BSD-2-Clause, LGPL-2.1, Apache-2.0
  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. #include "test_utils/ANGLETest.h"
  9. #include "util/shader_utils.h"
  10. #include <algorithm>
  11. #include <cmath>
  12. #include <fstream>
  13. using namespace angle;
  14. namespace
  15. {
  16. // Partial implementation of weight function for GLES 2 blend equation that
  17. // is dual-source aware.
  18. template <int factor, int index>
  19. float Weight(const float /*dst*/[4], const float src[4], const float src1[4])
  20. {
  21. if (factor == GL_SRC_COLOR)
  22. return src[index];
  23. if (factor == GL_SRC_ALPHA)
  24. return src[3];
  25. if (factor == GL_SRC1_COLOR_EXT)
  26. return src1[index];
  27. if (factor == GL_SRC1_ALPHA_EXT)
  28. return src1[3];
  29. if (factor == GL_ONE_MINUS_SRC1_COLOR_EXT)
  30. return 1.0f - src1[index];
  31. if (factor == GL_ONE_MINUS_SRC1_ALPHA_EXT)
  32. return 1.0f - src1[3];
  33. return 0.0f;
  34. }
  35. GLubyte ScaleChannel(float weight)
  36. {
  37. return static_cast<GLubyte>(std::floor(std::max(0.0f, std::min(1.0f, weight)) * 255.0f));
  38. }
  39. // Implementation of GLES 2 blend equation that is dual-source aware.
  40. template <int RGBs, int RGBd, int As, int Ad>
  41. void BlendEquationFuncAdd(const float dst[4],
  42. const float src[4],
  43. const float src1[4],
  44. angle::GLColor *result)
  45. {
  46. float r[4];
  47. r[0] = src[0] * Weight<RGBs, 0>(dst, src, src1) + dst[0] * Weight<RGBd, 0>(dst, src, src1);
  48. r[1] = src[1] * Weight<RGBs, 1>(dst, src, src1) + dst[1] * Weight<RGBd, 1>(dst, src, src1);
  49. r[2] = src[2] * Weight<RGBs, 2>(dst, src, src1) + dst[2] * Weight<RGBd, 2>(dst, src, src1);
  50. r[3] = src[3] * Weight<As, 3>(dst, src, src1) + dst[3] * Weight<Ad, 3>(dst, src, src1);
  51. result->R = ScaleChannel(r[0]);
  52. result->G = ScaleChannel(r[1]);
  53. result->B = ScaleChannel(r[2]);
  54. result->A = ScaleChannel(r[3]);
  55. }
  56. void CheckPixels(GLint x,
  57. GLint y,
  58. GLsizei width,
  59. GLsizei height,
  60. GLint tolerance,
  61. const angle::GLColor &color)
  62. {
  63. for (GLint yy = 0; yy < height; ++yy)
  64. {
  65. for (GLint xx = 0; xx < width; ++xx)
  66. {
  67. const auto px = x + xx;
  68. const auto py = y + yy;
  69. EXPECT_PIXEL_COLOR_NEAR(px, py, color, 1);
  70. }
  71. }
  72. }
  73. const GLuint kWidth = 100;
  74. const GLuint kHeight = 100;
  75. class EXTBlendFuncExtendedTest : public ANGLETest
  76. {};
  77. class EXTBlendFuncExtendedTestES3 : public ANGLETest
  78. {};
  79. class EXTBlendFuncExtendedDrawTest : public ANGLETest
  80. {
  81. protected:
  82. EXTBlendFuncExtendedDrawTest() : mProgram(0)
  83. {
  84. setWindowWidth(kWidth);
  85. setWindowHeight(kHeight);
  86. setConfigRedBits(8);
  87. setConfigGreenBits(8);
  88. setConfigBlueBits(8);
  89. setConfigAlphaBits(8);
  90. }
  91. void testSetUp() override
  92. {
  93. glGenBuffers(1, &mVBO);
  94. glBindBuffer(GL_ARRAY_BUFFER, mVBO);
  95. static const float vertices[] = {
  96. 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
  97. };
  98. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  99. ASSERT_GL_NO_ERROR();
  100. }
  101. void testTearDown() override
  102. {
  103. glDeleteBuffers(1, &mVBO);
  104. if (mProgram)
  105. {
  106. glDeleteProgram(mProgram);
  107. }
  108. ASSERT_GL_NO_ERROR();
  109. }
  110. void makeProgram(const char *vertSource, const char *fragSource)
  111. {
  112. mProgram = CompileProgram(vertSource, fragSource);
  113. ASSERT_NE(0u, mProgram);
  114. }
  115. void drawTest()
  116. {
  117. glUseProgram(mProgram);
  118. GLint position = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
  119. GLint src0 = glGetUniformLocation(mProgram, "src0");
  120. GLint src1 = glGetUniformLocation(mProgram, "src1");
  121. ASSERT_GL_NO_ERROR();
  122. glBindBuffer(GL_ARRAY_BUFFER, mVBO);
  123. glEnableVertexAttribArray(position);
  124. glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
  125. ASSERT_GL_NO_ERROR();
  126. static const float kDst[4] = {0.5f, 0.5f, 0.5f, 0.5f};
  127. static const float kSrc0[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  128. static const float kSrc1[4] = {0.3f, 0.6f, 0.9f, 0.7f};
  129. glUniform4f(src0, kSrc0[0], kSrc0[1], kSrc0[2], kSrc0[3]);
  130. glUniform4f(src1, kSrc1[0], kSrc1[1], kSrc1[2], kSrc1[3]);
  131. ASSERT_GL_NO_ERROR();
  132. glEnable(GL_BLEND);
  133. glBlendEquation(GL_FUNC_ADD);
  134. glViewport(0, 0, kWidth, kHeight);
  135. glClearColor(kDst[0], kDst[1], kDst[2], kDst[3]);
  136. ASSERT_GL_NO_ERROR();
  137. {
  138. glBlendFuncSeparate(GL_SRC1_COLOR_EXT, GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_COLOR_EXT,
  139. GL_ONE_MINUS_SRC1_ALPHA_EXT);
  140. glClear(GL_COLOR_BUFFER_BIT);
  141. glDrawArrays(GL_TRIANGLES, 0, 6);
  142. ASSERT_GL_NO_ERROR();
  143. // verify
  144. angle::GLColor color;
  145. BlendEquationFuncAdd<GL_SRC1_COLOR_EXT, GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_COLOR_EXT,
  146. GL_ONE_MINUS_SRC1_ALPHA_EXT>(kDst, kSrc0, kSrc1, &color);
  147. CheckPixels(kWidth / 4, (3 * kHeight) / 4, 1, 1, 1, color);
  148. CheckPixels(kWidth - 1, 0, 1, 1, 1, color);
  149. }
  150. {
  151. glBlendFuncSeparate(GL_ONE_MINUS_SRC1_COLOR_EXT, GL_ONE_MINUS_SRC_ALPHA,
  152. GL_ONE_MINUS_SRC_COLOR, GL_SRC1_ALPHA_EXT);
  153. glClear(GL_COLOR_BUFFER_BIT);
  154. glDrawArrays(GL_TRIANGLES, 0, 6);
  155. ASSERT_GL_NO_ERROR();
  156. // verify
  157. angle::GLColor color;
  158. BlendEquationFuncAdd<GL_ONE_MINUS_SRC1_COLOR_EXT, GL_ONE_MINUS_SRC_ALPHA,
  159. GL_ONE_MINUS_SRC_COLOR, GL_SRC1_ALPHA_EXT>(kDst, kSrc0, kSrc1,
  160. &color);
  161. CheckPixels(kWidth / 4, (3 * kHeight) / 4, 1, 1, 1, color);
  162. CheckPixels(kWidth - 1, 0, 1, 1, 1, color);
  163. }
  164. }
  165. GLuint mVBO;
  166. GLuint mProgram;
  167. };
  168. class EXTBlendFuncExtendedDrawTestES3 : public EXTBlendFuncExtendedDrawTest
  169. {
  170. protected:
  171. EXTBlendFuncExtendedDrawTestES3() : EXTBlendFuncExtendedDrawTest(), mIsES31OrNewer(false) {}
  172. void testSetUp() override
  173. {
  174. EXTBlendFuncExtendedDrawTest::testSetUp();
  175. if (getClientMajorVersion() > 3 ||
  176. (getClientMajorVersion() == 3 && getClientMinorVersion() >= 1))
  177. {
  178. mIsES31OrNewer = true;
  179. }
  180. }
  181. void checkOutputIndexQuery(const char *name, GLint expectedIndex)
  182. {
  183. GLint index = glGetFragDataIndexEXT(mProgram, name);
  184. EXPECT_EQ(expectedIndex, index);
  185. if (mIsES31OrNewer)
  186. {
  187. index = glGetProgramResourceLocationIndexEXT(mProgram, GL_PROGRAM_OUTPUT, name);
  188. EXPECT_EQ(expectedIndex, index);
  189. }
  190. else
  191. {
  192. glGetProgramResourceLocationIndexEXT(mProgram, GL_PROGRAM_OUTPUT, name);
  193. EXPECT_GL_ERROR(GL_INVALID_OPERATION);
  194. }
  195. }
  196. void LinkProgram()
  197. {
  198. glLinkProgram(mProgram);
  199. GLint linked = 0;
  200. glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
  201. EXPECT_NE(0, linked);
  202. glUseProgram(mProgram);
  203. return;
  204. }
  205. private:
  206. bool mIsES31OrNewer;
  207. };
  208. } // namespace
  209. // Test EXT_blend_func_extended related gets.
  210. TEST_P(EXTBlendFuncExtendedTest, TestMaxDualSourceDrawBuffers)
  211. {
  212. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  213. GLint maxDualSourceDrawBuffers = 0;
  214. glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers);
  215. EXPECT_GT(maxDualSourceDrawBuffers, 0);
  216. ASSERT_GL_NO_ERROR();
  217. }
  218. // Test a shader with EXT_blend_func_extended and gl_SecondaryFragColorEXT.
  219. // Outputs to primary color buffer using primary and secondary colors.
  220. TEST_P(EXTBlendFuncExtendedDrawTest, FragColor)
  221. {
  222. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  223. const char *kFragColorShader =
  224. "#extension GL_EXT_blend_func_extended : require\n"
  225. "precision mediump float;\n"
  226. "uniform vec4 src0;\n"
  227. "uniform vec4 src1;\n"
  228. "void main() {\n"
  229. " gl_FragColor = src0;\n"
  230. " gl_SecondaryFragColorEXT = src1;\n"
  231. "}\n";
  232. makeProgram(essl1_shaders::vs::Simple(), kFragColorShader);
  233. drawTest();
  234. }
  235. // Test a shader with EXT_blend_func_extended and gl_FragData.
  236. // Outputs to a color buffer using primary and secondary frag data.
  237. TEST_P(EXTBlendFuncExtendedDrawTest, FragData)
  238. {
  239. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  240. const char *kFragColorShader =
  241. "#extension GL_EXT_blend_func_extended : require\n"
  242. "precision mediump float;\n"
  243. "uniform vec4 src0;\n"
  244. "uniform vec4 src1;\n"
  245. "void main() {\n"
  246. " gl_FragData[0] = src0;\n"
  247. " gl_SecondaryFragDataEXT[0] = src1;\n"
  248. "}\n";
  249. makeProgram(essl1_shaders::vs::Simple(), kFragColorShader);
  250. drawTest();
  251. }
  252. // Test an ESSL 3.00 shader that uses two fragment outputs with locations specified in the shader.
  253. TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentOutputLocationsInShader)
  254. {
  255. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  256. const char *kFragColorShader = R"(#version 300 es
  257. #extension GL_EXT_blend_func_extended : require
  258. precision mediump float;
  259. uniform vec4 src0;
  260. uniform vec4 src1;
  261. layout(location = 0, index = 1) out vec4 outSrc1;
  262. layout(location = 0, index = 0) out vec4 outSrc0;
  263. void main() {
  264. outSrc0 = src0;
  265. outSrc1 = src1;
  266. })";
  267. makeProgram(essl3_shaders::vs::Simple(), kFragColorShader);
  268. checkOutputIndexQuery("outSrc0", 0);
  269. checkOutputIndexQuery("outSrc1", 1);
  270. drawTest();
  271. }
  272. // Test an ESSL 3.00 shader that uses two fragment outputs with locations specified through the API.
  273. TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentOutputLocationAPI)
  274. {
  275. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  276. constexpr char kFS[] = R"(#version 300 es
  277. #extension GL_EXT_blend_func_extended : require
  278. precision mediump float;
  279. uniform vec4 src0;
  280. uniform vec4 src1;
  281. out vec4 outSrc1;
  282. out vec4 outSrc0;
  283. void main() {
  284. outSrc0 = src0;
  285. outSrc1 = src1;
  286. })";
  287. mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFS, [](GLuint program) {
  288. glBindFragDataLocationIndexedEXT(program, 0, 0, "outSrc0");
  289. glBindFragDataLocationIndexedEXT(program, 0, 1, "outSrc1");
  290. });
  291. ASSERT_NE(0u, mProgram);
  292. checkOutputIndexQuery("outSrc0", 0);
  293. checkOutputIndexQuery("outSrc1", 1);
  294. drawTest();
  295. }
  296. // Test an ESSL 3.00 shader that uses two fragment outputs, with location for one specified through
  297. // the API and location for another being set automatically.
  298. TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentOutputLocationsAPIAndAutomatic)
  299. {
  300. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  301. constexpr char kFS[] = R"(#version 300 es
  302. #extension GL_EXT_blend_func_extended : require
  303. precision mediump float;
  304. uniform vec4 src0;
  305. uniform vec4 src1;
  306. out vec4 outSrc1;
  307. out vec4 outSrc0;
  308. void main() {
  309. outSrc0 = src0;
  310. outSrc1 = src1;
  311. })";
  312. mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFS, [](GLuint program) {
  313. glBindFragDataLocationIndexedEXT(program, 0, 1, "outSrc1");
  314. });
  315. ASSERT_NE(0u, mProgram);
  316. checkOutputIndexQuery("outSrc0", 0);
  317. checkOutputIndexQuery("outSrc1", 1);
  318. drawTest();
  319. }
  320. // Test an ESSL 3.00 shader that uses two array fragment outputs with locations specified through
  321. // the API.
  322. TEST_P(EXTBlendFuncExtendedDrawTestES3, FragmentArrayOutputLocationsAPI)
  323. {
  324. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  325. // TODO: Investigate this mac-only failure. http://angleproject.com/1085
  326. ANGLE_SKIP_TEST_IF(IsOSX());
  327. constexpr char kFS[] = R"(#version 300 es
  328. #extension GL_EXT_blend_func_extended : require
  329. precision mediump float;
  330. uniform vec4 src0;
  331. uniform vec4 src1;
  332. out vec4 outSrc1[1];
  333. out vec4 outSrc0[1];
  334. void main() {
  335. outSrc0[0] = src0;
  336. outSrc1[0] = src1;
  337. })";
  338. mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFS, [](GLuint program) {
  339. // Specs aren't very clear on what kind of name should be used when binding location for
  340. // array variables. We only allow names that do include the "[0]" suffix.
  341. glBindFragDataLocationIndexedEXT(program, 0, 0, "outSrc0[0]");
  342. glBindFragDataLocationIndexedEXT(program, 0, 1, "outSrc1[0]");
  343. });
  344. ASSERT_NE(0u, mProgram);
  345. // The extension spec is not very clear on what name can be used for the queries for array
  346. // variables. We're checking that the queries work in the same way as specified in OpenGL 4.4
  347. // page 107.
  348. checkOutputIndexQuery("outSrc0[0]", 0);
  349. checkOutputIndexQuery("outSrc1[0]", 1);
  350. checkOutputIndexQuery("outSrc0", 0);
  351. checkOutputIndexQuery("outSrc1", 1);
  352. // These queries use an out of range array index so they should return -1.
  353. checkOutputIndexQuery("outSrc0[1]", -1);
  354. checkOutputIndexQuery("outSrc1[1]", -1);
  355. drawTest();
  356. }
  357. // Ported from TranslatorVariants/EXTBlendFuncExtendedES3DrawTest
  358. // Test that tests glBindFragDataLocationEXT, glBindFragDataLocationIndexedEXT,
  359. // glGetFragDataLocation, glGetFragDataIndexEXT work correctly with
  360. // GLSL array output variables. The output variable can be bound by
  361. // referring to the variable name with or without the first element array
  362. // accessor. The getters can query location of the individual elements in
  363. // the array. The test does not actually use the base test drawing,
  364. // since the drivers at the time of writing do not support multiple
  365. // buffers and dual source blending.
  366. TEST_P(EXTBlendFuncExtendedDrawTestES3, ES3GettersArray)
  367. {
  368. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  369. // TODO(zmo): Figure out why this fails on AMD. crbug.com/585132.
  370. // Also fails on the Intel Mesa driver, see
  371. // https://bugs.freedesktop.org/show_bug.cgi?id=96765
  372. ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD());
  373. ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
  374. const GLint kTestArraySize = 2;
  375. const GLint kFragData0Location = 2;
  376. const GLint kFragData1Location = 1;
  377. const GLint kUnusedLocation = 5;
  378. // The test binds kTestArraySize -sized array to location 1 for test purposes.
  379. // The GL_MAX_DRAW_BUFFERS must be > kTestArraySize, since an
  380. // array will be bound to continuous locations, starting from the first
  381. // location.
  382. GLint maxDrawBuffers = 0;
  383. glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
  384. EXPECT_LT(kTestArraySize, maxDrawBuffers);
  385. constexpr char kFragColorShader[] = R"(#version 300 es
  386. #extension GL_EXT_blend_func_extended : require
  387. precision mediump float;
  388. uniform vec4 src;
  389. uniform vec4 src1;
  390. out vec4 FragData[2];
  391. void main() {
  392. FragData[0] = src;
  393. FragData[1] = src1;
  394. })";
  395. struct testCase
  396. {
  397. std::string unusedLocationName;
  398. std::string fragData0LocationName;
  399. std::string fragData1LocationName;
  400. };
  401. testCase testCases[4]{{"FragData[0]", "FragData", "FragData[1]"},
  402. {"FragData", "FragData[0]", "FragData[1]"},
  403. {"FragData[0]", "FragData", "FragData[1]"},
  404. {"FragData", "FragData[0]", "FragData[1]"}};
  405. for (const testCase &test : testCases)
  406. {
  407. mProgram =
  408. CompileProgram(essl3_shaders::vs::Simple(), kFragColorShader, [&](GLuint program) {
  409. glBindFragDataLocationEXT(program, kUnusedLocation,
  410. test.unusedLocationName.c_str());
  411. glBindFragDataLocationEXT(program, kFragData0Location,
  412. test.fragData0LocationName.c_str());
  413. glBindFragDataLocationEXT(program, kFragData1Location,
  414. test.fragData1LocationName.c_str());
  415. });
  416. EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
  417. LinkProgram();
  418. EXPECT_EQ(kFragData0Location, glGetFragDataLocation(mProgram, "FragData"));
  419. EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "FragData"));
  420. EXPECT_EQ(kFragData0Location, glGetFragDataLocation(mProgram, "FragData[0]"));
  421. EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "FragData[0]"));
  422. EXPECT_EQ(kFragData1Location, glGetFragDataLocation(mProgram, "FragData[1]"));
  423. EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "FragData[1]"));
  424. // Index bigger than the GLSL variable array length does not find anything.
  425. EXPECT_EQ(-1, glGetFragDataLocation(mProgram, "FragData[3]"));
  426. }
  427. }
  428. // Ported from TranslatorVariants/EXTBlendFuncExtendedES3DrawTest
  429. TEST_P(EXTBlendFuncExtendedDrawTestES3, ESSL3BindSimpleVarAsArrayNoBind)
  430. {
  431. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  432. constexpr char kFragDataShader[] = R"(#version 300 es
  433. #extension GL_EXT_blend_func_extended : require
  434. precision mediump float;
  435. uniform vec4 src;
  436. uniform vec4 src1;
  437. out vec4 FragData;
  438. out vec4 SecondaryFragData;
  439. void main() {
  440. FragData = src;
  441. SecondaryFragData = src1;
  442. })";
  443. mProgram = CompileProgram(essl3_shaders::vs::Simple(), kFragDataShader, [](GLuint program) {
  444. glBindFragDataLocationEXT(program, 0, "FragData[0]");
  445. glBindFragDataLocationIndexedEXT(program, 0, 1, "SecondaryFragData[0]");
  446. });
  447. LinkProgram();
  448. EXPECT_EQ(-1, glGetFragDataLocation(mProgram, "FragData[0]"));
  449. EXPECT_EQ(0, glGetFragDataLocation(mProgram, "FragData"));
  450. EXPECT_EQ(1, glGetFragDataLocation(mProgram, "SecondaryFragData"));
  451. // Did not bind index.
  452. EXPECT_EQ(0, glGetFragDataIndexEXT(mProgram, "SecondaryFragData"));
  453. glBindFragDataLocationEXT(mProgram, 0, "FragData");
  454. glBindFragDataLocationIndexedEXT(mProgram, 0, 1, "SecondaryFragData");
  455. LinkProgram();
  456. }
  457. // Test an ESSL 3.00 program with a link-time fragment output location conflict.
  458. TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputLocationConflict)
  459. {
  460. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  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 out0;
  467. out vec4 out1;
  468. void main() {
  469. out0 = src0;
  470. out1 = src1;
  471. })";
  472. GLuint vs = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
  473. GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
  474. ASSERT_NE(0u, vs);
  475. ASSERT_NE(0u, fs);
  476. GLuint program = glCreateProgram();
  477. glAttachShader(program, vs);
  478. glDeleteShader(vs);
  479. glAttachShader(program, fs);
  480. glDeleteShader(fs);
  481. glBindFragDataLocationIndexedEXT(program, 0, 0, "out0");
  482. glBindFragDataLocationIndexedEXT(program, 0, 0, "out1");
  483. // The program should fail to link.
  484. glLinkProgram(program);
  485. GLint linkStatus;
  486. glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
  487. EXPECT_EQ(0, linkStatus);
  488. glDeleteProgram(program);
  489. }
  490. // Test an ESSL 3.00 program with some bindings set for nonexistent variables. These should not
  491. // create link-time conflicts.
  492. TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputLocationForNonexistentOutput)
  493. {
  494. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  495. constexpr char kFS[] = R"(#version 300 es
  496. #extension GL_EXT_blend_func_extended : require
  497. precision mediump float;
  498. uniform vec4 src0;
  499. out vec4 out0;
  500. void main() {
  501. out0 = src0;
  502. })";
  503. GLuint vs = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
  504. GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
  505. ASSERT_NE(0u, vs);
  506. ASSERT_NE(0u, fs);
  507. GLuint program = glCreateProgram();
  508. glAttachShader(program, vs);
  509. glDeleteShader(vs);
  510. glAttachShader(program, fs);
  511. glDeleteShader(fs);
  512. glBindFragDataLocationIndexedEXT(program, 0, 0, "out0");
  513. glBindFragDataLocationIndexedEXT(program, 0, 0, "out1");
  514. glBindFragDataLocationIndexedEXT(program, 0, 0, "out2[0]");
  515. // The program should link successfully - conflicting location for nonexistent variables out1 or
  516. // out2 should not be an issue.
  517. glLinkProgram(program);
  518. GLint linkStatus;
  519. glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
  520. EXPECT_NE(0, linkStatus);
  521. glDeleteProgram(program);
  522. }
  523. // Test mixing shader-assigned and automatic output locations.
  524. TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputLocationsPartiallyAutomatic)
  525. {
  526. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  527. GLint maxDrawBuffers;
  528. glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
  529. ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4);
  530. constexpr char kFS[] = R"(#version 300 es
  531. #extension GL_EXT_blend_func_extended : require
  532. precision mediump float;
  533. uniform vec4 src0;
  534. uniform vec4 src1;
  535. uniform vec4 src2;
  536. uniform vec4 src3;
  537. layout(location=0) out vec4 out0;
  538. layout(location=3) out vec4 out3;
  539. out vec4 out12[2];
  540. void main() {
  541. out0 = src0;
  542. out12[0] = src1;
  543. out12[1] = src2;
  544. out3 = src3;
  545. })";
  546. GLuint program = CompileProgram(essl3_shaders::vs::Simple(), kFS);
  547. ASSERT_NE(0u, program);
  548. GLint location = glGetFragDataLocation(program, "out0");
  549. EXPECT_EQ(0, location);
  550. location = glGetFragDataLocation(program, "out12");
  551. EXPECT_EQ(1, location);
  552. location = glGetFragDataLocation(program, "out3");
  553. EXPECT_EQ(3, location);
  554. glDeleteProgram(program);
  555. }
  556. // Test a fragment output array that doesn't fit because contiguous locations are not available.
  557. TEST_P(EXTBlendFuncExtendedTestES3, FragmentOutputArrayDoesntFit)
  558. {
  559. ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
  560. GLint maxDrawBuffers;
  561. glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
  562. ANGLE_SKIP_TEST_IF(maxDrawBuffers < 4);
  563. std::stringstream fragShader;
  564. fragShader << R"(#version 300 es
  565. #extension GL_EXT_blend_func_extended : require
  566. precision mediump float;
  567. layout(location=2) out vec4 out0;
  568. out vec4 outArray[)"
  569. << (maxDrawBuffers - 1) << R"(];
  570. void main() {
  571. out0 = vec4(1.0);
  572. outArray[0] = vec4(1.0);
  573. })";
  574. GLuint vs = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
  575. GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragShader.str().c_str());
  576. ASSERT_NE(0u, vs);
  577. ASSERT_NE(0u, fs);
  578. GLuint program = glCreateProgram();
  579. glAttachShader(program, vs);
  580. glDeleteShader(vs);
  581. glAttachShader(program, fs);
  582. glDeleteShader(fs);
  583. // The program should not link - there's no way to fit "outArray" into available output
  584. // locations.
  585. glLinkProgram(program);
  586. GLint linkStatus;
  587. glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
  588. EXPECT_EQ(0, linkStatus);
  589. glDeleteProgram(program);
  590. }
  591. ANGLE_INSTANTIATE_TEST_ES2(EXTBlendFuncExtendedTest);
  592. ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(EXTBlendFuncExtendedTestES3);
  593. ANGLE_INSTANTIATE_TEST_ES2(EXTBlendFuncExtendedDrawTest);
  594. ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(EXTBlendFuncExtendedDrawTestES3);