You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
636 lines
24 KiB
636 lines
24 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 2.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 Texture access function tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es2fShaderTextureFunctionTests.hpp"
|
|
#include "glsShaderRenderCase.hpp"
|
|
#include "glsShaderLibrary.hpp"
|
|
#include "glsTextureTestUtil.hpp"
|
|
#include "gluTexture.hpp"
|
|
#include "gluTextureUtil.hpp"
|
|
#include "tcuTextureUtil.hpp"
|
|
#include "tcuMatrix.hpp"
|
|
#include "tcuMatrixUtil.hpp"
|
|
|
|
#include <sstream>
|
|
|
|
#include "glwEnums.hpp"
|
|
#include "glwFunctions.hpp"
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles2
|
|
{
|
|
namespace Functional
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
enum Function
|
|
{
|
|
FUNCTION_TEXTURE = 0, //!< texture(), textureOffset()
|
|
FUNCTION_TEXTUREPROJ, //!< textureProj(), textureProjOffset()
|
|
FUNCTION_TEXTUREPROJ3, //!< textureProj(sampler2D, vec3)
|
|
FUNCTION_TEXTURELOD, // ...
|
|
FUNCTION_TEXTUREPROJLOD,
|
|
FUNCTION_TEXTUREPROJLOD3, //!< textureProjLod(sampler2D, vec3)
|
|
|
|
FUNCTION_LAST
|
|
};
|
|
|
|
inline bool functionHasProj (Function function)
|
|
{
|
|
return function == FUNCTION_TEXTUREPROJ ||
|
|
function == FUNCTION_TEXTUREPROJ3 ||
|
|
function == FUNCTION_TEXTUREPROJLOD ||
|
|
function == FUNCTION_TEXTUREPROJLOD3;
|
|
}
|
|
|
|
inline bool functionHasLod (Function function)
|
|
{
|
|
return function == FUNCTION_TEXTURELOD ||
|
|
function == FUNCTION_TEXTUREPROJLOD ||
|
|
function == FUNCTION_TEXTUREPROJLOD3;
|
|
}
|
|
|
|
struct TextureLookupSpec
|
|
{
|
|
Function function;
|
|
|
|
tcu::Vec4 minCoord;
|
|
tcu::Vec4 maxCoord;
|
|
|
|
// Bias
|
|
bool useBias;
|
|
|
|
// Bias or Lod for *Lod* functions
|
|
float minLodBias;
|
|
float maxLodBias;
|
|
|
|
TextureLookupSpec (void)
|
|
: function (FUNCTION_LAST)
|
|
, minCoord (0.0f)
|
|
, maxCoord (1.0f)
|
|
, useBias (false)
|
|
, minLodBias (0.0f)
|
|
, maxLodBias (0.0f)
|
|
{
|
|
}
|
|
|
|
TextureLookupSpec (Function function_,
|
|
const tcu::Vec4& minCoord_,
|
|
const tcu::Vec4& maxCoord_,
|
|
bool useBias_,
|
|
float minLodBias_,
|
|
float maxLodBias_)
|
|
: function (function_)
|
|
, minCoord (minCoord_)
|
|
, maxCoord (maxCoord_)
|
|
, useBias (useBias_)
|
|
, minLodBias (minLodBias_)
|
|
, maxLodBias (maxLodBias_)
|
|
{
|
|
}
|
|
};
|
|
|
|
enum TextureType
|
|
{
|
|
TEXTURETYPE_2D,
|
|
TEXTURETYPE_CUBE_MAP,
|
|
|
|
TEXTURETYPE_LAST
|
|
};
|
|
|
|
struct TextureSpec
|
|
{
|
|
TextureType type; //!< Texture type (2D, cubemap, ...)
|
|
deUint32 format;
|
|
deUint32 dataType;
|
|
int width;
|
|
int height;
|
|
int numLevels;
|
|
tcu::Sampler sampler;
|
|
|
|
TextureSpec (void)
|
|
: type (TEXTURETYPE_LAST)
|
|
, format (GL_NONE)
|
|
, dataType (GL_NONE)
|
|
, width (0)
|
|
, height (0)
|
|
, numLevels (0)
|
|
{
|
|
}
|
|
|
|
TextureSpec (TextureType type_,
|
|
deUint32 format_,
|
|
deUint32 dataType_,
|
|
int width_,
|
|
int height_,
|
|
int numLevels_,
|
|
const tcu::Sampler& sampler_)
|
|
: type (type_)
|
|
, format (format_)
|
|
, dataType (dataType_)
|
|
, width (width_)
|
|
, height (height_)
|
|
, numLevels (numLevels_)
|
|
, sampler (sampler_)
|
|
{
|
|
}
|
|
};
|
|
|
|
struct TexLookupParams
|
|
{
|
|
float lod;
|
|
tcu::Vec4 scale;
|
|
tcu::Vec4 bias;
|
|
|
|
TexLookupParams (void)
|
|
: lod (0.0f)
|
|
, scale (1.0f)
|
|
, bias (0.0f)
|
|
{
|
|
}
|
|
};
|
|
|
|
} // anonymous
|
|
|
|
using tcu::Vec2;
|
|
using tcu::Vec3;
|
|
using tcu::Vec4;
|
|
using tcu::IVec2;
|
|
using tcu::IVec3;
|
|
using tcu::IVec4;
|
|
|
|
typedef void (*TexEvalFunc) (gls::ShaderEvalContext& c, const TexLookupParams& lookupParams);
|
|
|
|
inline Vec4 texture2D (const gls::ShaderEvalContext& c, float s, float t, float lod) { return c.textures[0].tex2D->sample(c.textures[0].sampler, s, t, lod); }
|
|
inline Vec4 textureCube (const gls::ShaderEvalContext& c, float s, float t, float r, float lod) { return c.textures[0].texCube->sample(c.textures[0].sampler, s, t, r, lod); }
|
|
|
|
// Eval functions.
|
|
static void evalTexture2D (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod)*p.scale + p.bias; }
|
|
static void evalTextureCube (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; }
|
|
|
|
static void evalTexture2DBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x())*p.scale + p.bias; }
|
|
static void evalTextureCubeBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
|
|
|
|
static void evalTexture2DProj3 (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod)*p.scale + p.bias; }
|
|
static void evalTexture2DProj3Bias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
|
|
static void evalTexture2DProj (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod)*p.scale + p.bias; }
|
|
static void evalTexture2DProjBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x())*p.scale + p.bias; }
|
|
|
|
static void evalTexture2DLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), c.in[1].x())*p.scale + p.bias; }
|
|
static void evalTextureCubeLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
|
|
|
|
static void evalTexture2DProjLod3 (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
|
|
static void evalTexture2DProjLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x())*p.scale + p.bias; }
|
|
|
|
class TexLookupEvaluator : public gls::ShaderEvaluator
|
|
{
|
|
public:
|
|
TexLookupEvaluator (TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {}
|
|
|
|
virtual void evaluate (gls::ShaderEvalContext& ctx) { m_evalFunc(ctx, m_lookupParams); }
|
|
|
|
private:
|
|
TexEvalFunc m_evalFunc;
|
|
const TexLookupParams& m_lookupParams;
|
|
};
|
|
|
|
class ShaderTextureFunctionCase : public gls::ShaderRenderCase
|
|
{
|
|
public:
|
|
ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase);
|
|
~ShaderTextureFunctionCase (void);
|
|
|
|
void init (void);
|
|
void deinit (void);
|
|
|
|
protected:
|
|
void setupUniforms (int programID, const tcu::Vec4& constCoords);
|
|
|
|
private:
|
|
void initTexture (void);
|
|
void initShaderSources (void);
|
|
|
|
TextureLookupSpec m_lookupSpec;
|
|
TextureSpec m_textureSpec;
|
|
|
|
TexLookupParams m_lookupParams;
|
|
TexLookupEvaluator m_evaluator;
|
|
|
|
glu::Texture2D* m_texture2D;
|
|
glu::TextureCube* m_textureCube;
|
|
};
|
|
|
|
ShaderTextureFunctionCase::ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase)
|
|
: gls::ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator)
|
|
, m_lookupSpec (lookup)
|
|
, m_textureSpec (texture)
|
|
, m_evaluator (evalFunc, m_lookupParams)
|
|
, m_texture2D (DE_NULL)
|
|
, m_textureCube (DE_NULL)
|
|
{
|
|
}
|
|
|
|
ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void)
|
|
{
|
|
delete m_texture2D;
|
|
delete m_textureCube;
|
|
}
|
|
|
|
void ShaderTextureFunctionCase::init (void)
|
|
{
|
|
if (m_isVertexCase)
|
|
{
|
|
const glw::Functions& gl = m_renderCtx.getFunctions();
|
|
int numVertexUnits = 0;
|
|
gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexUnits);
|
|
if (numVertexUnits < 1)
|
|
throw tcu::NotSupportedError("Vertex shader texture access is not supported");
|
|
}
|
|
|
|
{
|
|
// Base coord scale & bias
|
|
Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord;
|
|
Vec4 b = m_lookupSpec.minCoord;
|
|
|
|
float baseCoordTrans[] =
|
|
{
|
|
s.x(), 0.0f, 0.f, b.x(),
|
|
0.f, s.y(), 0.f, b.y(),
|
|
s.z()/2.f, -s.z()/2.f, 0.f, s.z()/2.f + b.z(),
|
|
-s.w()/2.f, s.w()/2.f, 0.f, s.w()/2.f + b.w()
|
|
};
|
|
|
|
m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans));
|
|
}
|
|
|
|
if (functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias)
|
|
{
|
|
float s = m_lookupSpec.maxLodBias-m_lookupSpec.minLodBias;
|
|
float b = m_lookupSpec.minLodBias;
|
|
float lodCoordTrans[] =
|
|
{
|
|
s/2.0f, s/2.0f, 0.f, b,
|
|
0.0f, 0.0f, 0.0f, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 0.0f
|
|
};
|
|
|
|
m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans));
|
|
}
|
|
|
|
initShaderSources();
|
|
initTexture();
|
|
|
|
gls::ShaderRenderCase::init();
|
|
}
|
|
|
|
void ShaderTextureFunctionCase::initTexture (void)
|
|
{
|
|
static const IVec4 texCubeSwz[] =
|
|
{
|
|
IVec4(0,0,1,1),
|
|
IVec4(1,1,0,0),
|
|
IVec4(0,1,0,1),
|
|
IVec4(1,0,1,0),
|
|
IVec4(0,1,1,0),
|
|
IVec4(1,0,0,1)
|
|
};
|
|
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST);
|
|
|
|
tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
|
|
tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
|
|
tcu::IVec2 viewportSize = getViewportSize();
|
|
bool isProj = functionHasProj(m_lookupSpec.function);
|
|
float proj = isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f;
|
|
|
|
switch (m_textureSpec.type)
|
|
{
|
|
case TEXTURETYPE_2D:
|
|
{
|
|
float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
|
|
Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
|
|
Vec4 cBias = fmtInfo.valueMin;
|
|
int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4);
|
|
|
|
m_texture2D = new glu::Texture2D(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width, m_textureSpec.height);
|
|
for (int level = 0; level < m_textureSpec.numLevels; level++)
|
|
{
|
|
float fA = float(level)*cStep;
|
|
float fB = 1.0f-fA;
|
|
Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB);
|
|
Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA);
|
|
|
|
m_texture2D->getRefTexture().allocLevel(level);
|
|
tcu::fillWithGrid(m_texture2D->getRefTexture().getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB);
|
|
}
|
|
m_texture2D->upload();
|
|
|
|
// Compute LOD.
|
|
float dudx = (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width / (float)viewportSize[0];
|
|
float dvdy = (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height / (float)viewportSize[1];
|
|
m_lookupParams.lod = glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
|
|
|
|
// Append to texture list.
|
|
m_textures.push_back(gls::TextureBinding(m_texture2D, m_textureSpec.sampler));
|
|
break;
|
|
}
|
|
|
|
case TEXTURETYPE_CUBE_MAP:
|
|
{
|
|
float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
|
|
Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
|
|
Vec4 cBias = fmtInfo.valueMin;
|
|
int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4);
|
|
|
|
DE_ASSERT(m_textureSpec.width == m_textureSpec.height);
|
|
m_textureCube = new glu::TextureCube(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width);
|
|
for (int level = 0; level < m_textureSpec.numLevels; level++)
|
|
{
|
|
float fA = float(level)*cStep;
|
|
float fB = 1.0f-fA;
|
|
Vec2 f (fA, fB);
|
|
|
|
for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
|
|
{
|
|
const IVec4& swzA = texCubeSwz[face];
|
|
IVec4 swzB = 1-swzA;
|
|
Vec4 colorA = cBias + cScale*f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]);
|
|
Vec4 colorB = cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]);
|
|
|
|
m_textureCube->getRefTexture().allocLevel((tcu::CubeFace)face, level);
|
|
tcu::fillWithGrid(m_textureCube->getRefTexture().getLevelFace(level, (tcu::CubeFace)face), de::max(1, baseCellSize>>level), colorA, colorB);
|
|
}
|
|
}
|
|
m_textureCube->upload();
|
|
|
|
// Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
|
|
DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005);
|
|
DE_ASSERT(de::abs(m_lookupSpec.minCoord[0]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[0]) < de::abs(m_lookupSpec.minCoord[2]));
|
|
DE_ASSERT(de::abs(m_lookupSpec.minCoord[1]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[1]) < de::abs(m_lookupSpec.minCoord[2]));
|
|
|
|
tcu::CubeFaceFloatCoords c00 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
|
|
tcu::CubeFaceFloatCoords c10 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.maxCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
|
|
tcu::CubeFaceFloatCoords c01 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.maxCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
|
|
float dudx = (c10.s - c00.s)*(float)m_textureSpec.width / (float)viewportSize[0];
|
|
float dvdy = (c01.t - c00.t)*(float)m_textureSpec.height / (float)viewportSize[1];
|
|
|
|
m_lookupParams.lod = glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
|
|
|
|
m_textures.push_back(gls::TextureBinding(m_textureCube, m_textureSpec.sampler));
|
|
break;
|
|
}
|
|
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
|
|
// Set lookup scale & bias
|
|
m_lookupParams.scale = fmtInfo.lookupScale;
|
|
m_lookupParams.bias = fmtInfo.lookupBias;
|
|
}
|
|
|
|
void ShaderTextureFunctionCase::initShaderSources (void)
|
|
{
|
|
Function function = m_lookupSpec.function;
|
|
bool isVtxCase = m_isVertexCase;
|
|
bool isProj = functionHasProj(function);
|
|
bool is2DProj4 = m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD);
|
|
bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias;
|
|
int texCoordComps = m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3;
|
|
int extraCoordComps = isProj ? (is2DProj4 ? 2 : 1) : 0;
|
|
glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps+extraCoordComps);
|
|
glu::Precision coordPrec = glu::PRECISION_MEDIUMP;
|
|
const char* coordTypeName = glu::getDataTypeName(coordType);
|
|
const char* coordPrecName = glu::getPrecisionName(coordPrec);
|
|
tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
|
|
glu::DataType samplerType = glu::TYPE_LAST;
|
|
const char* baseFuncName = m_textureSpec.type == TEXTURETYPE_2D ? "texture2D" : "textureCube";
|
|
const char* funcExt = DE_NULL;
|
|
|
|
switch (m_textureSpec.type)
|
|
{
|
|
case TEXTURETYPE_2D: samplerType = glu::getSampler2DType(texFmt); break;
|
|
case TEXTURETYPE_CUBE_MAP: samplerType = glu::getSamplerCubeType(texFmt); break;
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
|
|
switch (m_lookupSpec.function)
|
|
{
|
|
case FUNCTION_TEXTURE: funcExt = ""; break;
|
|
case FUNCTION_TEXTUREPROJ: funcExt = "Proj"; break;
|
|
case FUNCTION_TEXTUREPROJ3: funcExt = "Proj"; break;
|
|
case FUNCTION_TEXTURELOD: funcExt = "Lod"; break;
|
|
case FUNCTION_TEXTUREPROJLOD: funcExt = "ProjLod"; break;
|
|
case FUNCTION_TEXTUREPROJLOD3: funcExt = "ProjLod"; break;
|
|
default:
|
|
DE_ASSERT(DE_FALSE);
|
|
}
|
|
|
|
std::ostringstream vert;
|
|
std::ostringstream frag;
|
|
std::ostringstream& op = isVtxCase ? vert : frag;
|
|
|
|
vert << "attribute highp vec4 a_position;\n"
|
|
<< "attribute " << coordPrecName << " " << coordTypeName << " a_in0;\n";
|
|
|
|
if (hasLodBias)
|
|
vert << "attribute " << coordPrecName << " float a_in1;\n";
|
|
|
|
if (isVtxCase)
|
|
{
|
|
vert << "varying mediump vec4 v_color;\n";
|
|
frag << "varying mediump vec4 v_color;\n";
|
|
}
|
|
else
|
|
{
|
|
vert << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
|
|
frag << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
|
|
|
|
if (hasLodBias)
|
|
{
|
|
vert << "varying " << coordPrecName << " float v_lodBias;\n";
|
|
frag << "varying " << coordPrecName << " float v_lodBias;\n";
|
|
}
|
|
}
|
|
|
|
// Uniforms
|
|
op << "uniform lowp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";
|
|
|
|
vert << "\nvoid main()\n{\n"
|
|
<< "\tgl_Position = a_position;\n";
|
|
frag << "\nvoid main()\n{\n";
|
|
|
|
if (isVtxCase)
|
|
vert << "\tv_color = ";
|
|
else
|
|
frag << "\tgl_FragColor = ";
|
|
|
|
// Op.
|
|
{
|
|
const char* texCoord = isVtxCase ? "a_in0" : "v_texCoord";
|
|
const char* lodBias = isVtxCase ? "a_in1" : "v_lodBias";
|
|
|
|
op << baseFuncName << funcExt;
|
|
op << "(u_sampler, " << texCoord;
|
|
|
|
if (functionHasLod(function) || m_lookupSpec.useBias)
|
|
op << ", " << lodBias;
|
|
|
|
op << ");\n";
|
|
}
|
|
|
|
if (isVtxCase)
|
|
frag << "\tgl_FragColor = v_color;\n";
|
|
else
|
|
{
|
|
vert << "\tv_texCoord = a_in0;\n";
|
|
|
|
if (hasLodBias)
|
|
vert << "\tv_lodBias = a_in1;\n";
|
|
}
|
|
|
|
vert << "}\n";
|
|
frag << "}\n";
|
|
|
|
m_vertShaderSource = vert.str();
|
|
m_fragShaderSource = frag.str();
|
|
}
|
|
|
|
void ShaderTextureFunctionCase::deinit (void)
|
|
{
|
|
gls::ShaderRenderCase::deinit();
|
|
|
|
delete m_texture2D;
|
|
delete m_textureCube;
|
|
|
|
m_texture2D = DE_NULL;
|
|
m_textureCube = DE_NULL;
|
|
}
|
|
|
|
void ShaderTextureFunctionCase::setupUniforms (int programID, const tcu::Vec4&)
|
|
{
|
|
const glw::Functions& gl = m_renderCtx.getFunctions();
|
|
gl.uniform1i(gl.getUniformLocation(programID, "u_sampler"), 0);
|
|
}
|
|
|
|
ShaderTextureFunctionTests::ShaderTextureFunctionTests (Context& context)
|
|
: TestCaseGroup(context, "texture_functions", "Texture Access Function Tests")
|
|
{
|
|
}
|
|
|
|
ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void)
|
|
{
|
|
}
|
|
|
|
struct TexFuncCaseSpec
|
|
{
|
|
const char* name;
|
|
TextureLookupSpec lookupSpec;
|
|
TextureSpec texSpec;
|
|
TexEvalFunc evalFunc;
|
|
};
|
|
|
|
#define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, TEXSPEC, EVALFUNC) \
|
|
{ #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD), TEXSPEC, EVALFUNC }
|
|
|
|
static void createCaseGroup (TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases, bool isVertex)
|
|
{
|
|
tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc);
|
|
parent->addChild(group);
|
|
|
|
for (int ndx = 0; ndx < numCases; ndx++)
|
|
group->addChild(new ShaderTextureFunctionCase(parent->getContext(), cases[ndx].name, "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, isVertex));
|
|
}
|
|
|
|
void ShaderTextureFunctionTests::init (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
// Samplers
|
|
static const tcu::Sampler samplerLinearNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
|
|
tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
|
|
static tcu::Sampler samplerLinearMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
|
|
tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR);
|
|
|
|
samplerLinearMipmap.seamlessCubeMap = glu::IsES3Compatible(gl);
|
|
|
|
// Default textures.
|
|
// Type Format DataType W H L Sampler
|
|
static const TextureSpec tex2D (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap);
|
|
static const TextureSpec tex2DMipmap (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap);
|
|
|
|
static const TextureSpec texCube (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap);
|
|
static const TextureSpec texCubeMipmap (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap);
|
|
|
|
// Vertex cases
|
|
static const TexFuncCaseSpec vertexCases[] =
|
|
{
|
|
// Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
|
|
CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, 0.0f, 0.0f, tex2D, evalTexture2D),
|
|
// CASE_SPEC(texture2d_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), true, -2.0f, 2.0f, tex2D, evalTexture2DBias),
|
|
CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj3),
|
|
CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj),
|
|
CASE_SPEC(texture2dlod, FUNCTION_TEXTURELOD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, -1.0f, 9.0f, tex2DMipmap, evalTexture2DLod),
|
|
// CASE_SPEC(texture2dproj_vec3_bias, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), true, -2.0f, 2.0f, tex2D, evalTexture2DProj3Bias),
|
|
// CASE_SPEC(texture2dproj_vec4_bias, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), true, -2.0f, 2.0f, tex2D, evalTexture2DProjBias),
|
|
CASE_SPEC(texture2dprojlod_vec3, FUNCTION_TEXTUREPROJLOD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod3),
|
|
CASE_SPEC(texture2dprojlod_vec4, FUNCTION_TEXTUREPROJLOD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod),
|
|
CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, 0.0f, 0.0f, texCube, evalTextureCube),
|
|
// CASE_SPEC(texturecube_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), true, -2.0f, 2.0f, texCube, evalTextureCubeBias),
|
|
CASE_SPEC(texturecubelod, FUNCTION_TEXTURELOD, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, -1.0f, 9.0f, texCubeMipmap, evalTextureCubeLod),
|
|
};
|
|
createCaseGroup(this, "vertex", "Vertex Shader Texture Lookups", &vertexCases[0], DE_LENGTH_OF_ARRAY(vertexCases), true);
|
|
|
|
// Fragment cases
|
|
static const TexFuncCaseSpec fragmentCases[] =
|
|
{
|
|
// Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
|
|
CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2D),
|
|
CASE_SPEC(texture2d_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DBias),
|
|
CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj3),
|
|
CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj),
|
|
CASE_SPEC(texture2dproj_vec3_bias, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProj3Bias),
|
|
CASE_SPEC(texture2dproj_vec4_bias, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProjBias),
|
|
CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, 0.0f, 0.0f, texCubeMipmap, evalTextureCube),
|
|
CASE_SPEC(texturecube_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), true, -2.0f, 2.0f, texCubeMipmap, evalTextureCubeBias)
|
|
};
|
|
createCaseGroup(this, "fragment", "Fragment Shader Texture Lookups", &fragmentCases[0], DE_LENGTH_OF_ARRAY(fragmentCases), false);
|
|
|
|
// Negative cases.
|
|
{
|
|
gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
|
|
std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/invalid_texture_functions.test");
|
|
|
|
tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, "invalid", "Invalid texture function usage", negativeCases);
|
|
addChild(group);
|
|
}
|
|
}
|
|
|
|
} // Functional
|
|
} // gles3
|
|
} // deqp
|