Path: blob/main_old/src/tests/gl_tests/DrawElementsTest.cpp
1693 views
//1// Copyright 2015 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// DrawElementsTest:6// Tests for indexed draws.7//89#include "test_utils/ANGLETest.h"10#include "test_utils/gl_raii.h"1112using namespace angle;1314namespace15{1617class DrawElementsTest : public ANGLETest18{19protected:20DrawElementsTest() : mProgram(0u)21{22setWindowWidth(64);23setWindowHeight(64);24setConfigRedBits(8);25setConfigGreenBits(8);26setConfigBlueBits(8);27setConfigAlphaBits(8);28}2930~DrawElementsTest()31{32for (GLuint indexBuffer : mIndexBuffers)33{34if (indexBuffer != 0)35{36glDeleteBuffers(1, &indexBuffer);37}38}3940for (GLuint vertexArray : mVertexArrays)41{42if (vertexArray != 0)43{44glDeleteVertexArrays(1, &vertexArray);45}46}4748for (GLuint vertexBuffer : mVertexBuffers)49{50if (vertexBuffer != 0)51{52glDeleteBuffers(1, &vertexBuffer);53}54}5556if (mProgram != 0u)57{58glDeleteProgram(mProgram);59}60}6162std::vector<GLuint> mIndexBuffers;63std::vector<GLuint> mVertexArrays;64std::vector<GLuint> mVertexBuffers;65GLuint mProgram;66};6768class WebGLDrawElementsTest : public DrawElementsTest69{70public:71WebGLDrawElementsTest() { setWebGLCompatibilityEnabled(true); }72};7374// Test no error is generated when using client-side arrays, indices = nullptr and count = 075TEST_P(DrawElementsTest, ClientSideNullptrArrayZeroCount)76{77constexpr char kVS[] =78"attribute vec3 a_pos;\n"79"void main()\n"80"{\n"81" gl_Position = vec4(a_pos, 1.0);\n"82"}\n";8384ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Blue());8586GLint posLocation = glGetAttribLocation(program.get(), "a_pos");87ASSERT_NE(-1, posLocation);88glUseProgram(program.get());8990const auto &vertices = GetQuadVertices();9192GLBuffer vertexBuffer;93glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());94glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),95GL_STATIC_DRAW);9697glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);98glEnableVertexAttribArray(posLocation);99ASSERT_GL_NO_ERROR();100101// "If drawElements is called with a count greater than zero, and no WebGLBuffer is bound to the102// ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated."103glDrawElements(GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, nullptr);104EXPECT_GL_ERROR(GL_INVALID_OPERATION);105106// count == 0 so it's fine to have no element array buffer bound.107glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_BYTE, nullptr);108ASSERT_GL_NO_ERROR();109}110111// Test a state desync that can occur when using a streaming index buffer in GL in concert with112// deleting the applied index buffer.113TEST_P(DrawElementsTest, DeletingAfterStreamingIndexes)114{115// Init program116constexpr char kVS[] =117"attribute vec2 position;\n"118"attribute vec2 testFlag;\n"119"varying vec2 v_data;\n"120"void main() {\n"121" gl_Position = vec4(position, 0, 1);\n"122" v_data = testFlag;\n"123"}";124125constexpr char kFS[] =126"varying highp vec2 v_data;\n"127"void main() {\n"128" gl_FragColor = vec4(v_data, 0, 1);\n"129"}";130131mProgram = CompileProgram(kVS, kFS);132ASSERT_NE(0u, mProgram);133glUseProgram(mProgram);134135GLint positionLocation = glGetAttribLocation(mProgram, "position");136ASSERT_NE(-1, positionLocation);137138GLint testFlagLocation = glGetAttribLocation(mProgram, "testFlag");139ASSERT_NE(-1, testFlagLocation);140141mIndexBuffers.resize(3u);142glGenBuffers(3, &mIndexBuffers[0]);143144mVertexArrays.resize(2);145glGenVertexArrays(2, &mVertexArrays[0]);146147mVertexBuffers.resize(2);148glGenBuffers(2, &mVertexBuffers[0]);149150std::vector<GLuint> indexData[2];151indexData[0].push_back(0);152indexData[0].push_back(1);153indexData[0].push_back(2);154indexData[0].push_back(2);155indexData[0].push_back(3);156indexData[0].push_back(0);157158indexData[1] = indexData[0];159for (GLuint &item : indexData[1])160{161item += 4u;162}163164std::vector<GLfloat> positionData = {// quad verts165-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,166// Repeat position data167-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f};168169std::vector<GLfloat> testFlagData = {// red1701.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,171// green1720.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};173174glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);175glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexData[0].size(), &indexData[0][0],176GL_STATIC_DRAW);177178glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[2]);179glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexData[0].size(), &indexData[0][0],180GL_STATIC_DRAW);181182glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[1]);183glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexData[1].size(), &indexData[1][0],184GL_STATIC_DRAW);185186// Initialize first vertex array with second index buffer187glBindVertexArray(mVertexArrays[0]);188189glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[1]);190glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[0]);191glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * positionData.size(), &positionData[0],192GL_STATIC_DRAW);193glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);194glEnableVertexAttribArray(positionLocation);195196glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[1]);197glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * testFlagData.size(), &testFlagData[0],198GL_STATIC_DRAW);199glVertexAttribPointer(testFlagLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);200glEnableVertexAttribArray(testFlagLocation);201202// Initialize second vertex array with first index buffer203glBindVertexArray(mVertexArrays[1]);204205glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);206207glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[0]);208glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);209glEnableVertexAttribArray(positionLocation);210211glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[1]);212glVertexAttribPointer(testFlagLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);213glEnableVertexAttribArray(testFlagLocation);214215ASSERT_GL_NO_ERROR();216217glBindVertexArray(mVertexArrays[0]);218glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);219EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);220221glBindVertexArray(mVertexArrays[1]);222glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);223EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);224225glBindVertexArray(mVertexArrays[0]);226glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);227EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);228229// Trigger the bug here.230glDeleteBuffers(1, &mIndexBuffers[2]);231232glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);233EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);234235ASSERT_GL_NO_ERROR();236}237238// Test drawing to part of the indices in an index buffer, and then all of them.239TEST_P(DrawElementsTest, PartOfIndexBufferThenAll)240{241// Init program242constexpr char kVS[] =243"attribute vec2 position;\n"244"attribute vec2 testFlag;\n"245"varying vec2 v_data;\n"246"void main() {\n"247" gl_Position = vec4(position, 0, 1);\n"248" v_data = testFlag;\n"249"}";250251constexpr char kFS[] =252"varying highp vec2 v_data;\n"253"void main() {\n"254" gl_FragColor = vec4(v_data, 0, 1);\n"255"}";256257mProgram = CompileProgram(kVS, kFS);258ASSERT_NE(0u, mProgram);259glUseProgram(mProgram);260261GLint positionLocation = glGetAttribLocation(mProgram, "position");262ASSERT_NE(-1, positionLocation);263264GLint testFlagLocation = glGetAttribLocation(mProgram, "testFlag");265ASSERT_NE(-1, testFlagLocation);266267mIndexBuffers.resize(1);268glGenBuffers(1, &mIndexBuffers[0]);269270mVertexArrays.resize(1);271glGenVertexArrays(1, &mVertexArrays[0]);272273mVertexBuffers.resize(2);274glGenBuffers(2, &mVertexBuffers[0]);275276std::vector<GLubyte> indexData[2];277indexData[0].push_back(0);278indexData[0].push_back(1);279indexData[0].push_back(2);280indexData[0].push_back(2);281indexData[0].push_back(3);282indexData[0].push_back(0);283indexData[0].push_back(4);284indexData[0].push_back(5);285indexData[0].push_back(6);286indexData[0].push_back(6);287indexData[0].push_back(7);288indexData[0].push_back(4);289290// Make a copy:291indexData[1] = indexData[0];292293std::vector<GLfloat> positionData = {// quad verts294-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,295// Repeat position data296-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f};297298std::vector<GLfloat> testFlagData = {// red2991.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,300// green3010.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};302303glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);304glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * indexData[0].size(), &indexData[0][0],305GL_STATIC_DRAW);306307glBindVertexArray(mVertexArrays[0]);308309glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);310glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[0]);311glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * positionData.size(), &positionData[0],312GL_STATIC_DRAW);313glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);314glEnableVertexAttribArray(positionLocation);315316glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[1]);317glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * testFlagData.size(), &testFlagData[0],318GL_STATIC_DRAW);319glVertexAttribPointer(testFlagLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);320glEnableVertexAttribArray(testFlagLocation);321322ASSERT_GL_NO_ERROR();323324// Draw with just the second set of 6 items, then first 6, and then the entire index buffer325glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(6));326EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);327328glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);329EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);330331glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, nullptr);332EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);333334// Reload the buffer again with a copy of the same data335glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * indexData[1].size(), &indexData[1][0],336GL_STATIC_DRAW);337338// Draw with just the first 6 indices, and then with the entire index buffer339glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);340EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);341342glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, nullptr);343EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);344345// Reload the buffer again with a copy of the same data346glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * indexData[0].size(), &indexData[0][0],347GL_STATIC_DRAW);348349// This time, do not check color between draws (which causes a flush):350// Draw with just the second set of 6 items, then first 6, and then the entire index buffer351glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(6));352glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);353glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, nullptr);354EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);355356ASSERT_GL_NO_ERROR();357}358359// Test that the offset in the index buffer is forced to be a multiple of the element size360TEST_P(WebGLDrawElementsTest, DrawElementsTypeAlignment)361{362constexpr char kVS[] =363"attribute vec3 a_pos;\n"364"void main()\n"365"{\n"366" gl_Position = vec4(a_pos, 1.0);\n"367"}\n";368369ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Blue());370371GLint posLocation = glGetAttribLocation(program, "a_pos");372ASSERT_NE(-1, posLocation);373glUseProgram(program);374375const auto &vertices = GetQuadVertices();376377GLBuffer vertexBuffer;378glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);379glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),380GL_STATIC_DRAW);381382glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);383glEnableVertexAttribArray(posLocation);384385GLBuffer indexBuffer;386const GLubyte indices1[] = {0, 0, 0, 0, 0, 0};387glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);388glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices1), indices1, GL_STATIC_DRAW);389390ASSERT_GL_NO_ERROR();391392const char *zeroIndices = nullptr;393394glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices);395ASSERT_GL_NO_ERROR();396397const GLushort indices2[] = {0, 0, 0, 0, 0, 0};398glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);399glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);400401glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices + 1);402EXPECT_GL_ERROR(GL_INVALID_OPERATION);403}404405GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawElementsTest);406ANGLE_INSTANTIATE_TEST_ES3(DrawElementsTest);407408ANGLE_INSTANTIATE_TEST_ES2(WebGLDrawElementsTest);409} // namespace410411412