1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Texture buffer test case
22 *//*--------------------------------------------------------------------*/
24 #include "glsTextureBufferCase.hpp"
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"
35 #include "rrRenderer.hpp"
36 #include "rrShaders.hpp"
38 #include "gluObjectWrapper.hpp"
39 #include "gluPixelTransfer.hpp"
40 #include "gluShaderProgram.hpp"
41 #include "gluShaderUtil.hpp"
42 #include "gluStrUtil.hpp"
43 #include "gluTexture.hpp"
45 #include "glwEnums.hpp"
46 #include "glwFunctions.hpp"
48 #include "deRandom.hpp"
49 #include "deStringUtil.hpp"
50 #include "deUniquePtr.hpp"
66 using namespace deqp::gls::TextureBufferCaseUtil;
77 MAX_VIEWPORT_WIDTH = 256,
78 MAX_VIEWPORT_HEIGHT = 256,
79 MIN_VIEWPORT_WIDTH = 64,
80 MIN_VIEWPORT_HEIGHT = 64,
83 deUint8 extend2BitsToByte (deUint8 bits)
87 DE_ASSERT((bits & (~0x03u)) == 0);
97 void genRandomCoords (de::Random rng, vector<deUint8>& coords, size_t offset, size_t size)
99 const deUint8 bits = 2;
100 const deUint8 bitMask = deUint8((0x1u << bits) - 1);
104 for (int i = 0; i < (int)size; i++)
106 const deUint8 xBits = deUint8(rng.getUint32() & bitMask);
107 coords[i] = extend2BitsToByte(xBits);
110 // Fill indices with nice quad
112 const deUint8 indices[] =
114 extend2BitsToByte(0x0u),
115 extend2BitsToByte(0x1u),
116 extend2BitsToByte(0x2u),
117 extend2BitsToByte(0x3u)
120 for (int i = 0; i < DE_LENGTH_OF_ARRAY(indices); i++)
122 const deUint8 index = indices[i];
123 const size_t posX = (size_t(index) * 2) + 0;
124 const size_t posY = (size_t(index) * 2) + 1;
126 if (posX >= offset && posX < offset+size)
127 coords[posX - offset] = ((i % 2) == 0 ? extend2BitsToByte(0x0u) : extend2BitsToByte(0x3u));
129 if (posY >= offset && posY < offset+size)
130 coords[posY - offset] = ((i / 2) == 1 ? extend2BitsToByte(0x3u) : extend2BitsToByte(0x0u));
134 // Fill beginning of buffer
136 const deUint8 indices[] =
138 extend2BitsToByte(0x0u),
139 extend2BitsToByte(0x3u),
140 extend2BitsToByte(0x1u),
142 extend2BitsToByte(0x1u),
143 extend2BitsToByte(0x2u),
144 extend2BitsToByte(0x0u),
146 extend2BitsToByte(0x0u),
147 extend2BitsToByte(0x2u),
148 extend2BitsToByte(0x1u),
150 extend2BitsToByte(0x1u),
151 extend2BitsToByte(0x3u),
152 extend2BitsToByte(0x0u)
155 for (int i = (int)offset; i < DE_LENGTH_OF_ARRAY(indices) && i < (int)(offset + size); i++)
156 coords[i-offset] = indices[i];
160 class CoordVertexShader : public rr::VertexShader
163 CoordVertexShader (void)
164 : rr::VertexShader(1, 1)
166 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
167 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
170 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
172 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
174 rr::VertexPacket* const packet = packets[packetNdx];
177 readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
179 packet->outputs[0] = tcu::Vec4(1.0f);
180 packet->position = tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
185 class TextureVertexShader : public rr::VertexShader
188 TextureVertexShader (const tcu::ConstPixelBufferAccess& texture)
189 : rr::VertexShader (1, 1)
190 , m_texture (texture)
192 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
193 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
196 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
198 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
200 rr::VertexPacket* const packet = packets[packetNdx];
202 tcu::Vec4 texelValue;
204 readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
206 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));
208 packet->outputs[0] = texelValue;
209 packet->position = tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
214 const tcu::ConstPixelBufferAccess& m_texture;
217 class CoordFragmentShader : public rr::FragmentShader
220 CoordFragmentShader (void)
221 : rr::FragmentShader (1, 1)
223 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
224 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
228 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
230 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
232 rr::FragmentPacket& packet = packets[packetNdx];
234 const tcu::Vec4 vtxColor0 = rr::readVarying<float>(packet, context, 0, 0);
235 const tcu::Vec4 vtxColor1 = rr::readVarying<float>(packet, context, 0, 1);
236 const tcu::Vec4 vtxColor2 = rr::readVarying<float>(packet, context, 0, 2);
237 const tcu::Vec4 vtxColor3 = rr::readVarying<float>(packet, context, 0, 3);
239 const tcu::Vec4 color0 = vtxColor0;
240 const tcu::Vec4 color1 = vtxColor1;
241 const tcu::Vec4 color2 = vtxColor2;
242 const tcu::Vec4 color3 = vtxColor3;
244 rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
245 rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
246 rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
247 rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
252 class TextureFragmentShader : public rr::FragmentShader
255 TextureFragmentShader (const tcu::ConstPixelBufferAccess& texture)
256 : rr::FragmentShader (1, 1)
257 , m_texture (texture)
259 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
260 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
263 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
265 for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
267 rr::FragmentPacket& packet = packets[packetNdx];
269 const tcu::IVec2 position0 = packet.position + tcu::IVec2(0, 0);
270 const tcu::IVec2 position1 = packet.position + tcu::IVec2(1, 0);
271 const tcu::IVec2 position2 = packet.position + tcu::IVec2(0, 1);
272 const tcu::IVec2 position3 = packet.position + tcu::IVec2(1, 1);
274 const tcu::Vec4 texColor0 = m_texture.getPixel(de::clamp((position0.x() * position0.y()), 0, m_texture.getWidth()-1), 0);
275 const tcu::Vec4 texColor1 = m_texture.getPixel(de::clamp((position1.x() * position1.y()), 0, m_texture.getWidth()-1), 0);
276 const tcu::Vec4 texColor2 = m_texture.getPixel(de::clamp((position2.x() * position2.y()), 0, m_texture.getWidth()-1), 0);
277 const tcu::Vec4 texColor3 = m_texture.getPixel(de::clamp((position3.x() * position3.y()), 0, m_texture.getWidth()-1), 0);
279 const tcu::Vec4 vtxColor0 = rr::readVarying<float>(packet, context, 0, 0);
280 const tcu::Vec4 vtxColor1 = rr::readVarying<float>(packet, context, 0, 1);
281 const tcu::Vec4 vtxColor2 = rr::readVarying<float>(packet, context, 0, 2);
282 const tcu::Vec4 vtxColor3 = rr::readVarying<float>(packet, context, 0, 3);
284 const tcu::Vec4 color0 = 0.5f * (vtxColor0 + texColor0);
285 const tcu::Vec4 color1 = 0.5f * (vtxColor1 + texColor1);
286 const tcu::Vec4 color2 = 0.5f * (vtxColor2 + texColor2);
287 const tcu::Vec4 color3 = 0.5f * (vtxColor3 + texColor3);
289 rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
290 rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
291 rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
292 rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
297 const tcu::ConstPixelBufferAccess& m_texture;
300 string generateVertexShaderTemplate (RenderBits renderBits)
302 std::ostringstream stream;
305 "${VERSION_HEADER}\n";
307 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
308 stream << "${TEXTURE_BUFFER_EXT}";
311 "${VTX_INPUT} layout(location = 0) ${HIGHP} vec2 i_coord;\n"
312 "${VTX_OUTPUT} ${HIGHP} vec4 v_color;\n";
314 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
317 "uniform ${HIGHP} samplerBuffer u_vtxSampler;\n";
325 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
326 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";
328 stream << "\tv_color = vec4(1.0);\n";
331 "\tgl_Position = vec4(2.0 * (i_coord - vec2(0.5)), 0.0, 1.0);\n"
337 string generateFragmentShaderTemplate (RenderBits renderBits)
339 std::ostringstream stream;
342 "${VERSION_HEADER}\n";
344 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
345 stream << "${TEXTURE_BUFFER_EXT}";
348 "${FRAG_OUTPUT} layout(location = 0) ${HIGHP} vec4 dEQP_FragColor;\n"
349 "${FRAG_INPUT} ${HIGHP} vec4 v_color;\n";
351 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
352 stream << "uniform ${HIGHP} samplerBuffer u_fragSampler;\n";
359 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
360 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";
362 stream << "\t${HIGHP} vec4 color = v_color;\n";
365 "\tdEQP_FragColor = vec4(color.xyz * color.w, 1.0);\n"
371 string specializeShader (const string& shaderTemplateString, glu::GLSLVersion glslVersion)
373 const tcu::StringTemplate shaderTemplate(shaderTemplateString);
374 map<string, string> parameters;
376 parameters["VERSION_HEADER"] = glu::getGLSLVersionDeclaration(glslVersion);
377 parameters["VTX_OUTPUT"] = "out";
378 parameters["VTX_INPUT"] = "in";
379 parameters["FRAG_INPUT"] = "in";
380 parameters["FRAG_OUTPUT"] = "out";
381 parameters["HIGHP"] = (glslVersion == glu::GLSL_VERSION_330 ? "" : "highp");
382 parameters["TEXTURE_BUFFER_EXT"] = (glslVersion == glu::GLSL_VERSION_330 ? "" : "#extension GL_EXT_texture_buffer : enable\n");
384 return shaderTemplate.specialize(parameters);
387 glu::ShaderProgram* createRenderProgram (glu::RenderContext& renderContext,
388 RenderBits renderBits)
390 const string vertexShaderTemplate = generateVertexShaderTemplate(renderBits);
391 const string fragmentShaderTemplate = generateFragmentShaderTemplate(renderBits);
393 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(renderContext.getType());
395 const string vertexShaderSource = specializeShader(vertexShaderTemplate, glslVersion);
396 const string fragmentShaderSource = specializeShader(fragmentShaderTemplate, glslVersion);
398 glu::ShaderProgram* const program = new glu::ShaderProgram(renderContext, glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
403 void logModifications (TestLog& log, ModifyBits modifyBits)
405 tcu::ScopedLogSection section(log, "Modify Operations", "Modify Operations");
413 { MODIFYBITS_BUFFERDATA, "Recreate buffer data with glBufferData()." },
414 { MODIFYBITS_BUFFERSUBDATA, "Modify texture buffer with glBufferSubData()." },
415 { MODIFYBITS_MAPBUFFER_WRITE, "Map buffer write-only and rewrite data." },
416 { MODIFYBITS_MAPBUFFER_READWRITE, "Map buffer readw-write check and rewrite data." }
419 DE_ASSERT(modifyBits != 0);
421 for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
423 if (modifyBits & bitInfos[infoNdx].bit)
424 log << TestLog::Message << bitInfos[infoNdx].str << TestLog::EndMessage;
428 void modifyBufferData (TestLog& log,
430 glu::TextureBuffer& texture)
432 vector<deUint8> data;
434 genRandomCoords(rng, data, 0, texture.getBufferSize());
436 log << TestLog::Message << "BufferData, Size: " << data.size() << TestLog::EndMessage;
438 texture.bufferData(&(data[0]), data.size());
442 void modifyBufferSubData (TestLog& log,
444 const glw::Functions& gl,
445 glu::TextureBuffer& texture)
447 const size_t minSize = 4*16;
448 const size_t size = de::max<size_t>(minSize, size_t((texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7 + 0.3 * rng.getFloat())));
449 const size_t minOffset = texture.getOffset();
450 const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
451 vector<deUint8> data;
453 genRandomCoords(rng, data, offset, size);
455 log << TestLog::Message << "BufferSubData, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
457 gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
458 gl.bufferSubData(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)data.size(), &(data[0]));
459 gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
460 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glBufferSubData()");
462 deMemcpy(texture.getRefBuffer() + offset, &(data[0]), int(data.size()));
465 void modifyMapWrite (TestLog& log,
467 const glw::Functions& gl,
468 glu::TextureBuffer& texture)
470 const size_t minSize = 4*16;
471 const size_t size = de::max<size_t>(minSize, size_t((texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7 + 0.3 * rng.getFloat())));
472 const size_t minOffset = texture.getOffset();
473 const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
474 vector<deUint8> data;
476 genRandomCoords(rng, data, offset, size);
478 log << TestLog::Message << "glMapBufferRange, Write Only, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
480 gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
482 deUint8* ptr = (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT);
484 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
487 for (int i = 0; i < (int)data.size(); i++)
490 TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
492 gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
493 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
495 deMemcpy(texture.getRefBuffer()+offset, &(data[0]), int(data.size()));
498 void modifyMapReadWrite (TestLog& log,
499 tcu::ResultCollector& resultCollector,
501 const glw::Functions& gl,
502 glu::TextureBuffer& texture)
504 const size_t minSize = 4*16;
505 const size_t size = de::max<size_t>(minSize, size_t((texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7 + 0.3 * rng.getFloat())));
506 const size_t minOffset = texture.getOffset();
507 const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
508 vector<deUint8> data;
510 genRandomCoords(rng, data, offset, size);
512 log << TestLog::Message << "glMapBufferRange, Read Write, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
514 gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
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);
519 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
522 for (int i = 0; i < (int)data.size(); i++)
524 if (ptr[i] != texture.getRefBuffer()[offset+i])
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>(texture.getRefBuffer()[i]).toString() << TestLog::EndMessage;
535 TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
537 if (invalidBytes > 0)
539 log << TestLog::Message << "Total of " << invalidBytes << " invalid bytes." << TestLog::EndMessage;
540 resultCollector.fail("Invalid data in mapped buffer");
544 gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
545 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
547 for (int i = 0; i < (int)data.size(); i++)
548 texture.getRefBuffer()[offset+i] = data[i];
551 void modify (TestLog& log,
552 tcu::ResultCollector& resultCollector,
553 glu::RenderContext& renderContext,
554 ModifyBits modifyBits,
556 glu::TextureBuffer& texture)
558 const tcu::ScopedLogSection modifySection(log, "Modifying Texture buffer", "Modifying Texture Buffer");
560 logModifications(log, modifyBits);
562 if (modifyBits & MODIFYBITS_BUFFERDATA)
563 modifyBufferData(log, rng, texture);
565 if (modifyBits & MODIFYBITS_BUFFERSUBDATA)
566 modifyBufferSubData(log, rng, renderContext.getFunctions(), texture);
568 if (modifyBits & MODIFYBITS_MAPBUFFER_WRITE)
569 modifyMapWrite(log, rng, renderContext.getFunctions(), texture);
571 if (modifyBits & MODIFYBITS_MAPBUFFER_READWRITE)
572 modifyMapReadWrite(log, resultCollector, rng, renderContext.getFunctions(), texture);
575 void renderGL (glu::RenderContext& renderContext,
576 RenderBits renderBits,
579 glu::ShaderProgram& program,
580 glu::TextureBuffer& texture)
582 const glw::Functions& gl = renderContext.getFunctions();
583 const glu::VertexArray vao (renderContext);
584 const glu::Buffer coordBuffer (renderContext);
586 gl.useProgram(program.getProgram());
587 gl.bindVertexArray(*vao);
589 gl.enableVertexAttribArray(0);
591 if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
593 gl.bindBuffer(GL_ARRAY_BUFFER, texture.getGLBuffer());
594 gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
598 de::Random rng(coordSeed);
599 vector<deUint8> coords;
601 genRandomCoords(rng, coords, 0, 256*2);
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);
608 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
610 const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_vtxSampler");
612 gl.activeTexture(GL_TEXTURE0);
613 gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
614 gl.uniform1i(location, 0);
617 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
619 const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_fragSampler");
621 gl.activeTexture(GL_TEXTURE1);
622 gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
623 gl.uniform1i(location, 1);
624 gl.activeTexture(GL_TEXTURE0);
627 if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
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);
634 gl.drawArrays(GL_TRIANGLES, 0, triangleCount * 3);
636 if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
638 gl.activeTexture(GL_TEXTURE1);
639 gl.bindTexture(GL_TEXTURE_BUFFER, 0);
642 if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
644 gl.activeTexture(GL_TEXTURE0);
645 gl.bindTexture(GL_TEXTURE_BUFFER, 0);
648 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
649 gl.disableVertexAttribArray(0);
651 gl.bindVertexArray(0);
653 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
656 void renderReference (RenderBits renderBits,
659 glu::TextureBuffer& texture,
660 const tcu::PixelBufferAccess& target)
662 const CoordVertexShader coordVertexShader;
663 const TextureVertexShader textureVertexShader (texture.getRefTexture());
664 const rr::VertexShader* const vertexShader = (renderBits & RENDERBITS_AS_VERTEX_TEXTURE ? static_cast<const rr::VertexShader*>(&textureVertexShader) : &coordVertexShader);
666 const CoordFragmentShader coordFragmmentShader;
667 const TextureFragmentShader textureFragmentShader (texture.getRefTexture());
668 const rr::FragmentShader* const fragmentShader = (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE ? static_cast<const rr::FragmentShader*>(&textureFragmentShader) : &coordFragmmentShader);
670 const rr::Renderer renderer;
671 const rr::RenderState renderState(rr::ViewportState(rr::WindowRectangle(0, 0, target.getWidth(), target.getHeight())));
672 const rr::RenderTarget renderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(target));
674 const rr::Program program(vertexShader, fragmentShader);
676 rr::VertexAttrib vertexAttribs[1];
677 vector<deUint8> coords;
679 if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
681 vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
682 vertexAttribs[0].size = 2;
683 vertexAttribs[0].pointer = texture.getRefBuffer();
687 de::Random rng(coordSeed);
689 genRandomCoords(rng, coords, 0, 256*2);
691 vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
692 vertexAttribs[0].size = 2;
693 vertexAttribs[0].pointer = &(coords[0]);
696 if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
698 const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, rr::DrawIndices((const void*)texture.getRefBuffer(), rr::INDEXTYPE_UINT8));
699 const rr::DrawCommand cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
705 const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, 0);
706 const rr::DrawCommand cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
712 void logRendering (TestLog& log, RenderBits renderBits)
720 { RENDERBITS_AS_VERTEX_ARRAY, "vertex array" },
721 { RENDERBITS_AS_INDEX_ARRAY, "index array" },
722 { RENDERBITS_AS_VERTEX_TEXTURE, "vertex texture" },
723 { RENDERBITS_AS_FRAGMENT_TEXTURE, "fragment texture" }
726 std::ostringstream stream;
727 vector<const char*> usedAs;
729 DE_ASSERT(renderBits != 0);
731 for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
733 if (renderBits & bitInfos[infoNdx].bit)
734 usedAs.push_back(bitInfos[infoNdx].str);
737 stream << "Render using texture buffer as ";
739 for (int asNdx = 0; asNdx < (int)usedAs.size(); asNdx++)
741 if (asNdx+1 == (int)usedAs.size() && (int)usedAs.size() > 1)
746 stream << usedAs[asNdx];
751 log << TestLog::Message << stream.str() << TestLog::EndMessage;
754 void render (TestLog& log,
755 glu::RenderContext& renderContext,
756 RenderBits renderBits,
758 glu::ShaderProgram& program,
759 glu::TextureBuffer& texture,
760 const tcu::PixelBufferAccess& target)
762 const tcu::ScopedLogSection renderSection (log, "Render Texture buffer", "Render Texture Buffer");
763 const int triangleCount = 8;
764 const deUint32 coordSeed = rng.getUint32();
766 logRendering(log, renderBits);
768 renderGL(renderContext, renderBits, coordSeed, triangleCount, program, texture);
769 renderReference(renderBits, coordSeed, triangleCount, texture, target);
772 void verifyScreen (TestLog& log,
773 tcu::ResultCollector& resultCollector,
774 glu::RenderContext& renderContext,
775 const tcu::ConstPixelBufferAccess& referenceTarget)
777 const tcu::ScopedLogSection verifySection (log, "Verify screen contents", "Verify screen contents");
778 tcu::Surface screen (referenceTarget.getWidth(), referenceTarget.getHeight());
780 glu::readPixels(renderContext, 0, 0, screen.getAccess());
782 if (!tcu::fuzzyCompare(log, "Result of rendering", "Result of rendering", referenceTarget, screen.getAccess(), 0.05f, tcu::COMPARE_LOG_RESULT))
783 resultCollector.fail("Rendering failed");
786 void logImplementationInfo (TestLog& log, glu::RenderContext& renderContext)
788 const tcu::ScopedLogSection section (log, "Implementation Values", "Implementation Values");
789 de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(renderContext));
790 const glw::Functions& gl = renderContext.getFunctions();
792 if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)))
794 deInt32 maxTextureSize = 0;
796 gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
797 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE)");
799 log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE : " << maxTextureSize << TestLog::EndMessage;
801 else if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer"))
804 deInt32 maxTextureSize = 0;
806 gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
807 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE_EXT)");
809 log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE_EXT : " << maxTextureSize << TestLog::EndMessage;
813 deInt32 textureBufferAlignment = 0;
815 gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &textureBufferAlignment);
816 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT)");
818 log << TestLog::Message << "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT : " << textureBufferAlignment << TestLog::EndMessage;
825 void logTextureInfo (TestLog& log,
831 const tcu::ScopedLogSection section(log, "Texture Info", "Texture Info");
833 log << TestLog::Message << "Texture format : " << glu::getPixelFormatStr(format) << TestLog::EndMessage;
834 log << TestLog::Message << "Buffer size : " << bufferSize << TestLog::EndMessage;
836 if (offset != 0 || size != 0)
838 log << TestLog::Message << "Buffer range offset: " << offset << TestLog::EndMessage;
839 log << TestLog::Message << "Buffer range size: " << size << TestLog::EndMessage;
843 void runTests (tcu::TestContext& testCtx,
844 glu::RenderContext& renderContext,
850 RenderBits preRender,
851 glu::ShaderProgram* preRenderProgram,
852 ModifyBits modifyType,
853 RenderBits postRender,
854 glu::ShaderProgram* postRenderProgram)
856 const tcu::RenderTarget renderTarget (renderContext.getRenderTarget());
857 const glw::Functions& gl = renderContext.getFunctions();
859 const int width = de::min<int>(renderTarget.getWidth(), MAX_VIEWPORT_WIDTH);
860 const int height = de::min<int>(renderTarget.getHeight(), MAX_VIEWPORT_HEIGHT);
861 const tcu::Vec4 clearColor (0.25f, 0.5f, 0.75f, 1.0f);
863 TestLog& log = testCtx.getLog();
864 tcu::ResultCollector resultCollector (log);
866 logImplementationInfo(log, renderContext);
867 logTextureInfo(log, format, bufferSize, offset, size);
870 tcu::Surface referenceTarget (width, height);
871 vector<deUint8> bufferData;
873 genRandomCoords(rng, bufferData, 0, bufferSize);
875 for (deUint8 i = 0; i < 4; i++)
877 const deUint8 val = extend2BitsToByte(i);
879 if (val >= offset && val < offset + size)
881 bufferData[val*2 + 0] = (i / 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
882 bufferData[val*2 + 1] = (i % 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
887 glu::TextureBuffer texture (renderContext, format, bufferSize, offset, size, &(bufferData[0]));
889 TCU_CHECK_MSG(width >= MIN_VIEWPORT_WIDTH || height >= MIN_VIEWPORT_HEIGHT, "Too small viewport");
891 DE_ASSERT(preRender == 0 || preRenderProgram);
892 DE_ASSERT(postRender == 0 || postRenderProgram);
894 gl.viewport(0, 0, width, height);
895 gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
896 gl.clear(GL_COLOR_BUFFER_BIT);
897 GLU_EXPECT_NO_ERROR(gl.getError(), "Screen setup failed");
899 tcu::clear(referenceTarget.getAccess(), clearColor);
904 render(log, renderContext, preRender, rng, *preRenderProgram, texture, referenceTarget.getAccess());
907 modify(log, resultCollector, renderContext, modifyType, rng, texture);
910 render(log, renderContext, postRender, rng, *postRenderProgram, texture, referenceTarget.getAccess());
913 verifyScreen(log, resultCollector, renderContext, referenceTarget.getAccess());
915 resultCollector.setTestContextResult(testCtx);
921 TextureBufferCase::TextureBufferCase (tcu::TestContext& testCtx,
922 glu::RenderContext& renderCtx,
927 RenderBits preRender,
929 RenderBits postRender,
931 const char* description)
932 : tcu::TestCase (testCtx, name, description)
933 , m_renderCtx (renderCtx)
935 , m_bufferSize (bufferSize)
939 , m_preRender (preRender)
941 , m_postRender (postRender)
943 , m_preRenderProgram (DE_NULL)
944 , m_postRenderProgram (DE_NULL)
948 TextureBufferCase::~TextureBufferCase (void)
950 TextureBufferCase::deinit();
953 void TextureBufferCase::init (void)
955 de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(m_renderCtx));
957 if (!glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
958 && !(glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer")))
959 throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
961 if (m_preRender != 0)
963 TestLog& log = m_testCtx.getLog();
964 const char* const sectionName = (m_postRender != 0 ? "Primary render program" : "Render program");
965 const tcu::ScopedLogSection section (log, sectionName, sectionName);
967 m_preRenderProgram = createRenderProgram(m_renderCtx, m_preRender);
968 m_testCtx.getLog() << (*m_preRenderProgram);
970 TCU_CHECK(m_preRenderProgram->isOk());
973 if (m_postRender != 0)
976 if (m_preRender == m_postRender)
978 m_postRenderProgram = m_preRenderProgram;
982 TestLog& log = m_testCtx.getLog();
983 const char* const sectionName = (m_preRender!= 0 ? "Secondary render program" : "Render program");
984 const tcu::ScopedLogSection section (log, sectionName, sectionName);
986 m_postRenderProgram = createRenderProgram(m_renderCtx, m_postRender);
987 m_testCtx.getLog() << (*m_postRenderProgram);
989 TCU_CHECK(m_postRenderProgram->isOk());
994 void TextureBufferCase::deinit (void)
996 if (m_preRenderProgram == m_postRenderProgram)
997 m_postRenderProgram = DE_NULL;
999 delete m_preRenderProgram;
1000 m_preRenderProgram = DE_NULL;
1002 delete m_postRenderProgram;
1003 m_postRenderProgram = DE_NULL;
1006 tcu::TestCase::IterateResult TextureBufferCase::iterate (void)
1008 de::Random rng (deInt32Hash(deStringHash(getName())));
1013 const glw::Functions& gl = m_renderCtx.getFunctions();
1014 deInt32 alignment = 0;
1016 gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &alignment);
1017 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT)");
1019 offset = m_offset * alignment;
1024 runTests(m_testCtx, m_renderCtx, rng, m_format, m_bufferSize, offset, m_size, m_preRender, m_preRenderProgram, m_modify, m_postRender, m_postRenderProgram);