1117 lines
40 KiB
1117 lines
40 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 3.0 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 FBO test utilities.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es3fFboTestUtil.hpp"
|
|
#include "sglrContextUtil.hpp"
|
|
#include "sglrGLContext.hpp"
|
|
#include "sglrReferenceContext.hpp"
|
|
#include "gluTextureUtil.hpp"
|
|
#include "tcuTextureUtil.hpp"
|
|
#include "deStringUtil.hpp"
|
|
#include "deMath.h"
|
|
#include "glwEnums.hpp"
|
|
#include "glwFunctions.hpp"
|
|
|
|
#include <limits>
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles3
|
|
{
|
|
namespace Functional
|
|
{
|
|
namespace FboTestUtil
|
|
{
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
using tcu::Vec2;
|
|
using tcu::Vec3;
|
|
using tcu::Vec4;
|
|
using tcu::IVec2;
|
|
using tcu::IVec3;
|
|
using tcu::IVec4;
|
|
|
|
static rr::GenericVecType mapDataTypeToGenericVecType(glu::DataType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case glu::TYPE_FLOAT_VEC4: return rr::GENERICVECTYPE_FLOAT;
|
|
case glu::TYPE_INT_VEC4: return rr::GENERICVECTYPE_INT32;
|
|
case glu::TYPE_UINT_VEC4: return rr::GENERICVECTYPE_UINT32;
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
return rr::GENERICVECTYPE_LAST;
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
static tcu::Vector<T, 4> castVectorSaturate (const tcu::Vec4& in)
|
|
{
|
|
return tcu::Vector<T, 4>(((double)in.x() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.x() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.x()))),
|
|
((double)in.y() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.y() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.y()))),
|
|
((double)in.z() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.z() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.z()))),
|
|
((double)in.w() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.w() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.w()))));
|
|
}
|
|
|
|
FlatColorShader::FlatColorShader (glu::DataType outputType)
|
|
: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
|
|
<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
|
|
<< sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::VertexSource(
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
"}\n")
|
|
<< sglr::pdec::FragmentSource(
|
|
string(
|
|
"#version 300 es\n"
|
|
"uniform highp vec4 u_color;\n"
|
|
"layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" o_color = " + glu::getDataTypeName(outputType) + "(u_color);\n"
|
|
"}\n"))
|
|
, m_outputType(outputType)
|
|
{
|
|
}
|
|
|
|
void FlatColorShader::setColor (sglr::Context& context, deUint32 program, const tcu::Vec4& color)
|
|
{
|
|
deInt32 location = context.getUniformLocation(program, "u_color");
|
|
|
|
context.useProgram(program);
|
|
context.uniform4fv(location, 1, color.getPtr());
|
|
}
|
|
|
|
void FlatColorShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
}
|
|
}
|
|
|
|
void FlatColorShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const tcu::Vec4 color (m_uniforms[0].value.f4);
|
|
const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
|
|
const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
|
|
|
|
DE_UNREF(packets);
|
|
|
|
if (m_outputType == glu::TYPE_FLOAT_VEC4)
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
}
|
|
else if (m_outputType == glu::TYPE_INT_VEC4)
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
|
|
}
|
|
else if (m_outputType == glu::TYPE_UINT_VEC4)
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
|
|
}
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
|
|
GradientShader::GradientShader (glu::DataType outputType)
|
|
: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
|
|
<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
|
|
<< sglr::pdec::Uniform("u_gradientMin", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::Uniform("u_gradientMax", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::VertexSource(
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"in highp vec4 a_coord;\n"
|
|
"out highp vec4 v_coord;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_coord = a_coord;\n"
|
|
"}\n")
|
|
<< sglr::pdec::FragmentSource(
|
|
string(
|
|
"#version 300 es\n"
|
|
"in highp vec4 v_coord;\n"
|
|
"uniform highp vec4 u_gradientMin;\n"
|
|
"uniform highp vec4 u_gradientMax;\n"
|
|
"layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" highp float x = v_coord.x;\n"
|
|
" highp float y = v_coord.y;\n"
|
|
" highp float f0 = (x + y) * 0.5;\n"
|
|
" highp float f1 = 0.5 + (x - y) * 0.5;\n"
|
|
" highp vec4 fv = vec4(f0, f1, 1.0f-f0, 1.0f-f1);\n"
|
|
" o_color = " + glu::getDataTypeName(outputType) + "(u_gradientMin + (u_gradientMax-u_gradientMin)*fv);\n"
|
|
"}\n"))
|
|
, m_outputType(outputType)
|
|
{
|
|
}
|
|
|
|
void GradientShader::setGradient (sglr::Context& ctx, deUint32 program, const tcu::Vec4& gradientMin, const tcu::Vec4& gradientMax)
|
|
{
|
|
ctx.useProgram(program);
|
|
ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMin"), 1, gradientMin.getPtr());
|
|
ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMax"), 1, gradientMax.getPtr());
|
|
}
|
|
|
|
void GradientShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
|
|
}
|
|
}
|
|
|
|
void GradientShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const tcu::Vec4 gradientMin(m_uniforms[0].value.f4);
|
|
const tcu::Vec4 gradientMax(m_uniforms[1].value.f4);
|
|
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
|
|
const float x = coord.x();
|
|
const float y = coord.y();
|
|
const float f0 = (x + y) * 0.5f;
|
|
const float f1 = 0.5f + (x - y) * 0.5f;
|
|
const tcu::Vec4 fv = Vec4(f0, f1, 1.0f-f0, 1.0f-f1);
|
|
|
|
const tcu::Vec4 color = gradientMin + (gradientMax-gradientMin) * fv;
|
|
const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
|
|
const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
|
|
|
|
if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
|
|
else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
|
|
static string genTexFragmentShader (const vector<glu::DataType>& samplerTypes, glu::DataType outputType)
|
|
{
|
|
const char* precision = "highp";
|
|
std::ostringstream src;
|
|
|
|
src << "#version 300 es\n"
|
|
<< "layout(location = 0) out highp " << glu::getDataTypeName(outputType) << " o_color0;\n";
|
|
|
|
src << "in highp vec2 v_coord;\n";
|
|
|
|
for (int samplerNdx = 0; samplerNdx < (int)samplerTypes.size(); samplerNdx++)
|
|
{
|
|
src << "uniform " << precision << " " << glu::getDataTypeName(samplerTypes[samplerNdx]) << " u_sampler" << samplerNdx << ";\n";
|
|
src << "uniform " << precision << " vec4 u_texScale" << samplerNdx << ";\n";
|
|
src << "uniform " << precision << " vec4 u_texBias" << samplerNdx << ";\n";
|
|
}
|
|
|
|
// Output scale & bias
|
|
src << "uniform " << precision << " vec4 u_outScale0;\n"
|
|
<< "uniform " << precision << " vec4 u_outBias0;\n";
|
|
|
|
src << "\n"
|
|
<< "void main (void)\n"
|
|
<< "{\n"
|
|
<< " " << precision << " vec4 out0 = vec4(0.0);\n";
|
|
|
|
// Texture input fetch and combine.
|
|
for (int inNdx = 0; inNdx < (int)samplerTypes.size(); inNdx++)
|
|
src << "\tout0 += vec4("
|
|
<< "texture(u_sampler" << inNdx << ", v_coord)) * u_texScale" << inNdx << " + u_texBias" << inNdx << ";\n";
|
|
|
|
// Write output.
|
|
src << " o_color0 = " << glu::getDataTypeName(outputType) << "(out0 * u_outScale0 + u_outBias0);\n";
|
|
|
|
src << "}\n";
|
|
|
|
return src.str();
|
|
}
|
|
|
|
static sglr::pdec::ShaderProgramDeclaration genTexture2DShaderDecl (const DataTypes& samplerTypes, glu::DataType outputType)
|
|
{
|
|
sglr::pdec::ShaderProgramDeclaration decl;
|
|
|
|
decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
|
|
decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
|
|
decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
|
|
decl << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType));
|
|
|
|
decl << sglr::pdec::VertexSource(
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"in highp vec2 a_coord;\n"
|
|
"out highp vec2 v_coord;\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_coord = a_coord;\n"
|
|
"}\n");
|
|
decl << sglr::pdec::FragmentSource(genTexFragmentShader(samplerTypes.vec, outputType));
|
|
|
|
decl << sglr::pdec::Uniform("u_outScale0", glu::TYPE_FLOAT_VEC4);
|
|
decl << sglr::pdec::Uniform("u_outBias0", glu::TYPE_FLOAT_VEC4);
|
|
|
|
for (size_t ndx = 0; ndx < samplerTypes.vec.size(); ++ndx)
|
|
{
|
|
decl << sglr::pdec::Uniform(std::string("u_sampler") + de::toString(ndx), samplerTypes.vec[ndx]);
|
|
decl << sglr::pdec::Uniform(std::string("u_texScale") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
|
|
decl << sglr::pdec::Uniform(std::string("u_texBias") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
|
|
}
|
|
|
|
return decl;
|
|
}
|
|
|
|
Texture2DShader::Texture2DShader (const DataTypes& samplerTypes, glu::DataType outputType, const Vec4& outScale, const Vec4& outBias)
|
|
: sglr::ShaderProgram (genTexture2DShaderDecl(samplerTypes, outputType))
|
|
, m_outScale (outScale)
|
|
, m_outBias (outBias)
|
|
, m_outputType (outputType)
|
|
{
|
|
m_inputs.resize(samplerTypes.vec.size());
|
|
|
|
// Initialize units.
|
|
for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
|
|
{
|
|
m_inputs[ndx].unitNdx = ndx;
|
|
m_inputs[ndx].scale = Vec4(1.0f);
|
|
m_inputs[ndx].bias = Vec4(0.0f);
|
|
}
|
|
}
|
|
|
|
void Texture2DShader::setUnit (int inputNdx, int unitNdx)
|
|
{
|
|
m_inputs[inputNdx].unitNdx = unitNdx;
|
|
}
|
|
|
|
void Texture2DShader::setTexScaleBias (int inputNdx, const Vec4& scale, const Vec4& bias)
|
|
{
|
|
m_inputs[inputNdx].scale = scale;
|
|
m_inputs[inputNdx].bias = bias;
|
|
}
|
|
|
|
void Texture2DShader::setOutScaleBias (const Vec4& scale, const Vec4& bias)
|
|
{
|
|
m_outScale = scale;
|
|
m_outBias = bias;
|
|
}
|
|
|
|
void Texture2DShader::setUniforms (sglr::Context& gl, deUint32 program) const
|
|
{
|
|
gl.useProgram(program);
|
|
|
|
for (int texNdx = 0; texNdx < (int)m_inputs.size(); texNdx++)
|
|
{
|
|
string samplerName = string("u_sampler") + de::toString(texNdx);
|
|
string scaleName = string("u_texScale") + de::toString(texNdx);
|
|
string biasName = string("u_texBias") + de::toString(texNdx);
|
|
|
|
gl.uniform1i(gl.getUniformLocation(program, samplerName.c_str()), m_inputs[texNdx].unitNdx);
|
|
gl.uniform4fv(gl.getUniformLocation(program, scaleName.c_str()), 1, m_inputs[texNdx].scale.getPtr());
|
|
gl.uniform4fv(gl.getUniformLocation(program, biasName.c_str()), 1, m_inputs[texNdx].bias.getPtr());
|
|
}
|
|
|
|
gl.uniform4fv(gl.getUniformLocation(program, "u_outScale0"), 1, m_outScale.getPtr());
|
|
gl.uniform4fv(gl.getUniformLocation(program, "u_outBias0"), 1, m_outBias.getPtr());
|
|
}
|
|
|
|
void Texture2DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
|
|
}
|
|
}
|
|
|
|
void Texture2DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const tcu::Vec4 outScale (m_uniforms[0].value.f4);
|
|
const tcu::Vec4 outBias (m_uniforms[1].value.f4);
|
|
|
|
tcu::Vec2 texCoords[4];
|
|
tcu::Vec4 colors[4];
|
|
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
// setup tex coords
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
|
|
texCoords[fragNdx] = tcu::Vec2(coord.x(), coord.y());
|
|
}
|
|
|
|
// clear result
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
colors[fragNdx] = tcu::Vec4(0.0f);
|
|
|
|
// sample each texture
|
|
for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
|
|
{
|
|
const sglr::rc::Texture2D* tex = m_uniforms[2 + ndx*3].sampler.tex2D;
|
|
const tcu::Vec4 scale (m_uniforms[2 + ndx*3 + 1].value.f4);
|
|
const tcu::Vec4 bias (m_uniforms[2 + ndx*3 + 2].value.f4);
|
|
tcu::Vec4 tmpColors[4];
|
|
|
|
tex->sample4(tmpColors, texCoords);
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
colors[fragNdx] += tmpColors[fragNdx] * scale + bias;
|
|
}
|
|
|
|
// write out
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 color = colors[fragNdx] * outScale + outBias;
|
|
const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
|
|
const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
|
|
|
|
if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
|
|
else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
TextureCubeShader::TextureCubeShader (glu::DataType samplerType, glu::DataType outputType)
|
|
: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
|
|
<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
|
|
<< sglr::pdec::Uniform("u_coordMat", glu::TYPE_FLOAT_MAT3)
|
|
<< sglr::pdec::Uniform("u_sampler0", samplerType)
|
|
<< sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::VertexSource(
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"in mediump vec2 a_coord;\n"
|
|
"uniform mat3 u_coordMat;\n"
|
|
"out mediump vec3 v_coord;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_coord = u_coordMat * vec3(a_coord, 1.0);\n"
|
|
"}\n")
|
|
<< sglr::pdec::FragmentSource(
|
|
string("") +
|
|
"#version 300 es\n"
|
|
"uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
|
|
"uniform highp vec4 u_scale;\n"
|
|
"uniform highp vec4 u_bias;\n"
|
|
"in mediump vec3 v_coord;\n"
|
|
"layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, v_coord)) * u_scale + u_bias);\n"
|
|
"}\n"))
|
|
, m_texScale (1.0f)
|
|
, m_texBias (0.0f)
|
|
, m_outputType (outputType)
|
|
{
|
|
}
|
|
|
|
void TextureCubeShader::setFace (tcu::CubeFace face)
|
|
{
|
|
static const float s_cubeTransforms[][3*3] =
|
|
{
|
|
// Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
|
|
{ 0.0f, 0.0f, -1.0f,
|
|
0.0f, -2.0f, 1.0f,
|
|
2.0f, 0.0f, -1.0f },
|
|
// Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
|
|
{ 0.0f, 0.0f, 1.0f,
|
|
0.0f, -2.0f, 1.0f,
|
|
-2.0f, 0.0f, 1.0f },
|
|
// Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
|
|
{ 2.0f, 0.0f, -1.0f,
|
|
0.0f, 0.0f, -1.0f,
|
|
0.0f, -2.0f, 1.0f },
|
|
// Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
|
|
{ 2.0f, 0.0f, -1.0f,
|
|
0.0f, 0.0f, 1.0f,
|
|
0.0f, 2.0f, -1.0f },
|
|
// Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
|
|
{ -2.0f, 0.0f, 1.0f,
|
|
0.0f, -2.0f, 1.0f,
|
|
0.0f, 0.0f, -1.0f },
|
|
// Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
|
|
{ 2.0f, 0.0f, -1.0f,
|
|
0.0f, -2.0f, 1.0f,
|
|
0.0f, 0.0f, 1.0f }
|
|
};
|
|
DE_ASSERT(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
|
|
m_coordMat = tcu::Mat3(s_cubeTransforms[face]);
|
|
}
|
|
|
|
void TextureCubeShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
|
|
{
|
|
m_texScale = scale;
|
|
m_texBias = bias;
|
|
}
|
|
|
|
void TextureCubeShader::setUniforms (sglr::Context& gl, deUint32 program) const
|
|
{
|
|
gl.useProgram(program);
|
|
|
|
gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
|
|
gl.uniformMatrix3fv(gl.getUniformLocation(program, "u_coordMat"), 1, GL_FALSE, m_coordMat.getColumnMajorData().getPtr());
|
|
gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
|
|
gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
|
|
}
|
|
|
|
void TextureCubeShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
tcu::Mat3 texCoordMat = tcu::Mat3(m_uniforms[0].value.m3);
|
|
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
tcu::Vec2 a_coord = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx).xy();
|
|
tcu::Vec3 v_coord = texCoordMat * tcu::Vec3(a_coord.x(), a_coord.y(), 1.0f);
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
packet.outputs[0] = tcu::Vec4(v_coord.x(), v_coord.y(), v_coord.z(), 0.0f);
|
|
}
|
|
}
|
|
|
|
void TextureCubeShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const tcu::Vec4 texScale (m_uniforms[2].value.f4);
|
|
const tcu::Vec4 texBias (m_uniforms[3].value.f4);
|
|
|
|
tcu::Vec3 texCoords[4];
|
|
tcu::Vec4 colors[4];
|
|
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
const sglr::rc::TextureCube* tex = m_uniforms[1].sampler.texCube;
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
|
|
texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), coord.z());
|
|
}
|
|
|
|
tex->sample4(colors, texCoords);
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 color = colors[fragNdx] * texScale + texBias;
|
|
const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
|
|
const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
|
|
|
|
if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
|
|
else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
Texture2DArrayShader::Texture2DArrayShader (glu::DataType samplerType, glu::DataType outputType)
|
|
: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
|
|
<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
|
|
<< sglr::pdec::Uniform("u_sampler0", samplerType)
|
|
<< sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::Uniform("u_layer", glu::TYPE_INT)
|
|
<< sglr::pdec::VertexSource(
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"in highp vec2 a_coord;\n"
|
|
"out highp vec2 v_coord;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_coord = a_coord;\n"
|
|
"}\n")
|
|
<< sglr::pdec::FragmentSource(
|
|
string("") +
|
|
"#version 300 es\n"
|
|
"uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
|
|
"uniform highp vec4 u_scale;\n"
|
|
"uniform highp vec4 u_bias;\n"
|
|
"uniform highp int u_layer;\n"
|
|
"in highp vec2 v_coord;\n"
|
|
"layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec3(v_coord, u_layer))) * u_scale + u_bias);\n"
|
|
"}\n"))
|
|
, m_texScale (1.0f)
|
|
, m_texBias (0.0f)
|
|
, m_layer (0)
|
|
, m_outputType (outputType)
|
|
{
|
|
}
|
|
|
|
void Texture2DArrayShader::setLayer (int layer)
|
|
{
|
|
m_layer = layer;
|
|
}
|
|
|
|
void Texture2DArrayShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
|
|
{
|
|
m_texScale = scale;
|
|
m_texBias = bias;
|
|
}
|
|
|
|
void Texture2DArrayShader::setUniforms (sglr::Context& gl, deUint32 program) const
|
|
{
|
|
gl.useProgram(program);
|
|
|
|
gl.uniform1i (gl.getUniformLocation(program, "u_sampler0"), 0);
|
|
gl.uniform1i (gl.getUniformLocation(program, "u_layer"), m_layer);
|
|
gl.uniform4fv (gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
|
|
gl.uniform4fv (gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
|
|
}
|
|
|
|
void Texture2DArrayShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
|
|
}
|
|
}
|
|
|
|
void Texture2DArrayShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const tcu::Vec4 texScale (m_uniforms[1].value.f4);
|
|
const tcu::Vec4 texBias (m_uniforms[2].value.f4);
|
|
const int layer = m_uniforms[3].value.i;
|
|
|
|
tcu::Vec3 texCoords[4];
|
|
tcu::Vec4 colors[4];
|
|
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
const sglr::rc::Texture2DArray* tex = m_uniforms[0].sampler.tex2DArray;
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
|
|
texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), float(layer));
|
|
}
|
|
|
|
tex->sample4(colors, texCoords);
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 color = colors[fragNdx] * texScale + texBias;
|
|
const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
|
|
const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
|
|
|
|
if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
|
|
else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
Texture3DShader::Texture3DShader (glu::DataType samplerType, glu::DataType outputType)
|
|
: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
|
|
<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
|
|
<< sglr::pdec::Uniform("u_sampler0", samplerType)
|
|
<< sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::Uniform("u_depth", glu::TYPE_FLOAT)
|
|
<< sglr::pdec::VertexSource(
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"in highp vec2 a_coord;\n"
|
|
"out highp vec2 v_coord;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_coord = a_coord;\n"
|
|
"}\n")
|
|
<< sglr::pdec::FragmentSource(
|
|
string("") +
|
|
"#version 300 es\n"
|
|
"uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
|
|
"uniform highp vec4 u_scale;\n"
|
|
"uniform highp vec4 u_bias;\n"
|
|
"uniform highp float u_depth;\n"
|
|
"in highp vec2 v_coord;\n"
|
|
"layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec3(v_coord, u_depth))) * u_scale + u_bias);\n"
|
|
"}\n"))
|
|
, m_texScale (1.0f)
|
|
, m_texBias (0.0f)
|
|
, m_depth (0.0f)
|
|
, m_outputType (outputType)
|
|
{
|
|
}
|
|
|
|
void Texture3DShader::setDepth (float depth)
|
|
{
|
|
m_depth = depth;
|
|
}
|
|
|
|
void Texture3DShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
|
|
{
|
|
m_texScale = scale;
|
|
m_texBias = bias;
|
|
}
|
|
|
|
void Texture3DShader::setUniforms (sglr::Context& gl, deUint32 program) const
|
|
{
|
|
gl.useProgram(program);
|
|
|
|
gl.uniform1i (gl.getUniformLocation(program, "u_sampler0"), 0);
|
|
gl.uniform1f (gl.getUniformLocation(program, "u_depth"), m_depth);
|
|
gl.uniform4fv (gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
|
|
gl.uniform4fv (gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
|
|
}
|
|
|
|
void Texture3DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
|
|
}
|
|
}
|
|
|
|
void Texture3DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const tcu::Vec4 texScale (m_uniforms[1].value.f4);
|
|
const tcu::Vec4 texBias (m_uniforms[2].value.f4);
|
|
const float depth = m_uniforms[3].value.f;
|
|
|
|
tcu::Vec3 texCoords[4];
|
|
tcu::Vec4 colors[4];
|
|
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
const sglr::rc::Texture3D* tex = m_uniforms[0].sampler.tex3D;
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
|
|
texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), depth);
|
|
}
|
|
|
|
tex->sample4(colors, texCoords);
|
|
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 color = colors[fragNdx] * texScale + texBias;
|
|
const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
|
|
const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
|
|
|
|
if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
|
|
else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
DepthGradientShader::DepthGradientShader (glu::DataType outputType)
|
|
: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
|
|
<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
|
|
<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
|
|
<< sglr::pdec::Uniform("u_maxGradient", glu::TYPE_FLOAT)
|
|
<< sglr::pdec::Uniform("u_minGradient", glu::TYPE_FLOAT)
|
|
<< sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
|
|
<< sglr::pdec::VertexSource(
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"in highp vec4 a_coord;\n"
|
|
"out highp vec4 v_coord;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_coord = a_coord;\n"
|
|
"}\n")
|
|
<< sglr::pdec::FragmentSource(
|
|
string(
|
|
"#version 300 es\n"
|
|
"in highp vec4 v_coord;\n"
|
|
"uniform highp float u_minGradient;\n"
|
|
"uniform highp float u_maxGradient;\n"
|
|
"uniform highp vec4 u_color;\n"
|
|
"layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
" highp float x = v_coord.x;\n"
|
|
" highp float y = v_coord.y;\n"
|
|
" highp float f0 = (x + y) * 0.5;\n"
|
|
" gl_FragDepth = u_minGradient + (u_maxGradient-u_minGradient)*f0;\n"
|
|
" o_color = " + glu::getDataTypeName(outputType) + "(u_color);\n"
|
|
"}\n"))
|
|
, m_outputType (outputType)
|
|
, u_minGradient (getUniformByName("u_minGradient"))
|
|
, u_maxGradient (getUniformByName("u_maxGradient"))
|
|
, u_color (getUniformByName("u_color"))
|
|
{
|
|
}
|
|
|
|
void DepthGradientShader::setUniforms (sglr::Context& ctx, deUint32 program, const float gradientMin, const float gradientMax, const tcu::Vec4& color)
|
|
{
|
|
ctx.useProgram(program);
|
|
ctx.uniform1fv(ctx.getUniformLocation(program, "u_minGradient"), 1, &gradientMin);
|
|
ctx.uniform1fv(ctx.getUniformLocation(program, "u_maxGradient"), 1, &gradientMax);
|
|
ctx.uniform4fv(ctx.getUniformLocation(program, "u_color"), 1, color.getPtr());
|
|
}
|
|
|
|
void DepthGradientShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
{
|
|
rr::VertexPacket& packet = *packets[packetNdx];
|
|
|
|
packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
|
|
packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
|
|
}
|
|
}
|
|
|
|
void DepthGradientShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const float gradientMin (u_minGradient.value.f);
|
|
const float gradientMax (u_maxGradient.value.f);
|
|
const tcu::Vec4 color (u_color.value.f4);
|
|
const tcu::IVec4 icolor (castVectorSaturate<deInt32>(color));
|
|
const tcu::UVec4 uicolor (castVectorSaturate<deUint32>(color));
|
|
|
|
// running this shader without a depth buffer does not make any sense
|
|
DE_ASSERT(context.fragmentDepths);
|
|
|
|
for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
|
|
for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
|
|
{
|
|
const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
|
|
const float x = coord.x();
|
|
const float y = coord.y();
|
|
const float f0 = (x + y) * 0.5f;
|
|
|
|
rr::writeFragmentDepth(context, packetNdx, fragNdx, 0, gradientMin + (gradientMax-gradientMin) * f0);
|
|
|
|
if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
|
|
else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
|
|
else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
|
|
else
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
|
|
void clearColorBuffer (sglr::Context& ctx, const tcu::TextureFormat& format, const tcu::Vec4& value)
|
|
{
|
|
const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(format.type);
|
|
|
|
switch (fmtClass)
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
ctx.clearBufferfv(GL_COLOR, 0, value.getPtr());
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
ctx.clearBufferuiv(GL_COLOR, 0, value.asUint().getPtr());
|
|
break;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
ctx.clearBufferiv(GL_COLOR, 0, value.asInt().getPtr());
|
|
break;
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
}
|
|
|
|
void readPixels (sglr::Context& ctx, tcu::Surface& dst, int x, int y, int width, int height, const tcu::TextureFormat& format, const tcu::Vec4& scale, const tcu::Vec4& bias)
|
|
{
|
|
tcu::TextureFormat readFormat = getFramebufferReadFormat(format);
|
|
glu::TransferFormat transferFmt = glu::getTransferFormat(readFormat);
|
|
int alignment = 4; // \note GL_PACK_ALIGNMENT = 4 is assumed.
|
|
int rowSize = deAlign32(readFormat.getPixelSize()*width, alignment);
|
|
vector<deUint8> data (rowSize*height);
|
|
|
|
ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, &data[0]);
|
|
|
|
// Convert to surface.
|
|
tcu::ConstPixelBufferAccess src(readFormat, width, height, 1, rowSize, 0, &data[0]);
|
|
|
|
dst.setSize(width, height);
|
|
tcu::PixelBufferAccess dstAccess = dst.getAccess();
|
|
|
|
for (int yo = 0; yo < height; yo++)
|
|
for (int xo = 0; xo < width; xo++)
|
|
dstAccess.setPixel(src.getPixel(xo, yo) * scale + bias, xo, yo);
|
|
}
|
|
|
|
static const char* getFboIncompleteReasonName (deUint32 reason)
|
|
{
|
|
switch (reason)
|
|
{
|
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
|
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
|
|
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
|
|
case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
|
|
case GL_FRAMEBUFFER_COMPLETE: return "GL_FRAMEBUFFER_COMPLETE";
|
|
default: return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
FboIncompleteException::FboIncompleteException (deUint32 reason, const char* file, int line)
|
|
: TestError ("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
|
|
, m_reason (reason)
|
|
{
|
|
}
|
|
|
|
const char* getFormatName (deUint32 format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case GL_RGB565: return "rgb565";
|
|
case GL_RGB5_A1: return "rgb5_a1";
|
|
case GL_RGBA4: return "rgba4";
|
|
case GL_DEPTH_COMPONENT16: return "depth_component16";
|
|
case GL_STENCIL_INDEX8: return "stencil_index8";
|
|
case GL_RGBA32F: return "rgba32f";
|
|
case GL_RGBA32I: return "rgba32i";
|
|
case GL_RGBA32UI: return "rgba32ui";
|
|
case GL_RGBA16F: return "rgba16f";
|
|
case GL_RGBA16I: return "rgba16i";
|
|
case GL_RGBA16UI: return "rgba16ui";
|
|
case GL_RGBA8: return "rgba8";
|
|
case GL_RGBA8I: return "rgba8i";
|
|
case GL_RGBA8UI: return "rgba8ui";
|
|
case GL_SRGB8_ALPHA8: return "srgb8_alpha8";
|
|
case GL_RGB10_A2: return "rgb10_a2";
|
|
case GL_RGB10_A2UI: return "rgb10_a2ui";
|
|
case GL_RGBA8_SNORM: return "rgba8_snorm";
|
|
case GL_RGB8: return "rgb8";
|
|
case GL_R11F_G11F_B10F: return "r11f_g11f_b10f";
|
|
case GL_RGB32F: return "rgb32f";
|
|
case GL_RGB32I: return "rgb32i";
|
|
case GL_RGB32UI: return "rgb32ui";
|
|
case GL_RGB16F: return "rgb16f";
|
|
case GL_RGB16I: return "rgb16i";
|
|
case GL_RGB16UI: return "rgb16ui";
|
|
case GL_RGB8_SNORM: return "rgb8_snorm";
|
|
case GL_RGB8I: return "rgb8i";
|
|
case GL_RGB8UI: return "rgb8ui";
|
|
case GL_SRGB8: return "srgb8";
|
|
case GL_RGB9_E5: return "rgb9_e5";
|
|
case GL_RG32F: return "rg32f";
|
|
case GL_RG32I: return "rg32i";
|
|
case GL_RG32UI: return "rg32ui";
|
|
case GL_RG16F: return "rg16f";
|
|
case GL_RG16I: return "rg16i";
|
|
case GL_RG16UI: return "rg16ui";
|
|
case GL_RG8: return "rg8";
|
|
case GL_RG8I: return "rg8i";
|
|
case GL_RG8UI: return "rg8ui";
|
|
case GL_RG8_SNORM: return "rg8_snorm";
|
|
case GL_R32F: return "r32f";
|
|
case GL_R32I: return "r32i";
|
|
case GL_R32UI: return "r32ui";
|
|
case GL_R16F: return "r16f";
|
|
case GL_R16I: return "r16i";
|
|
case GL_R16UI: return "r16ui";
|
|
case GL_R8: return "r8";
|
|
case GL_R8I: return "r8i";
|
|
case GL_R8UI: return "r8ui";
|
|
case GL_R8_SNORM: return "r8_snorm";
|
|
case GL_DEPTH_COMPONENT32F: return "depth_component32f";
|
|
case GL_DEPTH_COMPONENT24: return "depth_component24";
|
|
case GL_DEPTH32F_STENCIL8: return "depth32f_stencil8";
|
|
case GL_DEPTH24_STENCIL8: return "depth24_stencil8";
|
|
|
|
default:
|
|
TCU_FAIL("Unknown format");
|
|
}
|
|
}
|
|
|
|
glu::DataType getFragmentOutputType (const tcu::TextureFormat& format)
|
|
{
|
|
switch (tcu::getTextureChannelClass(format.type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
return glu::TYPE_FLOAT_VEC4;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
return glu::TYPE_UINT_VEC4;
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
return glu::TYPE_INT_VEC4;
|
|
|
|
default:
|
|
DE_FATAL("Unknown format");
|
|
return glu::TYPE_LAST;
|
|
}
|
|
}
|
|
|
|
tcu::TextureFormat getFramebufferReadFormat (const tcu::TextureFormat& format)
|
|
{
|
|
switch (tcu::getTextureChannelClass(format.type))
|
|
{
|
|
case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
|
|
return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
|
|
return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
|
|
|
|
case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
|
|
return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
|
|
|
|
case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
|
|
return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
|
|
|
|
default:
|
|
DE_FATAL("Unknown format");
|
|
return tcu::TextureFormat();
|
|
}
|
|
}
|
|
|
|
static int calculateU8ConversionError (int srcBits)
|
|
{
|
|
if (srcBits > 0)
|
|
{
|
|
const int clampedBits = de::clamp<int>(srcBits, 0, 8);
|
|
const int srcMaxValue = de::max((1<<clampedBits) - 1, 1);
|
|
const int error = int(deFloatCeil(255.0f * 2.0f / float(srcMaxValue)));
|
|
|
|
return de::clamp<int>(error, 0, 255);
|
|
}
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
tcu::RGBA getFormatThreshold (const tcu::TextureFormat& format)
|
|
{
|
|
const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(format);
|
|
|
|
return tcu::RGBA(calculateU8ConversionError(bits.x()),
|
|
calculateU8ConversionError(bits.y()),
|
|
calculateU8ConversionError(bits.z()),
|
|
calculateU8ConversionError(bits.w()));
|
|
}
|
|
|
|
tcu::RGBA getFormatThreshold (deUint32 glFormat)
|
|
{
|
|
const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
|
|
|
|
return getFormatThreshold(format);
|
|
}
|
|
|
|
static int getToSRGB8ConversionError (int srcBits)
|
|
{
|
|
// \note These are pre-computed based on simulation results.
|
|
static const int errors[] =
|
|
{
|
|
1, // 0 bits - rounding
|
|
255, // 1 bits
|
|
157, // 2 bits
|
|
106, // 3 bits
|
|
74, // 4 bits
|
|
51, // 5 bits
|
|
34, // 6 bits
|
|
22, // 7 bits
|
|
13, // 8 bits
|
|
7, // 9 bits
|
|
4, // 10 bits
|
|
3, // 11 bits
|
|
2, // 12 bits
|
|
// 1 from this on
|
|
};
|
|
|
|
DE_ASSERT(srcBits >= 0);
|
|
if (srcBits < DE_LENGTH_OF_ARRAY(errors))
|
|
return errors[srcBits];
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
tcu::RGBA getToSRGBConversionThreshold (const tcu::TextureFormat& src, const tcu::TextureFormat& dst)
|
|
{
|
|
// Only SRGB8 and SRGB8_ALPHA8 formats are supported.
|
|
DE_ASSERT(dst.type == tcu::TextureFormat::UNORM_INT8 && tcu::isSRGB(dst));
|
|
|
|
const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(src);
|
|
const bool dstHasAlpha = dst.order == tcu::TextureFormat::sRGBA;
|
|
|
|
return tcu::RGBA(getToSRGB8ConversionError(bits.x()),
|
|
getToSRGB8ConversionError(bits.y()),
|
|
getToSRGB8ConversionError(bits.z()),
|
|
dstHasAlpha ? calculateU8ConversionError(bits.w()) : 0);
|
|
}
|
|
|
|
} // FboTestUtil
|
|
} // Functional
|
|
} // gles3
|
|
} // deqp
|