1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Texture buffer test case
22 *//*--------------------------------------------------------------------*/
23
24 #include "glsTextureBufferCase.hpp"
25
26 #include "tcuFormatUtil.hpp"
27 #include "tcuImageCompare.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "tcuSurface.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuResultCollector.hpp"
34
35 #include "rrRenderer.hpp"
36 #include "rrShaders.hpp"
37
38 #include "gluObjectWrapper.hpp"
39 #include "gluPixelTransfer.hpp"
40 #include "gluShaderProgram.hpp"
41 #include "gluShaderUtil.hpp"
42 #include "gluStrUtil.hpp"
43 #include "gluTexture.hpp"
44 #include "gluTextureUtil.hpp"
45
46 #include "glwEnums.hpp"
47 #include "glwFunctions.hpp"
48
49 #include "deRandom.hpp"
50 #include "deStringUtil.hpp"
51 #include "deUniquePtr.hpp"
52
53 #include "deMemory.h"
54 #include "deString.h"
55 #include "deMath.h"
56
57 #include <sstream>
58 #include <string>
59 #include <vector>
60
61 using tcu::TestLog;
62
63 using std::map;
64 using std::string;
65 using std::vector;
66
67 using namespace deqp::gls::TextureBufferCaseUtil;
68
69 namespace deqp
70 {
71 namespace gls
72 {
73 namespace
74 {
75
76 enum
77 {
78 MAX_VIEWPORT_WIDTH = 256,
79 MAX_VIEWPORT_HEIGHT = 256,
80 MIN_VIEWPORT_WIDTH = 64,
81 MIN_VIEWPORT_HEIGHT = 64,
82 };
83
extend2BitsToByte(deUint8 bits)84 deUint8 extend2BitsToByte (deUint8 bits)
85 {
86 DE_ASSERT((bits & (~0x03u)) == 0);
87
88 return (deUint8)(bits | (bits << 2) | (bits << 4) | (bits << 6));
89 }
90
genRandomCoords(de::Random rng,vector<deUint8> & coords,size_t offset,size_t size)91 void genRandomCoords (de::Random rng, vector<deUint8>& coords, size_t offset, size_t size)
92 {
93 const deUint8 bits = 2;
94 const deUint8 bitMask = deUint8((0x1u << bits) - 1);
95
96 coords.resize(size);
97
98 for (int i = 0; i < (int)size; i++)
99 {
100 const deUint8 xBits = deUint8(rng.getUint32() & bitMask);
101 coords[i] = extend2BitsToByte(xBits);
102 }
103
104 // Fill indices with nice quad
105 {
106 const deUint8 indices[] =
107 {
108 extend2BitsToByte(0x0u),
109 extend2BitsToByte(0x1u),
110 extend2BitsToByte(0x2u),
111 extend2BitsToByte(0x3u)
112 };
113
114 for (int i = 0; i < DE_LENGTH_OF_ARRAY(indices); i++)
115 {
116 const deUint8 index = indices[i];
117 const size_t posX = (size_t(index) * 2) + 0;
118 const size_t posY = (size_t(index) * 2) + 1;
119
120 if (posX >= offset && posX < offset+size)
121 coords[posX - offset] = ((i % 2) == 0 ? extend2BitsToByte(0x0u) : extend2BitsToByte(0x3u));
122
123 if (posY >= offset && posY < offset+size)
124 coords[posY - offset] = ((i / 2) == 1 ? extend2BitsToByte(0x3u) : extend2BitsToByte(0x0u));
125 }
126 }
127
128 // Fill beginning of buffer
129 {
130 const deUint8 indices[] =
131 {
132 extend2BitsToByte(0x0u),
133 extend2BitsToByte(0x3u),
134 extend2BitsToByte(0x1u),
135
136 extend2BitsToByte(0x1u),
137 extend2BitsToByte(0x2u),
138 extend2BitsToByte(0x0u),
139
140 extend2BitsToByte(0x0u),
141 extend2BitsToByte(0x2u),
142 extend2BitsToByte(0x1u),
143
144 extend2BitsToByte(0x1u),
145 extend2BitsToByte(0x3u),
146 extend2BitsToByte(0x0u)
147 };
148
149 for (int i = (int)offset; i < DE_LENGTH_OF_ARRAY(indices) && i < (int)(offset + size); i++)
150 coords[i-offset] = indices[i];
151 }
152 }
153
154 class CoordVertexShader : public rr::VertexShader
155 {
156 public:
CoordVertexShader(void)157 CoordVertexShader (void)
158 : rr::VertexShader(1, 1)
159 {
160 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
161 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
162 }
163
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const164 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
165 {
166 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
167 {
168 rr::VertexPacket* const packet = packets[packetNdx];
169 tcu::Vec4 position;
170
171 readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
172
173 packet->outputs[0] = tcu::Vec4(1.0f);
174 packet->position = tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
175 }
176 }
177 };
178
179 class TextureVertexShader : public rr::VertexShader
180 {
181 public:
TextureVertexShader(const tcu::ConstPixelBufferAccess & texture)182 TextureVertexShader (const tcu::ConstPixelBufferAccess& texture)
183 : rr::VertexShader (1, 1)
184 , m_texture (texture)
185 {
186 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
187 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
188 }
189
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const190 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
191 {
192 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
193 {
194 rr::VertexPacket* const packet = packets[packetNdx];
195 tcu::Vec4 position;
196 tcu::Vec4 texelValue;
197
198 readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
199
200 texelValue = tcu::Vec4(m_texture.getPixel(de::clamp<int>((deRoundFloatToInt32(position.x() * 4) + 4) * (deRoundFloatToInt32(position.y() * 4) + 4), 0, m_texture.getWidth()-1), 0));
201
202 packet->outputs[0] = texelValue;
203 packet->position = tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
204 }
205 }
206
207 private:
208 const tcu::ConstPixelBufferAccess m_texture;
209 };
210
211 class CoordFragmentShader : public rr::FragmentShader
212 {
213 public:
CoordFragmentShader(void)214 CoordFragmentShader (void)
215 : rr::FragmentShader (1, 1)
216 {
217 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
218 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
219 }
220
221
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const222 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
223 {
224 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
225 {
226 rr::FragmentPacket& packet = packets[packetNdx];
227
228 const tcu::Vec4 vtxColor0 = rr::readVarying<float>(packet, context, 0, 0);
229 const tcu::Vec4 vtxColor1 = rr::readVarying<float>(packet, context, 0, 1);
230 const tcu::Vec4 vtxColor2 = rr::readVarying<float>(packet, context, 0, 2);
231 const tcu::Vec4 vtxColor3 = rr::readVarying<float>(packet, context, 0, 3);
232
233 const tcu::Vec4 color0 = vtxColor0;
234 const tcu::Vec4 color1 = vtxColor1;
235 const tcu::Vec4 color2 = vtxColor2;
236 const tcu::Vec4 color3 = vtxColor3;
237
238 rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
239 rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
240 rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
241 rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
242 }
243 }
244 };
245
246 class TextureFragmentShader : public rr::FragmentShader
247 {
248 public:
TextureFragmentShader(const tcu::ConstPixelBufferAccess & texture)249 TextureFragmentShader (const tcu::ConstPixelBufferAccess& texture)
250 : rr::FragmentShader (1, 1)
251 , m_texture (texture)
252 {
253 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
254 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
255 }
256
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const257 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
258 {
259 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
260 {
261 rr::FragmentPacket& packet = packets[packetNdx];
262
263 const tcu::IVec2 position0 = packet.position + tcu::IVec2(0, 0);
264 const tcu::IVec2 position1 = packet.position + tcu::IVec2(1, 0);
265 const tcu::IVec2 position2 = packet.position + tcu::IVec2(0, 1);
266 const tcu::IVec2 position3 = packet.position + tcu::IVec2(1, 1);
267
268 const tcu::Vec4 texColor0 = m_texture.getPixel(de::clamp((position0.x() * position0.y()), 0, m_texture.getWidth()-1), 0);
269 const tcu::Vec4 texColor1 = m_texture.getPixel(de::clamp((position1.x() * position1.y()), 0, m_texture.getWidth()-1), 0);
270 const tcu::Vec4 texColor2 = m_texture.getPixel(de::clamp((position2.x() * position2.y()), 0, m_texture.getWidth()-1), 0);
271 const tcu::Vec4 texColor3 = m_texture.getPixel(de::clamp((position3.x() * position3.y()), 0, m_texture.getWidth()-1), 0);
272
273 const tcu::Vec4 vtxColor0 = rr::readVarying<float>(packet, context, 0, 0);
274 const tcu::Vec4 vtxColor1 = rr::readVarying<float>(packet, context, 0, 1);
275 const tcu::Vec4 vtxColor2 = rr::readVarying<float>(packet, context, 0, 2);
276 const tcu::Vec4 vtxColor3 = rr::readVarying<float>(packet, context, 0, 3);
277
278 const tcu::Vec4 color0 = 0.5f * (vtxColor0 + texColor0);
279 const tcu::Vec4 color1 = 0.5f * (vtxColor1 + texColor1);
280 const tcu::Vec4 color2 = 0.5f * (vtxColor2 + texColor2);
281 const tcu::Vec4 color3 = 0.5f * (vtxColor3 + texColor3);
282
283 rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
284 rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
285 rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
286 rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
287 }
288 }
289
290 private:
291 const tcu::ConstPixelBufferAccess m_texture;
292 };
293
generateVertexShaderTemplate(RenderBits renderBits)294 string generateVertexShaderTemplate (RenderBits renderBits)
295 {
296 std::ostringstream stream;
297
298 stream <<
299 "${VERSION_HEADER}\n";
300
301 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
302 stream << "${TEXTURE_BUFFER_EXT}";
303
304 stream <<
305 "${VTX_INPUT} layout(location = 0) ${HIGHP} vec2 i_coord;\n"
306 "${VTX_OUTPUT} ${HIGHP} vec4 v_color;\n";
307
308 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
309 {
310 stream <<
311 "uniform ${HIGHP} samplerBuffer u_vtxSampler;\n";
312 }
313
314 stream <<
315 "\n"
316 "void main (void)\n"
317 "{\n";
318
319 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
320 stream << "\tv_color = texelFetch(u_vtxSampler, clamp((int(round(i_coord.x * 4.0)) + 4) * (int(round(i_coord.y * 4.0)) + 4), 0, textureSize(u_vtxSampler)-1));\n";
321 else
322 stream << "\tv_color = vec4(1.0);\n";
323
324 stream <<
325 "\tgl_Position = vec4(2.0 * (i_coord - vec2(0.5)), 0.0, 1.0);\n"
326 "}\n";
327
328 return stream.str();
329 }
330
generateFragmentShaderTemplate(RenderBits renderBits)331 string generateFragmentShaderTemplate (RenderBits renderBits)
332 {
333 std::ostringstream stream;
334
335 stream <<
336 "${VERSION_HEADER}\n";
337
338 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
339 stream << "${TEXTURE_BUFFER_EXT}";
340
341 stream <<
342 "${FRAG_OUTPUT} layout(location = 0) ${HIGHP} vec4 dEQP_FragColor;\n"
343 "${FRAG_INPUT} ${HIGHP} vec4 v_color;\n";
344
345 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
346 stream << "uniform ${HIGHP} samplerBuffer u_fragSampler;\n";
347
348 stream <<
349 "\n"
350 "void main (void)\n"
351 "{\n";
352
353 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
354 stream << "\t${HIGHP} vec4 color = 0.5 * (v_color + texelFetch(u_fragSampler, clamp(int(gl_FragCoord.x) * int(gl_FragCoord.y), 0, textureSize(u_fragSampler)-1)));\n";
355 else
356 stream << "\t${HIGHP} vec4 color = v_color;\n";
357
358 stream <<
359 "\tdEQP_FragColor = vec4(color.xyz * color.w, 1.0);\n"
360 "}\n";
361
362 return stream.str();
363 }
364
specializeShader(const string & shaderTemplateString,glu::GLSLVersion glslVersion)365 string specializeShader (const string& shaderTemplateString, glu::GLSLVersion glslVersion)
366 {
367 const tcu::StringTemplate shaderTemplate(shaderTemplateString);
368 map<string, string> parameters;
369
370 parameters["VERSION_HEADER"] = glu::getGLSLVersionDeclaration(glslVersion);
371 parameters["VTX_OUTPUT"] = "out";
372 parameters["VTX_INPUT"] = "in";
373 parameters["FRAG_INPUT"] = "in";
374 parameters["FRAG_OUTPUT"] = "out";
375 parameters["HIGHP"] = (glslVersion == glu::GLSL_VERSION_330 ? "" : "highp");
376 parameters["TEXTURE_BUFFER_EXT"] = (glslVersion == glu::GLSL_VERSION_330 ? "" : "#extension GL_EXT_texture_buffer : enable\n");
377
378 return shaderTemplate.specialize(parameters);
379 }
380
createRenderProgram(glu::RenderContext & renderContext,RenderBits renderBits)381 glu::ShaderProgram* createRenderProgram (glu::RenderContext& renderContext,
382 RenderBits renderBits)
383 {
384 const string vertexShaderTemplate = generateVertexShaderTemplate(renderBits);
385 const string fragmentShaderTemplate = generateFragmentShaderTemplate(renderBits);
386
387 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(renderContext.getType());
388
389 const string vertexShaderSource = specializeShader(vertexShaderTemplate, glslVersion);
390 const string fragmentShaderSource = specializeShader(fragmentShaderTemplate, glslVersion);
391
392 glu::ShaderProgram* const program = new glu::ShaderProgram(renderContext, glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
393
394 return program;
395 }
396
logModifications(TestLog & log,ModifyBits modifyBits)397 void logModifications (TestLog& log, ModifyBits modifyBits)
398 {
399 tcu::ScopedLogSection section(log, "Modify Operations", "Modify Operations");
400
401 const struct
402 {
403 ModifyBits bit;
404 const char* str;
405 } bitInfos[] =
406 {
407 { MODIFYBITS_BUFFERDATA, "Recreate buffer data with glBufferData()." },
408 { MODIFYBITS_BUFFERSUBDATA, "Modify texture buffer with glBufferSubData()." },
409 { MODIFYBITS_MAPBUFFER_WRITE, "Map buffer write-only and rewrite data." },
410 { MODIFYBITS_MAPBUFFER_READWRITE, "Map buffer readw-write check and rewrite data." }
411 };
412
413 DE_ASSERT(modifyBits != 0);
414
415 for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
416 {
417 if (modifyBits & bitInfos[infoNdx].bit)
418 log << TestLog::Message << bitInfos[infoNdx].str << TestLog::EndMessage;
419 }
420 }
421
modifyBufferData(TestLog & log,de::Random & rng,glu::TextureBuffer & texture)422 void modifyBufferData (TestLog& log,
423 de::Random& rng,
424 glu::TextureBuffer& texture)
425 {
426 vector<deUint8> data;
427
428 genRandomCoords(rng, data, 0, texture.getBufferSize());
429
430 log << TestLog::Message << "BufferData, Size: " << data.size() << TestLog::EndMessage;
431
432 {
433 // replace getRefBuffer with a new buffer
434 de::ArrayBuffer<deUint8> buffer(&(data[0]), data.size());
435 texture.getRefBuffer().swap(buffer);
436 }
437
438 texture.upload();
439 }
440
modifyBufferSubData(TestLog & log,de::Random & rng,const glw::Functions & gl,glu::TextureBuffer & texture)441 void modifyBufferSubData (TestLog& log,
442 de::Random& rng,
443 const glw::Functions& gl,
444 glu::TextureBuffer& texture)
445 {
446 const size_t minSize = 4*16;
447 const size_t size = de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
448 const size_t minOffset = texture.getOffset();
449 const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
450 vector<deUint8> data;
451
452 genRandomCoords(rng, data, offset, size);
453
454 log << TestLog::Message << "BufferSubData, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
455
456 gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
457 gl.bufferSubData(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)data.size(), &(data[0]));
458 gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
459 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glBufferSubData()");
460
461 deMemcpy((deUint8*)texture.getRefBuffer().getPtr() + offset, &(data[0]), int(data.size()));
462 }
463
modifyMapWrite(TestLog & log,de::Random & rng,const glw::Functions & gl,glu::TextureBuffer & texture)464 void modifyMapWrite (TestLog& log,
465 de::Random& rng,
466 const glw::Functions& gl,
467 glu::TextureBuffer& texture)
468 {
469 const size_t minSize = 4*16;
470 const size_t size = de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
471 const size_t minOffset = texture.getOffset();
472 const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
473 vector<deUint8> data;
474
475 genRandomCoords(rng, data, offset, size);
476
477 log << TestLog::Message << "glMapBufferRange, Write Only, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
478
479 gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
480 {
481 deUint8* ptr = (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT);
482
483 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
484 TCU_CHECK(ptr);
485
486 for (int i = 0; i < (int)data.size(); i++)
487 ptr[i] = data[i];
488
489 TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
490 }
491 gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
492 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
493
494 deMemcpy((deUint8*)texture.getRefBuffer().getPtr()+offset, &(data[0]), int(data.size()));
495 }
496
modifyMapReadWrite(TestLog & log,tcu::ResultCollector & resultCollector,de::Random & rng,const glw::Functions & gl,glu::TextureBuffer & texture)497 void modifyMapReadWrite (TestLog& log,
498 tcu::ResultCollector& resultCollector,
499 de::Random& rng,
500 const glw::Functions& gl,
501 glu::TextureBuffer& texture)
502 {
503 const size_t minSize = 4*16;
504 const size_t size = de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
505 const size_t minOffset = texture.getOffset();
506 const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
507 deUint8* const refPtr = (deUint8*)texture.getRefBuffer().getPtr() + offset;
508 vector<deUint8> data;
509
510 genRandomCoords(rng, data, offset, size);
511
512 log << TestLog::Message << "glMapBufferRange, Read Write, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
513
514 gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
515 {
516 size_t invalidBytes = 0;
517 deUint8* const ptr = (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT|GL_MAP_READ_BIT);
518
519 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
520 TCU_CHECK(ptr);
521
522 for (int i = 0; i < (int)data.size(); i++)
523 {
524 if (ptr[i] != refPtr[i])
525 {
526 if (invalidBytes < 24)
527 log << TestLog::Message << "Invalid byte in mapped buffer. " << tcu::Format::Hex<2>(data[i]).toString() << " at " << i << ", expected " << tcu::Format::Hex<2>(refPtr[i]).toString() << TestLog::EndMessage;
528
529 invalidBytes++;
530 }
531
532 ptr[i] = data[i];
533 }
534
535 TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
536
537 if (invalidBytes > 0)
538 {
539 log << TestLog::Message << "Total of " << invalidBytes << " invalid bytes." << TestLog::EndMessage;
540 resultCollector.fail("Invalid data in mapped buffer");
541 }
542 }
543
544 gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
545 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
546
547 for (int i = 0; i < (int)data.size(); i++)
548 refPtr[i] = data[i];
549 }
550
modify(TestLog & log,tcu::ResultCollector & resultCollector,glu::RenderContext & renderContext,ModifyBits modifyBits,de::Random & rng,glu::TextureBuffer & texture)551 void modify (TestLog& log,
552 tcu::ResultCollector& resultCollector,
553 glu::RenderContext& renderContext,
554 ModifyBits modifyBits,
555 de::Random& rng,
556 glu::TextureBuffer& texture)
557 {
558 const tcu::ScopedLogSection modifySection(log, "Modifying Texture buffer", "Modifying Texture Buffer");
559
560 logModifications(log, modifyBits);
561
562 if (modifyBits & MODIFYBITS_BUFFERDATA)
563 modifyBufferData(log, rng, texture);
564
565 if (modifyBits & MODIFYBITS_BUFFERSUBDATA)
566 modifyBufferSubData(log, rng, renderContext.getFunctions(), texture);
567
568 if (modifyBits & MODIFYBITS_MAPBUFFER_WRITE)
569 modifyMapWrite(log, rng, renderContext.getFunctions(), texture);
570
571 if (modifyBits & MODIFYBITS_MAPBUFFER_READWRITE)
572 modifyMapReadWrite(log, resultCollector, rng, renderContext.getFunctions(), texture);
573 }
574
renderGL(glu::RenderContext & renderContext,RenderBits renderBits,deUint32 coordSeed,int triangleCount,glu::ShaderProgram & program,glu::TextureBuffer & texture)575 void renderGL (glu::RenderContext& renderContext,
576 RenderBits renderBits,
577 deUint32 coordSeed,
578 int triangleCount,
579 glu::ShaderProgram& program,
580 glu::TextureBuffer& texture)
581 {
582 const glw::Functions& gl = renderContext.getFunctions();
583 const glu::VertexArray vao (renderContext);
584 const glu::Buffer coordBuffer (renderContext);
585
586 gl.useProgram(program.getProgram());
587 gl.bindVertexArray(*vao);
588
589 gl.enableVertexAttribArray(0);
590
591 if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
592 {
593 gl.bindBuffer(GL_ARRAY_BUFFER, texture.getGLBuffer());
594 gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
595 }
596 else
597 {
598 de::Random rng(coordSeed);
599 vector<deUint8> coords;
600
601 genRandomCoords(rng, coords, 0, 256*2);
602
603 gl.bindBuffer(GL_ARRAY_BUFFER, *coordBuffer);
604 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)coords.size(), &(coords[0]), GL_STREAM_DRAW);
605 gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
606 }
607
608 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
609 {
610 const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_vtxSampler");
611
612 gl.activeTexture(GL_TEXTURE0);
613 gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
614 gl.uniform1i(location, 0);
615 }
616
617 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
618 {
619 const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_fragSampler");
620
621 gl.activeTexture(GL_TEXTURE1);
622 gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
623 gl.uniform1i(location, 1);
624 gl.activeTexture(GL_TEXTURE0);
625 }
626
627 if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
628 {
629 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, texture.getGLBuffer());
630 gl.drawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_BYTE, DE_NULL);
631 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
632 }
633 else
634 gl.drawArrays(GL_TRIANGLES, 0, triangleCount * 3);
635
636 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
637 {
638 gl.activeTexture(GL_TEXTURE1);
639 gl.bindTexture(GL_TEXTURE_BUFFER, 0);
640 }
641
642 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
643 {
644 gl.activeTexture(GL_TEXTURE0);
645 gl.bindTexture(GL_TEXTURE_BUFFER, 0);
646 }
647
648 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
649 gl.disableVertexAttribArray(0);
650
651 gl.bindVertexArray(0);
652 gl.useProgram(0);
653 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
654 }
655
renderReference(RenderBits renderBits,deUint32 coordSeed,int triangleCount,const glu::TextureBuffer & texture,int maxTextureBufferSize,const tcu::PixelBufferAccess & target,int subpixelBits)656 void renderReference (RenderBits renderBits,
657 deUint32 coordSeed,
658 int triangleCount,
659 const glu::TextureBuffer& texture,
660 int maxTextureBufferSize,
661 const tcu::PixelBufferAccess& target,
662 int subpixelBits)
663 {
664 const tcu::ConstPixelBufferAccess effectiveAccess = glu::getTextureBufferEffectiveRefTexture(texture, maxTextureBufferSize);
665
666 const CoordVertexShader coordVertexShader;
667 const TextureVertexShader textureVertexShader (effectiveAccess);
668 const rr::VertexShader* const vertexShader = (renderBits & RENDERBITS_AS_VERTEX_TEXTURE ? static_cast<const rr::VertexShader*>(&textureVertexShader) : &coordVertexShader);
669
670 const CoordFragmentShader coordFragmmentShader;
671 const TextureFragmentShader textureFragmentShader (effectiveAccess);
672 const rr::FragmentShader* const fragmentShader = (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE ? static_cast<const rr::FragmentShader*>(&textureFragmentShader) : &coordFragmmentShader);
673
674 const rr::Renderer renderer;
675 const rr::RenderState renderState(rr::ViewportState(rr::WindowRectangle(0, 0, target.getWidth(), target.getHeight())), subpixelBits);
676 const rr::RenderTarget renderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(target));
677
678 const rr::Program program(vertexShader, fragmentShader);
679
680 rr::VertexAttrib vertexAttribs[1];
681 vector<deUint8> coords;
682
683 if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
684 {
685 vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
686 vertexAttribs[0].size = 2;
687 vertexAttribs[0].pointer = texture.getRefBuffer().getPtr();
688 }
689 else
690 {
691 de::Random rng(coordSeed);
692
693 genRandomCoords(rng, coords, 0, 256*2);
694
695 vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
696 vertexAttribs[0].size = 2;
697 vertexAttribs[0].pointer = &(coords[0]);
698 }
699
700 if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
701 {
702 const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, rr::DrawIndices(texture.getRefBuffer().getPtr(), rr::INDEXTYPE_UINT8));
703 const rr::DrawCommand cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
704
705 renderer.draw(cmd);
706 }
707 else
708 {
709 const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, 0);
710 const rr::DrawCommand cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
711
712 renderer.draw(cmd);
713 }
714 }
715
logRendering(TestLog & log,RenderBits renderBits)716 void logRendering (TestLog& log, RenderBits renderBits)
717 {
718 const struct
719 {
720 RenderBits bit;
721 const char* str;
722 } bitInfos[] =
723 {
724 { RENDERBITS_AS_VERTEX_ARRAY, "vertex array" },
725 { RENDERBITS_AS_INDEX_ARRAY, "index array" },
726 { RENDERBITS_AS_VERTEX_TEXTURE, "vertex texture" },
727 { RENDERBITS_AS_FRAGMENT_TEXTURE, "fragment texture" }
728 };
729
730 std::ostringstream stream;
731 vector<const char*> usedAs;
732
733 DE_ASSERT(renderBits != 0);
734
735 for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
736 {
737 if (renderBits & bitInfos[infoNdx].bit)
738 usedAs.push_back(bitInfos[infoNdx].str);
739 }
740
741 stream << "Render using texture buffer as ";
742
743 for (int asNdx = 0; asNdx < (int)usedAs.size(); asNdx++)
744 {
745 if (asNdx+1 == (int)usedAs.size() && (int)usedAs.size() > 1)
746 stream << " and ";
747 else if (asNdx > 0)
748 stream << ", ";
749
750 stream << usedAs[asNdx];
751 }
752
753 stream << ".";
754
755 log << TestLog::Message << stream.str() << TestLog::EndMessage;
756 }
757
render(TestLog & log,glu::RenderContext & renderContext,RenderBits renderBits,de::Random & rng,glu::ShaderProgram & program,glu::TextureBuffer & texture,const tcu::PixelBufferAccess & target)758 void render (TestLog& log,
759 glu::RenderContext& renderContext,
760 RenderBits renderBits,
761 de::Random& rng,
762 glu::ShaderProgram& program,
763 glu::TextureBuffer& texture,
764 const tcu::PixelBufferAccess& target)
765 {
766 const tcu::ScopedLogSection renderSection (log, "Render Texture buffer", "Render Texture Buffer");
767 const int triangleCount = 8;
768 const deUint32 coordSeed = rng.getUint32();
769 int maxTextureBufferSize = 0;
770
771 renderContext.getFunctions().getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize);
772 GLU_EXPECT_NO_ERROR(renderContext.getFunctions().getError(), "query GL_MAX_TEXTURE_BUFFER_SIZE");
773 DE_ASSERT(maxTextureBufferSize > 0); // checked in init()
774
775 logRendering(log, renderBits);
776
777 renderGL(renderContext, renderBits, coordSeed, triangleCount, program, texture);
778
779 int subpixelBits = 0;
780 renderContext.getFunctions().getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
781 renderReference(renderBits, coordSeed, triangleCount, texture, maxTextureBufferSize, target, subpixelBits);
782 }
783
verifyScreen(TestLog & log,tcu::ResultCollector & resultCollector,glu::RenderContext & renderContext,const tcu::ConstPixelBufferAccess & referenceTarget)784 void verifyScreen (TestLog& log,
785 tcu::ResultCollector& resultCollector,
786 glu::RenderContext& renderContext,
787 const tcu::ConstPixelBufferAccess& referenceTarget)
788 {
789 const tcu::ScopedLogSection verifySection (log, "Verify screen contents", "Verify screen contents");
790 tcu::Surface screen (referenceTarget.getWidth(), referenceTarget.getHeight());
791
792 glu::readPixels(renderContext, 0, 0, screen.getAccess());
793
794 if (!tcu::fuzzyCompare(log, "Result of rendering", "Result of rendering", referenceTarget, screen.getAccess(), 0.05f, tcu::COMPARE_LOG_RESULT))
795 resultCollector.fail("Rendering failed");
796 }
797
logImplementationInfo(TestLog & log,glu::RenderContext & renderContext)798 void logImplementationInfo (TestLog& log, glu::RenderContext& renderContext)
799 {
800 const tcu::ScopedLogSection section (log, "Implementation Values", "Implementation Values");
801 de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(renderContext));
802 const glw::Functions& gl = renderContext.getFunctions();
803
804 if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)))
805 {
806 deInt32 maxTextureSize = 0;
807
808 gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
809 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE)");
810
811 log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE : " << maxTextureSize << TestLog::EndMessage;
812 }
813 else if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer"))
814 {
815 {
816 deInt32 maxTextureSize = 0;
817
818 gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
819 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE_EXT)");
820
821 log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE_EXT : " << maxTextureSize << TestLog::EndMessage;
822 }
823
824 {
825 deInt32 textureBufferAlignment = 0;
826
827 gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &textureBufferAlignment);
828 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT)");
829
830 log << TestLog::Message << "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT : " << textureBufferAlignment << TestLog::EndMessage;
831 }
832 }
833 else
834 DE_ASSERT(DE_FALSE);
835 }
836
logTextureInfo(TestLog & log,deUint32 format,size_t bufferSize,size_t offset,size_t size)837 void logTextureInfo (TestLog& log,
838 deUint32 format,
839 size_t bufferSize,
840 size_t offset,
841 size_t size)
842 {
843 const tcu::ScopedLogSection section(log, "Texture Info", "Texture Info");
844
845 log << TestLog::Message << "Texture format : " << glu::getTextureFormatStr(format) << TestLog::EndMessage;
846 log << TestLog::Message << "Buffer size : " << bufferSize << TestLog::EndMessage;
847
848 if (offset != 0 || size != 0)
849 {
850 log << TestLog::Message << "Buffer range offset: " << offset << TestLog::EndMessage;
851 log << TestLog::Message << "Buffer range size: " << size << TestLog::EndMessage;
852 }
853 }
854
runTests(tcu::TestContext & testCtx,glu::RenderContext & renderContext,de::Random & rng,deUint32 format,size_t bufferSize,size_t offset,size_t size,RenderBits preRender,glu::ShaderProgram * preRenderProgram,ModifyBits modifyType,RenderBits postRender,glu::ShaderProgram * postRenderProgram)855 void runTests (tcu::TestContext& testCtx,
856 glu::RenderContext& renderContext,
857 de::Random& rng,
858 deUint32 format,
859 size_t bufferSize,
860 size_t offset,
861 size_t size,
862 RenderBits preRender,
863 glu::ShaderProgram* preRenderProgram,
864 ModifyBits modifyType,
865 RenderBits postRender,
866 glu::ShaderProgram* postRenderProgram)
867 {
868 const tcu::RenderTarget renderTarget (renderContext.getRenderTarget());
869 const glw::Functions& gl = renderContext.getFunctions();
870
871 const int width = de::min<int>(renderTarget.getWidth(), MAX_VIEWPORT_WIDTH);
872 const int height = de::min<int>(renderTarget.getHeight(), MAX_VIEWPORT_HEIGHT);
873 const tcu::Vec4 clearColor (0.25f, 0.5f, 0.75f, 1.0f);
874
875 TestLog& log = testCtx.getLog();
876 tcu::ResultCollector resultCollector (log);
877
878 logImplementationInfo(log, renderContext);
879 logTextureInfo(log, format, bufferSize, offset, size);
880
881 {
882 tcu::Surface referenceTarget (width, height);
883 vector<deUint8> bufferData;
884
885 genRandomCoords(rng, bufferData, 0, bufferSize);
886
887 for (deUint8 i = 0; i < 4; i++)
888 {
889 const deUint8 val = extend2BitsToByte(i);
890
891 if (val >= offset && val < offset + size)
892 {
893 bufferData[val*2 + 0] = (i / 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
894 bufferData[val*2 + 1] = (i % 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
895 }
896 }
897
898 {
899 glu::TextureBuffer texture (renderContext, format, bufferSize, offset, size, &(bufferData[0]));
900
901 TCU_CHECK_MSG(width >= MIN_VIEWPORT_WIDTH || height >= MIN_VIEWPORT_HEIGHT, "Too small viewport");
902
903 DE_ASSERT(preRender == 0 || preRenderProgram);
904 DE_ASSERT(postRender == 0 || postRenderProgram);
905
906 gl.viewport(0, 0, width, height);
907 gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
908 gl.clear(GL_COLOR_BUFFER_BIT);
909 GLU_EXPECT_NO_ERROR(gl.getError(), "Screen setup failed");
910
911 tcu::clear(referenceTarget.getAccess(), clearColor);
912
913 texture.upload();
914
915 if (preRender != 0)
916 render(log, renderContext, preRender, rng, *preRenderProgram, texture, referenceTarget.getAccess());
917
918 if (modifyType != 0)
919 modify(log, resultCollector, renderContext, modifyType, rng, texture);
920
921 if (postRender != 0)
922 render(log, renderContext, postRender, rng, *postRenderProgram, texture, referenceTarget.getAccess());
923 }
924
925 verifyScreen(log, resultCollector, renderContext, referenceTarget.getAccess());
926
927 resultCollector.setTestContextResult(testCtx);
928 }
929 }
930
931 } // anonymous
932
TextureBufferCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,deUint32 format,size_t bufferSize,size_t offset,size_t size,RenderBits preRender,ModifyBits modify,RenderBits postRender,const char * name,const char * description)933 TextureBufferCase::TextureBufferCase (tcu::TestContext& testCtx,
934 glu::RenderContext& renderCtx,
935 deUint32 format,
936 size_t bufferSize,
937 size_t offset,
938 size_t size,
939 RenderBits preRender,
940 ModifyBits modify,
941 RenderBits postRender,
942 const char* name,
943 const char* description)
944 : tcu::TestCase (testCtx, name, description)
945 , m_renderCtx (renderCtx)
946 , m_format (format)
947 , m_bufferSize (bufferSize)
948 , m_offset (offset)
949 , m_size (size)
950
951 , m_preRender (preRender)
952 , m_modify (modify)
953 , m_postRender (postRender)
954
955 , m_preRenderProgram (DE_NULL)
956 , m_postRenderProgram (DE_NULL)
957 {
958 }
959
~TextureBufferCase(void)960 TextureBufferCase::~TextureBufferCase (void)
961 {
962 TextureBufferCase::deinit();
963 }
964
init(void)965 void TextureBufferCase::init (void)
966 {
967 de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(m_renderCtx));
968
969 if (!glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
970 && !(glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer")))
971 throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
972
973 {
974 const int maxTextureBufferSize = info->getInt(GL_MAX_TEXTURE_BUFFER_SIZE);
975 if (maxTextureBufferSize <= 0)
976 TCU_THROW(NotSupportedError, "GL_MAX_TEXTURE_BUFFER_SIZE > 0 required");
977 }
978
979 if (m_preRender != 0)
980 {
981 TestLog& log = m_testCtx.getLog();
982 const char* const sectionName = (m_postRender != 0 ? "Primary render program" : "Render program");
983 const tcu::ScopedLogSection section (log, sectionName, sectionName);
984
985 m_preRenderProgram = createRenderProgram(m_renderCtx, m_preRender);
986 m_testCtx.getLog() << (*m_preRenderProgram);
987
988 TCU_CHECK(m_preRenderProgram->isOk());
989 }
990
991 if (m_postRender != 0)
992 {
993 // Reusing program
994 if (m_preRender == m_postRender)
995 {
996 m_postRenderProgram = m_preRenderProgram;
997 }
998 else
999 {
1000 TestLog& log = m_testCtx.getLog();
1001 const char* const sectionName = (m_preRender!= 0 ? "Secondary render program" : "Render program");
1002 const tcu::ScopedLogSection section (log, sectionName, sectionName);
1003
1004 m_postRenderProgram = createRenderProgram(m_renderCtx, m_postRender);
1005 m_testCtx.getLog() << (*m_postRenderProgram);
1006
1007 TCU_CHECK(m_postRenderProgram->isOk());
1008 }
1009 }
1010 }
1011
deinit(void)1012 void TextureBufferCase::deinit (void)
1013 {
1014 if (m_preRenderProgram == m_postRenderProgram)
1015 m_postRenderProgram = DE_NULL;
1016
1017 delete m_preRenderProgram;
1018 m_preRenderProgram = DE_NULL;
1019
1020 delete m_postRenderProgram;
1021 m_postRenderProgram = DE_NULL;
1022 }
1023
iterate(void)1024 tcu::TestCase::IterateResult TextureBufferCase::iterate (void)
1025 {
1026 de::Random rng (deInt32Hash(deStringHash(getName())));
1027 size_t offset;
1028
1029 if (m_offset != 0)
1030 {
1031 const glw::Functions& gl = m_renderCtx.getFunctions();
1032 deInt32 alignment = 0;
1033
1034 gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &alignment);
1035 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT)");
1036
1037 offset = m_offset * alignment;
1038 }
1039 else
1040 offset = 0;
1041
1042 runTests(m_testCtx, m_renderCtx, rng, m_format, m_bufferSize, offset, m_size, m_preRender, m_preRenderProgram, m_modify, m_postRender, m_postRenderProgram);
1043
1044 return STOP;
1045 }
1046
1047 } // gls
1048 } // deqp
1049