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