• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 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 // IndexBufferOffsetTest.cpp: Test glDrawElements with an offset and an index buffer
8 
9 #include "test_utils/ANGLETest.h"
10 #include "util/test_utils.h"
11 
12 using namespace angle;
13 
14 class IndexBufferOffsetTest : public ANGLETest
15 {
16   protected:
IndexBufferOffsetTest()17     IndexBufferOffsetTest()
18     {
19         setWindowWidth(128);
20         setWindowHeight(128);
21         setConfigRedBits(8);
22         setConfigGreenBits(8);
23         setConfigBlueBits(8);
24         setConfigAlphaBits(8);
25     }
26 
testSetUp()27     void testSetUp() override
28     {
29         constexpr char kVS[] =
30             R"(precision highp float;
31             attribute vec2 position;
32 
33             void main()
34             {
35                 gl_Position = vec4(position, 0.0, 1.0);
36             })";
37 
38         constexpr char kFS[] =
39             R"(precision highp float;
40             uniform vec4 color;
41 
42             void main()
43             {
44                 gl_FragColor = color;
45             })";
46 
47         mProgram = CompileProgram(kVS, kFS);
48         ASSERT_NE(0u, mProgram);
49 
50         mColorUniformLocation      = glGetUniformLocation(mProgram, "color");
51         mPositionAttributeLocation = glGetAttribLocation(mProgram, "position");
52 
53         const GLfloat vertices[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
54         glGenBuffers(1, &mVertexBuffer);
55         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
56         glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
57 
58         glGenBuffers(1, &mIndexBuffer);
59         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
60     }
61 
testTearDown()62     void testTearDown() override
63     {
64         glDeleteBuffers(1, &mVertexBuffer);
65         glDeleteBuffers(1, &mIndexBuffer);
66         glDeleteProgram(mProgram);
67     }
68 
runTest(GLenum type,int typeWidth,void * indexData)69     void runTest(GLenum type, int typeWidth, void *indexData)
70     {
71         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
72         glClear(GL_COLOR_BUFFER_BIT);
73 
74         GLuint nullIndexData[] = {0, 0, 0, 0, 0, 0};
75 
76         size_t indexDataWidth = 6 * typeWidth;
77 
78         glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * indexDataWidth, nullptr, GL_DYNAMIC_DRAW);
79         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexDataWidth, nullIndexData);
80         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, indexData);
81         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, nullIndexData);
82 
83         glUseProgram(mProgram);
84 
85         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
86         glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
87         glEnableVertexAttribArray(mPositionAttributeLocation);
88 
89         glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
90 
91         for (int i = 0; i < 16; i++)
92         {
93             glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<void *>(indexDataWidth));
94             EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::red);
95         }
96 
97         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexDataWidth, nullIndexData);
98         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 2 * indexDataWidth, indexDataWidth, indexData);
99 
100         glUniform4f(mColorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
101         glDrawElements(GL_TRIANGLES, 6, type, reinterpret_cast<void *>(indexDataWidth * 2));
102         EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::green);
103 
104         EXPECT_GL_NO_ERROR();
105         swapBuffers();
106     }
107 
108     GLuint mProgram;
109     GLint mColorUniformLocation;
110     GLint mPositionAttributeLocation;
111     GLuint mVertexBuffer;
112     GLuint mIndexBuffer;
113 };
114 
115 // Test using an offset for an UInt8 index buffer
TEST_P(IndexBufferOffsetTest,UInt8Index)116 TEST_P(IndexBufferOffsetTest, UInt8Index)
117 {
118     GLubyte indexData[] = {0, 1, 2, 1, 2, 3};
119     runTest(GL_UNSIGNED_BYTE, 1, indexData);
120 }
121 
122 // Test using an offset for an UInt16 index buffer
TEST_P(IndexBufferOffsetTest,UInt16Index)123 TEST_P(IndexBufferOffsetTest, UInt16Index)
124 {
125     // TODO(jie.a.chen@intel.com): Re-enable the test once the driver fix is
126     // available in public release.
127     // http://anglebug.com/2663
128     ANGLE_SKIP_TEST_IF(IsIntel() && IsVulkan());
129 
130     GLushort indexData[] = {0, 1, 2, 1, 2, 3};
131     runTest(GL_UNSIGNED_SHORT, 2, indexData);
132 }
133 
134 // Test using an offset for an UInt32 index buffer
TEST_P(IndexBufferOffsetTest,UInt32Index)135 TEST_P(IndexBufferOffsetTest, UInt32Index)
136 {
137     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
138                        !IsGLExtensionEnabled("GL_OES_element_index_uint"));
139 
140     GLuint indexData[] = {0, 1, 2, 1, 2, 3};
141     runTest(GL_UNSIGNED_INT, 4, indexData);
142 }
143 
144 // Uses index buffer offset and 2 drawElement calls one of the other, makes sure the second
145 // drawElement call will use the correct offset.
TEST_P(IndexBufferOffsetTest,DrawAtDifferentOffsets)146 TEST_P(IndexBufferOffsetTest, DrawAtDifferentOffsets)
147 {
148     GLushort indexData[] = {0, 1, 2, 1, 2, 3};
149     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
150     glClear(GL_COLOR_BUFFER_BIT);
151 
152     size_t indexDataWidth = 6 * sizeof(GLushort);
153 
154     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexData, GL_DYNAMIC_DRAW);
155     glUseProgram(mProgram);
156 
157     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
158     glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
159     glEnableVertexAttribArray(mPositionAttributeLocation);
160 
161     glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
162 
163     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
164     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT,
165                    reinterpret_cast<void *>(indexDataWidth / 2));
166 
167     // Check the upper left triangle
168     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red);
169 
170     // Check the down right triangle
171     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
172 
173     EXPECT_GL_NO_ERROR();
174 }
175 
176 // Uses index buffer offset and 2 drawElement calls one of the other, one has aligned
177 // offset and one doesn't
TEST_P(IndexBufferOffsetTest,DrawAtDifferentOffsetAlignments)178 TEST_P(IndexBufferOffsetTest, DrawAtDifferentOffsetAlignments)
179 {
180     GLubyte indexData8[]   = {0, 1, 0, 1, 2, 3};
181     GLushort indexData16[] = {0, 1, 2, 1, 2, 3};
182     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
183     glClear(GL_COLOR_BUFFER_BIT);
184 
185     size_t indexDataWidth16 = 6 * sizeof(GLushort);
186 
187     GLuint buffer[2];
188     glGenBuffers(2, buffer);
189 
190     glUseProgram(mProgram);
191     glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
192 
193     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
194     glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
195     glEnableVertexAttribArray(mPositionAttributeLocation);
196 
197     // 8 bit index with aligned offset
198     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[0]);
199     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData8), indexData8, GL_DYNAMIC_DRAW);
200 
201     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(2));
202 
203     // 16 bits index buffer, which unaligned offset
204     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[1]);
205     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth16, indexData16, GL_DYNAMIC_DRAW);
206 
207     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT,
208                    reinterpret_cast<void *>(indexDataWidth16 / 2));
209 
210     // Check the upper left triangle
211     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red);
212 
213     // Check the down right triangle
214     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
215 
216     EXPECT_GL_NO_ERROR();
217 }
218 
219 // Uses index buffer offset and 2 drawElement calls one of the other with different counts,
220 // makes sure the second drawElement call will have its data available.
TEST_P(IndexBufferOffsetTest,DrawWithDifferentCountsSameOffset)221 TEST_P(IndexBufferOffsetTest, DrawWithDifferentCountsSameOffset)
222 {
223     GLubyte indexData[] = {99, 0, 1, 2, 1, 2, 3};
224     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
225     glClear(GL_COLOR_BUFFER_BIT);
226 
227     size_t indexDataWidth = 7 * sizeof(GLubyte);
228 
229     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexDataWidth, indexData, GL_DYNAMIC_DRAW);
230     glUseProgram(mProgram);
231 
232     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
233     glVertexAttribPointer(mPositionAttributeLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
234     glEnableVertexAttribArray(mPositionAttributeLocation);
235 
236     glUniform4f(mColorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
237 
238     // The first draw draws the first triangle, and the second draws a quad.
239     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(1));
240     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(1));
241 
242     // Check the upper left triangle
243     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4, GLColor::red);
244 
245     // Check the down right triangle
246     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
247 
248     EXPECT_GL_NO_ERROR();
249 }
250 
251 ANGLE_INSTANTIATE_TEST(IndexBufferOffsetTest,
252                        ES2_D3D9(),
253                        ES2_D3D11(),
254                        ES3_D3D11(),
255                        ES2_METAL(),
256                        ES2_OPENGL(),
257                        ES3_OPENGL(),
258                        ES2_OPENGLES(),
259                        ES3_OPENGLES(),
260                        ES2_VULKAN());
261