1049 lines
34 KiB
C++
1049 lines
34 KiB
C++
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL (ES) Module
|
|
* -----------------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Texture buffer test case
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "glsTextureBufferCase.hpp"
|
|
|
|
#include "tcuFormatUtil.hpp"
|
|
#include "tcuImageCompare.hpp"
|
|
#include "tcuRenderTarget.hpp"
|
|
#include "tcuStringTemplate.hpp"
|
|
#include "tcuSurface.hpp"
|
|
#include "tcuTestLog.hpp"
|
|
#include "tcuTextureUtil.hpp"
|
|
#include "tcuResultCollector.hpp"
|
|
|
|
#include "rrRenderer.hpp"
|
|
#include "rrShaders.hpp"
|
|
|
|
#include "gluObjectWrapper.hpp"
|
|
#include "gluPixelTransfer.hpp"
|
|
#include "gluShaderProgram.hpp"
|
|
#include "gluShaderUtil.hpp"
|
|
#include "gluStrUtil.hpp"
|
|
#include "gluTexture.hpp"
|
|
#include "gluTextureUtil.hpp"
|
|
|
|
#include "glwEnums.hpp"
|
|
#include "glwFunctions.hpp"
|
|
|
|
#include "deRandom.hpp"
|
|
#include "deStringUtil.hpp"
|
|
#include "deUniquePtr.hpp"
|
|
|
|
#include "deMemory.h"
|
|
#include "deString.h"
|
|
#include "deMath.h"
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
using tcu::TestLog;
|
|
|
|
using std::map;
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
using namespace deqp::gls::TextureBufferCaseUtil;
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gls
|
|
{
|
|
namespace
|
|
{
|
|
|
|
enum
|
|
{
|
|
MAX_VIEWPORT_WIDTH = 256,
|
|
MAX_VIEWPORT_HEIGHT = 256,
|
|
MIN_VIEWPORT_WIDTH = 64,
|
|
MIN_VIEWPORT_HEIGHT = 64,
|
|
};
|
|
|
|
deUint8 extend2BitsToByte (deUint8 bits)
|
|
{
|
|
DE_ASSERT((bits & (~0x03u)) == 0);
|
|
|
|
return (deUint8)(bits | (bits << 2) | (bits << 4) | (bits << 6));
|
|
}
|
|
|
|
void genRandomCoords (de::Random rng, vector<deUint8>& coords, size_t offset, size_t size)
|
|
{
|
|
const deUint8 bits = 2;
|
|
const deUint8 bitMask = deUint8((0x1u << bits) - 1);
|
|
|
|
coords.resize(size);
|
|
|
|
for (int i = 0; i < (int)size; i++)
|
|
{
|
|
const deUint8 xBits = deUint8(rng.getUint32() & bitMask);
|
|
coords[i] = extend2BitsToByte(xBits);
|
|
}
|
|
|
|
// Fill indices with nice quad
|
|
{
|
|
const deUint8 indices[] =
|
|
{
|
|
extend2BitsToByte(0x0u),
|
|
extend2BitsToByte(0x1u),
|
|
extend2BitsToByte(0x2u),
|
|
extend2BitsToByte(0x3u)
|
|
};
|
|
|
|
for (int i = 0; i < DE_LENGTH_OF_ARRAY(indices); i++)
|
|
{
|
|
const deUint8 index = indices[i];
|
|
const size_t posX = (size_t(index) * 2) + 0;
|
|
const size_t posY = (size_t(index) * 2) + 1;
|
|
|
|
if (posX >= offset && posX < offset+size)
|
|
coords[posX - offset] = ((i % 2) == 0 ? extend2BitsToByte(0x0u) : extend2BitsToByte(0x3u));
|
|
|
|
if (posY >= offset && posY < offset+size)
|
|
coords[posY - offset] = ((i / 2) == 1 ? extend2BitsToByte(0x3u) : extend2BitsToByte(0x0u));
|
|
}
|
|
}
|
|
|
|
// Fill beginning of buffer
|
|
{
|
|
const deUint8 indices[] =
|
|
{
|
|
extend2BitsToByte(0x0u),
|
|
extend2BitsToByte(0x3u),
|
|
extend2BitsToByte(0x1u),
|
|
|
|
extend2BitsToByte(0x1u),
|
|
extend2BitsToByte(0x2u),
|
|
extend2BitsToByte(0x0u),
|
|
|
|
extend2BitsToByte(0x0u),
|
|
extend2BitsToByte(0x2u),
|
|
extend2BitsToByte(0x1u),
|
|
|
|
extend2BitsToByte(0x1u),
|
|
extend2BitsToByte(0x3u),
|
|
extend2BitsToByte(0x0u)
|
|
};
|
|
|
|
for (int i = (int)offset; i < DE_LENGTH_OF_ARRAY(indices) && i < (int)(offset + size); i++)
|
|
coords[i-offset] = indices[i];
|
|
}
|
|
}
|
|
|
|
class CoordVertexShader : public rr::VertexShader
|
|
{
|
|
public:
|
|
CoordVertexShader (void)
|
|
: rr::VertexShader(1, 1)
|
|
{
|
|
m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
}
|
|
|
|
void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
|
|
{
|
|
rr::VertexPacket* const packet = packets[packetNdx];
|
|
tcu::Vec4 position;
|
|
|
|
readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
|
|
|
|
packet->outputs[0] = tcu::Vec4(1.0f);
|
|
packet->position = tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
|
|
}
|
|
}
|
|
};
|
|
|
|
class TextureVertexShader : public rr::VertexShader
|
|
{
|
|
public:
|
|
TextureVertexShader (const tcu::ConstPixelBufferAccess& texture)
|
|
: rr::VertexShader (1, 1)
|
|
, m_texture (texture)
|
|
{
|
|
m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
}
|
|
|
|
void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
|
|
{
|
|
rr::VertexPacket* const packet = packets[packetNdx];
|
|
tcu::Vec4 position;
|
|
tcu::Vec4 texelValue;
|
|
|
|
readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
|
|
|
|
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));
|
|
|
|
packet->outputs[0] = texelValue;
|
|
packet->position = tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
|
|
}
|
|
}
|
|
|
|
private:
|
|
const tcu::ConstPixelBufferAccess m_texture;
|
|
};
|
|
|
|
class CoordFragmentShader : public rr::FragmentShader
|
|
{
|
|
public:
|
|
CoordFragmentShader (void)
|
|
: rr::FragmentShader (1, 1)
|
|
{
|
|
m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
}
|
|
|
|
|
|
void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
|
|
{
|
|
rr::FragmentPacket& packet = packets[packetNdx];
|
|
|
|
const tcu::Vec4 vtxColor0 = rr::readVarying<float>(packet, context, 0, 0);
|
|
const tcu::Vec4 vtxColor1 = rr::readVarying<float>(packet, context, 0, 1);
|
|
const tcu::Vec4 vtxColor2 = rr::readVarying<float>(packet, context, 0, 2);
|
|
const tcu::Vec4 vtxColor3 = rr::readVarying<float>(packet, context, 0, 3);
|
|
|
|
const tcu::Vec4 color0 = vtxColor0;
|
|
const tcu::Vec4 color1 = vtxColor1;
|
|
const tcu::Vec4 color2 = vtxColor2;
|
|
const tcu::Vec4 color3 = vtxColor3;
|
|
|
|
rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
|
|
rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
|
|
rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
|
|
rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
|
|
}
|
|
}
|
|
};
|
|
|
|
class TextureFragmentShader : public rr::FragmentShader
|
|
{
|
|
public:
|
|
TextureFragmentShader (const tcu::ConstPixelBufferAccess& texture)
|
|
: rr::FragmentShader (1, 1)
|
|
, m_texture (texture)
|
|
{
|
|
m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
|
|
}
|
|
|
|
void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
|
|
{
|
|
rr::FragmentPacket& packet = packets[packetNdx];
|
|
|
|
const tcu::IVec2 position0 = packet.position + tcu::IVec2(0, 0);
|
|
const tcu::IVec2 position1 = packet.position + tcu::IVec2(1, 0);
|
|
const tcu::IVec2 position2 = packet.position + tcu::IVec2(0, 1);
|
|
const tcu::IVec2 position3 = packet.position + tcu::IVec2(1, 1);
|
|
|
|
const tcu::Vec4 texColor0 = m_texture.getPixel(de::clamp((position0.x() * position0.y()), 0, m_texture.getWidth()-1), 0);
|
|
const tcu::Vec4 texColor1 = m_texture.getPixel(de::clamp((position1.x() * position1.y()), 0, m_texture.getWidth()-1), 0);
|
|
const tcu::Vec4 texColor2 = m_texture.getPixel(de::clamp((position2.x() * position2.y()), 0, m_texture.getWidth()-1), 0);
|
|
const tcu::Vec4 texColor3 = m_texture.getPixel(de::clamp((position3.x() * position3.y()), 0, m_texture.getWidth()-1), 0);
|
|
|
|
const tcu::Vec4 vtxColor0 = rr::readVarying<float>(packet, context, 0, 0);
|
|
const tcu::Vec4 vtxColor1 = rr::readVarying<float>(packet, context, 0, 1);
|
|
const tcu::Vec4 vtxColor2 = rr::readVarying<float>(packet, context, 0, 2);
|
|
const tcu::Vec4 vtxColor3 = rr::readVarying<float>(packet, context, 0, 3);
|
|
|
|
const tcu::Vec4 color0 = 0.5f * (vtxColor0 + texColor0);
|
|
const tcu::Vec4 color1 = 0.5f * (vtxColor1 + texColor1);
|
|
const tcu::Vec4 color2 = 0.5f * (vtxColor2 + texColor2);
|
|
const tcu::Vec4 color3 = 0.5f * (vtxColor3 + texColor3);
|
|
|
|
rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
|
|
rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
|
|
rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
|
|
rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
|
|
}
|
|
}
|
|
|
|
private:
|
|
const tcu::ConstPixelBufferAccess m_texture;
|
|
};
|
|
|
|
string generateVertexShaderTemplate (RenderBits renderBits)
|
|
{
|
|
std::ostringstream stream;
|
|
|
|
stream <<
|
|
"${VERSION_HEADER}\n";
|
|
|
|
if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
|
|
stream << "${TEXTURE_BUFFER_EXT}";
|
|
|
|
stream <<
|
|
"${VTX_INPUT} layout(location = 0) ${HIGHP} vec2 i_coord;\n"
|
|
"${VTX_OUTPUT} ${HIGHP} vec4 v_color;\n";
|
|
|
|
if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
|
|
{
|
|
stream <<
|
|
"uniform ${HIGHP} samplerBuffer u_vtxSampler;\n";
|
|
}
|
|
|
|
stream <<
|
|
"\n"
|
|
"void main (void)\n"
|
|
"{\n";
|
|
|
|
if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
|
|
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";
|
|
else
|
|
stream << "\tv_color = vec4(1.0);\n";
|
|
|
|
stream <<
|
|
"\tgl_Position = vec4(2.0 * (i_coord - vec2(0.5)), 0.0, 1.0);\n"
|
|
"}\n";
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
string generateFragmentShaderTemplate (RenderBits renderBits)
|
|
{
|
|
std::ostringstream stream;
|
|
|
|
stream <<
|
|
"${VERSION_HEADER}\n";
|
|
|
|
if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
|
|
stream << "${TEXTURE_BUFFER_EXT}";
|
|
|
|
stream <<
|
|
"${FRAG_OUTPUT} layout(location = 0) ${HIGHP} vec4 dEQP_FragColor;\n"
|
|
"${FRAG_INPUT} ${HIGHP} vec4 v_color;\n";
|
|
|
|
if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
|
|
stream << "uniform ${HIGHP} samplerBuffer u_fragSampler;\n";
|
|
|
|
stream <<
|
|
"\n"
|
|
"void main (void)\n"
|
|
"{\n";
|
|
|
|
if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
|
|
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";
|
|
else
|
|
stream << "\t${HIGHP} vec4 color = v_color;\n";
|
|
|
|
stream <<
|
|
"\tdEQP_FragColor = vec4(color.xyz * color.w, 1.0);\n"
|
|
"}\n";
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
string specializeShader (const string& shaderTemplateString, glu::GLSLVersion glslVersion)
|
|
{
|
|
const tcu::StringTemplate shaderTemplate(shaderTemplateString);
|
|
map<string, string> parameters;
|
|
|
|
parameters["VERSION_HEADER"] = glu::getGLSLVersionDeclaration(glslVersion);
|
|
parameters["VTX_OUTPUT"] = "out";
|
|
parameters["VTX_INPUT"] = "in";
|
|
parameters["FRAG_INPUT"] = "in";
|
|
parameters["FRAG_OUTPUT"] = "out";
|
|
parameters["HIGHP"] = (glslVersion == glu::GLSL_VERSION_330 ? "" : "highp");
|
|
parameters["TEXTURE_BUFFER_EXT"] = (glslVersion == glu::GLSL_VERSION_330 ? "" : "#extension GL_EXT_texture_buffer : enable\n");
|
|
|
|
return shaderTemplate.specialize(parameters);
|
|
}
|
|
|
|
glu::ShaderProgram* createRenderProgram (glu::RenderContext& renderContext,
|
|
RenderBits renderBits)
|
|
{
|
|
const string vertexShaderTemplate = generateVertexShaderTemplate(renderBits);
|
|
const string fragmentShaderTemplate = generateFragmentShaderTemplate(renderBits);
|
|
|
|
const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(renderContext.getType());
|
|
|
|
const string vertexShaderSource = specializeShader(vertexShaderTemplate, glslVersion);
|
|
const string fragmentShaderSource = specializeShader(fragmentShaderTemplate, glslVersion);
|
|
|
|
glu::ShaderProgram* const program = new glu::ShaderProgram(renderContext, glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
|
|
|
|
return program;
|
|
}
|
|
|
|
void logModifications (TestLog& log, ModifyBits modifyBits)
|
|
{
|
|
tcu::ScopedLogSection section(log, "Modify Operations", "Modify Operations");
|
|
|
|
const struct
|
|
{
|
|
ModifyBits bit;
|
|
const char* str;
|
|
} bitInfos[] =
|
|
{
|
|
{ MODIFYBITS_BUFFERDATA, "Recreate buffer data with glBufferData()." },
|
|
{ MODIFYBITS_BUFFERSUBDATA, "Modify texture buffer with glBufferSubData()." },
|
|
{ MODIFYBITS_MAPBUFFER_WRITE, "Map buffer write-only and rewrite data." },
|
|
{ MODIFYBITS_MAPBUFFER_READWRITE, "Map buffer readw-write check and rewrite data." }
|
|
};
|
|
|
|
DE_ASSERT(modifyBits != 0);
|
|
|
|
for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
|
|
{
|
|
if (modifyBits & bitInfos[infoNdx].bit)
|
|
log << TestLog::Message << bitInfos[infoNdx].str << TestLog::EndMessage;
|
|
}
|
|
}
|
|
|
|
void modifyBufferData (TestLog& log,
|
|
de::Random& rng,
|
|
glu::TextureBuffer& texture)
|
|
{
|
|
vector<deUint8> data;
|
|
|
|
genRandomCoords(rng, data, 0, texture.getBufferSize());
|
|
|
|
log << TestLog::Message << "BufferData, Size: " << data.size() << TestLog::EndMessage;
|
|
|
|
{
|
|
// replace getRefBuffer with a new buffer
|
|
de::ArrayBuffer<deUint8> buffer(&(data[0]), data.size());
|
|
texture.getRefBuffer().swap(buffer);
|
|
}
|
|
|
|
texture.upload();
|
|
}
|
|
|
|
void modifyBufferSubData (TestLog& log,
|
|
de::Random& rng,
|
|
const glw::Functions& gl,
|
|
glu::TextureBuffer& texture)
|
|
{
|
|
const size_t minSize = 4*16;
|
|
const size_t size = de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
|
|
const size_t minOffset = texture.getOffset();
|
|
const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
|
|
vector<deUint8> data;
|
|
|
|
genRandomCoords(rng, data, offset, size);
|
|
|
|
log << TestLog::Message << "BufferSubData, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
|
|
|
|
gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
|
|
gl.bufferSubData(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)data.size(), &(data[0]));
|
|
gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glBufferSubData()");
|
|
|
|
deMemcpy((deUint8*)texture.getRefBuffer().getPtr() + offset, &(data[0]), int(data.size()));
|
|
}
|
|
|
|
void modifyMapWrite (TestLog& log,
|
|
de::Random& rng,
|
|
const glw::Functions& gl,
|
|
glu::TextureBuffer& texture)
|
|
{
|
|
const size_t minSize = 4*16;
|
|
const size_t size = de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
|
|
const size_t minOffset = texture.getOffset();
|
|
const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
|
|
vector<deUint8> data;
|
|
|
|
genRandomCoords(rng, data, offset, size);
|
|
|
|
log << TestLog::Message << "glMapBufferRange, Write Only, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
|
|
|
|
gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
|
|
{
|
|
deUint8* ptr = (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT);
|
|
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
|
|
TCU_CHECK(ptr);
|
|
|
|
for (int i = 0; i < (int)data.size(); i++)
|
|
ptr[i] = data[i];
|
|
|
|
TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
|
|
}
|
|
gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
|
|
|
|
deMemcpy((deUint8*)texture.getRefBuffer().getPtr()+offset, &(data[0]), int(data.size()));
|
|
}
|
|
|
|
void modifyMapReadWrite (TestLog& log,
|
|
tcu::ResultCollector& resultCollector,
|
|
de::Random& rng,
|
|
const glw::Functions& gl,
|
|
glu::TextureBuffer& texture)
|
|
{
|
|
const size_t minSize = 4*16;
|
|
const size_t size = de::max<size_t>(minSize, size_t((float)(texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7f + 0.3f * rng.getFloat())));
|
|
const size_t minOffset = texture.getOffset();
|
|
const size_t offset = minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
|
|
deUint8* const refPtr = (deUint8*)texture.getRefBuffer().getPtr() + offset;
|
|
vector<deUint8> data;
|
|
|
|
genRandomCoords(rng, data, offset, size);
|
|
|
|
log << TestLog::Message << "glMapBufferRange, Read Write, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
|
|
|
|
gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
|
|
{
|
|
size_t invalidBytes = 0;
|
|
deUint8* const ptr = (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT|GL_MAP_READ_BIT);
|
|
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
|
|
TCU_CHECK(ptr);
|
|
|
|
for (int i = 0; i < (int)data.size(); i++)
|
|
{
|
|
if (ptr[i] != refPtr[i])
|
|
{
|
|
if (invalidBytes < 24)
|
|
log << TestLog::Message << "Invalid byte in mapped buffer. " << tcu::Format::Hex<2>(data[i]).toString() << " at " << i << ", expected " << tcu::Format::Hex<2>(refPtr[i]).toString() << TestLog::EndMessage;
|
|
|
|
invalidBytes++;
|
|
}
|
|
|
|
ptr[i] = data[i];
|
|
}
|
|
|
|
TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
|
|
|
|
if (invalidBytes > 0)
|
|
{
|
|
log << TestLog::Message << "Total of " << invalidBytes << " invalid bytes." << TestLog::EndMessage;
|
|
resultCollector.fail("Invalid data in mapped buffer");
|
|
}
|
|
}
|
|
|
|
gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
|
|
|
|
for (int i = 0; i < (int)data.size(); i++)
|
|
refPtr[i] = data[i];
|
|
}
|
|
|
|
void modify (TestLog& log,
|
|
tcu::ResultCollector& resultCollector,
|
|
glu::RenderContext& renderContext,
|
|
ModifyBits modifyBits,
|
|
de::Random& rng,
|
|
glu::TextureBuffer& texture)
|
|
{
|
|
const tcu::ScopedLogSection modifySection(log, "Modifying Texture buffer", "Modifying Texture Buffer");
|
|
|
|
logModifications(log, modifyBits);
|
|
|
|
if (modifyBits & MODIFYBITS_BUFFERDATA)
|
|
modifyBufferData(log, rng, texture);
|
|
|
|
if (modifyBits & MODIFYBITS_BUFFERSUBDATA)
|
|
modifyBufferSubData(log, rng, renderContext.getFunctions(), texture);
|
|
|
|
if (modifyBits & MODIFYBITS_MAPBUFFER_WRITE)
|
|
modifyMapWrite(log, rng, renderContext.getFunctions(), texture);
|
|
|
|
if (modifyBits & MODIFYBITS_MAPBUFFER_READWRITE)
|
|
modifyMapReadWrite(log, resultCollector, rng, renderContext.getFunctions(), texture);
|
|
}
|
|
|
|
void renderGL (glu::RenderContext& renderContext,
|
|
RenderBits renderBits,
|
|
deUint32 coordSeed,
|
|
int triangleCount,
|
|
glu::ShaderProgram& program,
|
|
glu::TextureBuffer& texture)
|
|
{
|
|
const glw::Functions& gl = renderContext.getFunctions();
|
|
const glu::VertexArray vao (renderContext);
|
|
const glu::Buffer coordBuffer (renderContext);
|
|
|
|
gl.useProgram(program.getProgram());
|
|
gl.bindVertexArray(*vao);
|
|
|
|
gl.enableVertexAttribArray(0);
|
|
|
|
if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
|
|
{
|
|
gl.bindBuffer(GL_ARRAY_BUFFER, texture.getGLBuffer());
|
|
gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
|
|
}
|
|
else
|
|
{
|
|
de::Random rng(coordSeed);
|
|
vector<deUint8> coords;
|
|
|
|
genRandomCoords(rng, coords, 0, 256*2);
|
|
|
|
gl.bindBuffer(GL_ARRAY_BUFFER, *coordBuffer);
|
|
gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)coords.size(), &(coords[0]), GL_STREAM_DRAW);
|
|
gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
|
|
}
|
|
|
|
if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
|
|
{
|
|
const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_vtxSampler");
|
|
|
|
gl.activeTexture(GL_TEXTURE0);
|
|
gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
|
|
gl.uniform1i(location, 0);
|
|
}
|
|
|
|
if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
|
|
{
|
|
const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_fragSampler");
|
|
|
|
gl.activeTexture(GL_TEXTURE1);
|
|
gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
|
|
gl.uniform1i(location, 1);
|
|
gl.activeTexture(GL_TEXTURE0);
|
|
}
|
|
|
|
if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
|
|
{
|
|
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, texture.getGLBuffer());
|
|
gl.drawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_BYTE, DE_NULL);
|
|
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
}
|
|
else
|
|
gl.drawArrays(GL_TRIANGLES, 0, triangleCount * 3);
|
|
|
|
if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
|
|
{
|
|
gl.activeTexture(GL_TEXTURE1);
|
|
gl.bindTexture(GL_TEXTURE_BUFFER, 0);
|
|
}
|
|
|
|
if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
|
|
{
|
|
gl.activeTexture(GL_TEXTURE0);
|
|
gl.bindTexture(GL_TEXTURE_BUFFER, 0);
|
|
}
|
|
|
|
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
|
|
gl.disableVertexAttribArray(0);
|
|
|
|
gl.bindVertexArray(0);
|
|
gl.useProgram(0);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
|
|
}
|
|
|
|
void renderReference (RenderBits renderBits,
|
|
deUint32 coordSeed,
|
|
int triangleCount,
|
|
const glu::TextureBuffer& texture,
|
|
int maxTextureBufferSize,
|
|
const tcu::PixelBufferAccess& target,
|
|
int subpixelBits)
|
|
{
|
|
const tcu::ConstPixelBufferAccess effectiveAccess = glu::getTextureBufferEffectiveRefTexture(texture, maxTextureBufferSize);
|
|
|
|
const CoordVertexShader coordVertexShader;
|
|
const TextureVertexShader textureVertexShader (effectiveAccess);
|
|
const rr::VertexShader* const vertexShader = (renderBits & RENDERBITS_AS_VERTEX_TEXTURE ? static_cast<const rr::VertexShader*>(&textureVertexShader) : &coordVertexShader);
|
|
|
|
const CoordFragmentShader coordFragmmentShader;
|
|
const TextureFragmentShader textureFragmentShader (effectiveAccess);
|
|
const rr::FragmentShader* const fragmentShader = (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE ? static_cast<const rr::FragmentShader*>(&textureFragmentShader) : &coordFragmmentShader);
|
|
|
|
const rr::Renderer renderer;
|
|
const rr::RenderState renderState(rr::ViewportState(rr::WindowRectangle(0, 0, target.getWidth(), target.getHeight())), subpixelBits);
|
|
const rr::RenderTarget renderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(target));
|
|
|
|
const rr::Program program(vertexShader, fragmentShader);
|
|
|
|
rr::VertexAttrib vertexAttribs[1];
|
|
vector<deUint8> coords;
|
|
|
|
if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
|
|
{
|
|
vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
|
|
vertexAttribs[0].size = 2;
|
|
vertexAttribs[0].pointer = texture.getRefBuffer().getPtr();
|
|
}
|
|
else
|
|
{
|
|
de::Random rng(coordSeed);
|
|
|
|
genRandomCoords(rng, coords, 0, 256*2);
|
|
|
|
vertexAttribs[0].type = rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
|
|
vertexAttribs[0].size = 2;
|
|
vertexAttribs[0].pointer = &(coords[0]);
|
|
}
|
|
|
|
if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
|
|
{
|
|
const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, rr::DrawIndices(texture.getRefBuffer().getPtr(), rr::INDEXTYPE_UINT8));
|
|
const rr::DrawCommand cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
|
|
|
|
renderer.draw(cmd);
|
|
}
|
|
else
|
|
{
|
|
const rr::PrimitiveList primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, 0);
|
|
const rr::DrawCommand cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
|
|
|
|
renderer.draw(cmd);
|
|
}
|
|
}
|
|
|
|
void logRendering (TestLog& log, RenderBits renderBits)
|
|
{
|
|
const struct
|
|
{
|
|
RenderBits bit;
|
|
const char* str;
|
|
} bitInfos[] =
|
|
{
|
|
{ RENDERBITS_AS_VERTEX_ARRAY, "vertex array" },
|
|
{ RENDERBITS_AS_INDEX_ARRAY, "index array" },
|
|
{ RENDERBITS_AS_VERTEX_TEXTURE, "vertex texture" },
|
|
{ RENDERBITS_AS_FRAGMENT_TEXTURE, "fragment texture" }
|
|
};
|
|
|
|
std::ostringstream stream;
|
|
vector<const char*> usedAs;
|
|
|
|
DE_ASSERT(renderBits != 0);
|
|
|
|
for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
|
|
{
|
|
if (renderBits & bitInfos[infoNdx].bit)
|
|
usedAs.push_back(bitInfos[infoNdx].str);
|
|
}
|
|
|
|
stream << "Render using texture buffer as ";
|
|
|
|
for (int asNdx = 0; asNdx < (int)usedAs.size(); asNdx++)
|
|
{
|
|
if (asNdx+1 == (int)usedAs.size() && (int)usedAs.size() > 1)
|
|
stream << " and ";
|
|
else if (asNdx > 0)
|
|
stream << ", ";
|
|
|
|
stream << usedAs[asNdx];
|
|
}
|
|
|
|
stream << ".";
|
|
|
|
log << TestLog::Message << stream.str() << TestLog::EndMessage;
|
|
}
|
|
|
|
void render (TestLog& log,
|
|
glu::RenderContext& renderContext,
|
|
RenderBits renderBits,
|
|
de::Random& rng,
|
|
glu::ShaderProgram& program,
|
|
glu::TextureBuffer& texture,
|
|
const tcu::PixelBufferAccess& target)
|
|
{
|
|
const tcu::ScopedLogSection renderSection (log, "Render Texture buffer", "Render Texture Buffer");
|
|
const int triangleCount = 8;
|
|
const deUint32 coordSeed = rng.getUint32();
|
|
int maxTextureBufferSize = 0;
|
|
|
|
renderContext.getFunctions().getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize);
|
|
GLU_EXPECT_NO_ERROR(renderContext.getFunctions().getError(), "query GL_MAX_TEXTURE_BUFFER_SIZE");
|
|
DE_ASSERT(maxTextureBufferSize > 0); // checked in init()
|
|
|
|
logRendering(log, renderBits);
|
|
|
|
renderGL(renderContext, renderBits, coordSeed, triangleCount, program, texture);
|
|
|
|
int subpixelBits = 0;
|
|
renderContext.getFunctions().getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
|
|
renderReference(renderBits, coordSeed, triangleCount, texture, maxTextureBufferSize, target, subpixelBits);
|
|
}
|
|
|
|
void verifyScreen (TestLog& log,
|
|
tcu::ResultCollector& resultCollector,
|
|
glu::RenderContext& renderContext,
|
|
const tcu::ConstPixelBufferAccess& referenceTarget)
|
|
{
|
|
const tcu::ScopedLogSection verifySection (log, "Verify screen contents", "Verify screen contents");
|
|
tcu::Surface screen (referenceTarget.getWidth(), referenceTarget.getHeight());
|
|
|
|
glu::readPixels(renderContext, 0, 0, screen.getAccess());
|
|
|
|
if (!tcu::fuzzyCompare(log, "Result of rendering", "Result of rendering", referenceTarget, screen.getAccess(), 0.05f, tcu::COMPARE_LOG_RESULT))
|
|
resultCollector.fail("Rendering failed");
|
|
}
|
|
|
|
void logImplementationInfo (TestLog& log, glu::RenderContext& renderContext)
|
|
{
|
|
const tcu::ScopedLogSection section (log, "Implementation Values", "Implementation Values");
|
|
de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(renderContext));
|
|
const glw::Functions& gl = renderContext.getFunctions();
|
|
|
|
if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)))
|
|
{
|
|
deInt32 maxTextureSize = 0;
|
|
|
|
gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE)");
|
|
|
|
log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE : " << maxTextureSize << TestLog::EndMessage;
|
|
}
|
|
else if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer"))
|
|
{
|
|
{
|
|
deInt32 maxTextureSize = 0;
|
|
|
|
gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE_EXT)");
|
|
|
|
log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE_EXT : " << maxTextureSize << TestLog::EndMessage;
|
|
}
|
|
|
|
{
|
|
deInt32 textureBufferAlignment = 0;
|
|
|
|
gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &textureBufferAlignment);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT)");
|
|
|
|
log << TestLog::Message << "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT : " << textureBufferAlignment << TestLog::EndMessage;
|
|
}
|
|
}
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
|
|
void logTextureInfo (TestLog& log,
|
|
deUint32 format,
|
|
size_t bufferSize,
|
|
size_t offset,
|
|
size_t size)
|
|
{
|
|
const tcu::ScopedLogSection section(log, "Texture Info", "Texture Info");
|
|
|
|
log << TestLog::Message << "Texture format : " << glu::getTextureFormatStr(format) << TestLog::EndMessage;
|
|
log << TestLog::Message << "Buffer size : " << bufferSize << TestLog::EndMessage;
|
|
|
|
if (offset != 0 || size != 0)
|
|
{
|
|
log << TestLog::Message << "Buffer range offset: " << offset << TestLog::EndMessage;
|
|
log << TestLog::Message << "Buffer range size: " << size << TestLog::EndMessage;
|
|
}
|
|
}
|
|
|
|
void runTests (tcu::TestContext& testCtx,
|
|
glu::RenderContext& renderContext,
|
|
de::Random& rng,
|
|
deUint32 format,
|
|
size_t bufferSize,
|
|
size_t offset,
|
|
size_t size,
|
|
RenderBits preRender,
|
|
glu::ShaderProgram* preRenderProgram,
|
|
ModifyBits modifyType,
|
|
RenderBits postRender,
|
|
glu::ShaderProgram* postRenderProgram)
|
|
{
|
|
const tcu::RenderTarget renderTarget (renderContext.getRenderTarget());
|
|
const glw::Functions& gl = renderContext.getFunctions();
|
|
|
|
const int width = de::min<int>(renderTarget.getWidth(), MAX_VIEWPORT_WIDTH);
|
|
const int height = de::min<int>(renderTarget.getHeight(), MAX_VIEWPORT_HEIGHT);
|
|
const tcu::Vec4 clearColor (0.25f, 0.5f, 0.75f, 1.0f);
|
|
|
|
TestLog& log = testCtx.getLog();
|
|
tcu::ResultCollector resultCollector (log);
|
|
|
|
logImplementationInfo(log, renderContext);
|
|
logTextureInfo(log, format, bufferSize, offset, size);
|
|
|
|
{
|
|
tcu::Surface referenceTarget (width, height);
|
|
vector<deUint8> bufferData;
|
|
|
|
genRandomCoords(rng, bufferData, 0, bufferSize);
|
|
|
|
for (deUint8 i = 0; i < 4; i++)
|
|
{
|
|
const deUint8 val = extend2BitsToByte(i);
|
|
|
|
if (val >= offset && val < offset + size)
|
|
{
|
|
bufferData[val*2 + 0] = (i / 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
|
|
bufferData[val*2 + 1] = (i % 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
|
|
}
|
|
}
|
|
|
|
{
|
|
glu::TextureBuffer texture (renderContext, format, bufferSize, offset, size, &(bufferData[0]));
|
|
|
|
TCU_CHECK_MSG(width >= MIN_VIEWPORT_WIDTH || height >= MIN_VIEWPORT_HEIGHT, "Too small viewport");
|
|
|
|
DE_ASSERT(preRender == 0 || preRenderProgram);
|
|
DE_ASSERT(postRender == 0 || postRenderProgram);
|
|
|
|
gl.viewport(0, 0, width, height);
|
|
gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
|
|
gl.clear(GL_COLOR_BUFFER_BIT);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Screen setup failed");
|
|
|
|
tcu::clear(referenceTarget.getAccess(), clearColor);
|
|
|
|
texture.upload();
|
|
|
|
if (preRender != 0)
|
|
render(log, renderContext, preRender, rng, *preRenderProgram, texture, referenceTarget.getAccess());
|
|
|
|
if (modifyType != 0)
|
|
modify(log, resultCollector, renderContext, modifyType, rng, texture);
|
|
|
|
if (postRender != 0)
|
|
render(log, renderContext, postRender, rng, *postRenderProgram, texture, referenceTarget.getAccess());
|
|
}
|
|
|
|
verifyScreen(log, resultCollector, renderContext, referenceTarget.getAccess());
|
|
|
|
resultCollector.setTestContextResult(testCtx);
|
|
}
|
|
}
|
|
|
|
} // anonymous
|
|
|
|
TextureBufferCase::TextureBufferCase (tcu::TestContext& testCtx,
|
|
glu::RenderContext& renderCtx,
|
|
deUint32 format,
|
|
size_t bufferSize,
|
|
size_t offset,
|
|
size_t size,
|
|
RenderBits preRender,
|
|
ModifyBits modify,
|
|
RenderBits postRender,
|
|
const char* name,
|
|
const char* description)
|
|
: tcu::TestCase (testCtx, name, description)
|
|
, m_renderCtx (renderCtx)
|
|
, m_format (format)
|
|
, m_bufferSize (bufferSize)
|
|
, m_offset (offset)
|
|
, m_size (size)
|
|
|
|
, m_preRender (preRender)
|
|
, m_modify (modify)
|
|
, m_postRender (postRender)
|
|
|
|
, m_preRenderProgram (DE_NULL)
|
|
, m_postRenderProgram (DE_NULL)
|
|
{
|
|
}
|
|
|
|
TextureBufferCase::~TextureBufferCase (void)
|
|
{
|
|
TextureBufferCase::deinit();
|
|
}
|
|
|
|
void TextureBufferCase::init (void)
|
|
{
|
|
de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(m_renderCtx));
|
|
|
|
if (!glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
|
|
&& !(glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer")))
|
|
throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
|
|
|
|
{
|
|
const int maxTextureBufferSize = info->getInt(GL_MAX_TEXTURE_BUFFER_SIZE);
|
|
if (maxTextureBufferSize <= 0)
|
|
TCU_THROW(NotSupportedError, "GL_MAX_TEXTURE_BUFFER_SIZE > 0 required");
|
|
}
|
|
|
|
if (m_preRender != 0)
|
|
{
|
|
TestLog& log = m_testCtx.getLog();
|
|
const char* const sectionName = (m_postRender != 0 ? "Primary render program" : "Render program");
|
|
const tcu::ScopedLogSection section (log, sectionName, sectionName);
|
|
|
|
m_preRenderProgram = createRenderProgram(m_renderCtx, m_preRender);
|
|
m_testCtx.getLog() << (*m_preRenderProgram);
|
|
|
|
TCU_CHECK(m_preRenderProgram->isOk());
|
|
}
|
|
|
|
if (m_postRender != 0)
|
|
{
|
|
// Reusing program
|
|
if (m_preRender == m_postRender)
|
|
{
|
|
m_postRenderProgram = m_preRenderProgram;
|
|
}
|
|
else
|
|
{
|
|
TestLog& log = m_testCtx.getLog();
|
|
const char* const sectionName = (m_preRender!= 0 ? "Secondary render program" : "Render program");
|
|
const tcu::ScopedLogSection section (log, sectionName, sectionName);
|
|
|
|
m_postRenderProgram = createRenderProgram(m_renderCtx, m_postRender);
|
|
m_testCtx.getLog() << (*m_postRenderProgram);
|
|
|
|
TCU_CHECK(m_postRenderProgram->isOk());
|
|
}
|
|
}
|
|
}
|
|
|
|
void TextureBufferCase::deinit (void)
|
|
{
|
|
if (m_preRenderProgram == m_postRenderProgram)
|
|
m_postRenderProgram = DE_NULL;
|
|
|
|
delete m_preRenderProgram;
|
|
m_preRenderProgram = DE_NULL;
|
|
|
|
delete m_postRenderProgram;
|
|
m_postRenderProgram = DE_NULL;
|
|
}
|
|
|
|
tcu::TestCase::IterateResult TextureBufferCase::iterate (void)
|
|
{
|
|
de::Random rng (deInt32Hash(deStringHash(getName())));
|
|
size_t offset;
|
|
|
|
if (m_offset != 0)
|
|
{
|
|
const glw::Functions& gl = m_renderCtx.getFunctions();
|
|
deInt32 alignment = 0;
|
|
|
|
gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &alignment);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT)");
|
|
|
|
offset = m_offset * alignment;
|
|
}
|
|
else
|
|
offset = 0;
|
|
|
|
runTests(m_testCtx, m_renderCtx, rng, m_format, m_bufferSize, offset, m_size, m_preRender, m_preRenderProgram, m_modify, m_postRender, m_postRenderProgram);
|
|
|
|
return STOP;
|
|
}
|
|
|
|
} // gls
|
|
} // deqp
|