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