From 08a3fca4026822a0f753c737b38553231926d8de Mon Sep 17 00:00:00 2001 From: Akos Dirner Date: Fri, 11 Mar 2016 16:53:35 +0100 Subject: [PATCH] Add ShaderRenderTextureFunctionTests. Fixes #324. --- .../modules/vulkan/shaderrender/CMakeLists.txt | 2 + .../vktShaderRenderTextureFunctionTests.cpp | 2115 ++++++++++++++++++++ .../vktShaderRenderTextureFunctionTests.hpp | 48 + .../vulkancts/modules/vulkan/vktTestPackage.cpp | 18 +- 4 files changed, 2175 insertions(+), 8 deletions(-) create mode 100644 external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.cpp create mode 100644 external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.hpp diff --git a/external/vulkancts/modules/vulkan/shaderrender/CMakeLists.txt b/external/vulkancts/modules/vulkan/shaderrender/CMakeLists.txt index 2a697a1..3c3ba07 100644 --- a/external/vulkancts/modules/vulkan/shaderrender/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/shaderrender/CMakeLists.txt @@ -21,6 +21,8 @@ set(DEQP_VK_SHADERRENDER_SRCS vktShaderRenderStructTests.hpp vktShaderRenderSwitchTests.cpp vktShaderRenderSwitchTests.hpp + vktShaderRenderTextureFunctionTests.cpp + vktShaderRenderTextureFunctionTests.hpp ) set(DEQP_VK_SHADERRENDER_LIBS diff --git a/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.cpp b/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.cpp new file mode 100644 index 0000000..408aba9 --- /dev/null +++ b/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.cpp @@ -0,0 +1,2115 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 The Android Open Source Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice(s) and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + * + *//*! + * \file + * \brief Texture access function tests. + *//*--------------------------------------------------------------------*/ + +#include "vktShaderRenderTextureFunctionTests.hpp" +#include "vktShaderRender.hpp" +#include "gluTextureUtil.hpp" +#include "tcuTexture.hpp" +#include "tcuTextureUtil.hpp" +#include "tcuTestLog.hpp" +#include "glwEnums.hpp" +#include "deMath.h" + +namespace vkt +{ +namespace sr +{ +namespace +{ + +using tcu::Vec2; +using tcu::Vec3; +using tcu::Vec4; +using tcu::IVec2; +using tcu::IVec3; +using tcu::IVec4; + +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_TEXTUREGRAD, + FUNCTION_TEXTUREPROJGRAD, + FUNCTION_TEXTUREPROJGRAD3, //!< textureProjGrad(sampler2D, vec3) + FUNCTION_TEXELFETCH, + + FUNCTION_LAST +}; + +inline bool functionHasAutoLod (glu::ShaderType shaderType, Function function) +{ + return shaderType == glu::SHADERTYPE_FRAGMENT && + (function == FUNCTION_TEXTURE || + function == FUNCTION_TEXTUREPROJ || + function == FUNCTION_TEXTUREPROJ3); +} + +inline bool functionHasProj (Function function) +{ + return function == FUNCTION_TEXTUREPROJ || + function == FUNCTION_TEXTUREPROJ3 || + function == FUNCTION_TEXTUREPROJLOD || + function == FUNCTION_TEXTUREPROJGRAD || + function == FUNCTION_TEXTUREPROJLOD3 || + function == FUNCTION_TEXTUREPROJGRAD3; +} + +inline bool functionHasGrad (Function function) +{ + return function == FUNCTION_TEXTUREGRAD || function == FUNCTION_TEXTUREPROJGRAD || function == FUNCTION_TEXTUREPROJGRAD3; +} + +inline bool functionHasLod (Function function) +{ + return function == FUNCTION_TEXTURELOD || + function == FUNCTION_TEXTUREPROJLOD || + function == FUNCTION_TEXTUREPROJLOD3 || + function == FUNCTION_TEXELFETCH; +} + +struct TextureLookupSpec +{ + Function function; + + tcu::Vec4 minCoord; + tcu::Vec4 maxCoord; + + // Bias + bool useBias; + + // Bias or Lod for *Lod* functions + float minLodBias; + float maxLodBias; + + // For *Grad* functions + tcu::Vec3 minDX; + tcu::Vec3 maxDX; + tcu::Vec3 minDY; + tcu::Vec3 maxDY; + + bool useOffset; + tcu::IVec3 offset; + + TextureLookupSpec (void) + : function (FUNCTION_LAST) + , minCoord (0.0f) + , maxCoord (1.0f) + , useBias (false) + , minLodBias (0.0f) + , maxLodBias (0.0f) + , minDX (0.0f) + , maxDX (0.0f) + , minDY (0.0f) + , maxDY (0.0f) + , useOffset (false) + , offset (0) + { + } + + TextureLookupSpec (Function function_, + const tcu::Vec4& minCoord_, + const tcu::Vec4& maxCoord_, + bool useBias_, + float minLodBias_, + float maxLodBias_, + const tcu::Vec3& minDX_, + const tcu::Vec3& maxDX_, + const tcu::Vec3& minDY_, + const tcu::Vec3& maxDY_, + bool useOffset_, + const tcu::IVec3& offset_) + : function (function_) + , minCoord (minCoord_) + , maxCoord (maxCoord_) + , useBias (useBias_) + , minLodBias (minLodBias_) + , maxLodBias (maxLodBias_) + , minDX (minDX_) + , maxDX (maxDX_) + , minDY (minDY_) + , maxDY (maxDY_) + , useOffset (useOffset_) + , offset (offset_) + { + } +}; + +enum TextureType +{ + TEXTURETYPE_2D, + TEXTURETYPE_CUBE_MAP, + TEXTURETYPE_2D_ARRAY, + TEXTURETYPE_3D, + + TEXTURETYPE_LAST +}; + +struct TextureSpec +{ + TextureType type; //!< Texture type (2D, cubemap, ...) + deUint32 format; //!< Internal format. + int width; + int height; + int depth; + int numLevels; + tcu::Sampler sampler; + + TextureSpec (void) + : type (TEXTURETYPE_LAST) + , format (GL_NONE) + , width (0) + , height (0) + , depth (0) + , numLevels (0) + { + } + + TextureSpec (TextureType type_, + deUint32 format_, + int width_, + int height_, + int depth_, + int numLevels_, + const tcu::Sampler& sampler_) + : type (type_) + , format (format_) + , width (width_) + , height (height_) + , depth (depth_) + , numLevels (numLevels_) + , sampler (sampler_) + { + } +}; + +struct TexLookupParams +{ + float lod; + tcu::IVec3 offset; + tcu::Vec4 scale; + tcu::Vec4 bias; + + TexLookupParams (void) + : lod (0.0f) + , offset (0) + , scale (1.0f) + , bias (0.0f) + { + } +}; + +// \note LodMode and computeLodFromDerivates functions are copied from glsTextureTestUtil + +enum LodMode +{ + LODMODE_EXACT = 0, //!< Ideal lod computation. + LODMODE_MIN_BOUND, //!< Use estimation range minimum bound. + LODMODE_MAX_BOUND, //!< Use estimation range maximum bound. + + LODMODE_LAST +}; + +// 2D lookup LOD computation. + +float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dudy, float dvdy) +{ + float p = 0.0f; + switch (mode) + { + case LODMODE_EXACT: + p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx), deFloatSqrt(dudy*dudy + dvdy*dvdy)); + break; + + case LODMODE_MIN_BOUND: + case LODMODE_MAX_BOUND: + { + float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy)); + float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy)); + + p = mode == LODMODE_MIN_BOUND ? de::max(mu, mv) : mu + mv; + break; + } + + default: + DE_ASSERT(DE_FALSE); + } + + return deFloatLog2(p); +} + +// 3D lookup LOD computation. + +float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dwdx, float dudy, float dvdy, float dwdy) +{ + float p = 0.0f; + switch (mode) + { + case LODMODE_EXACT: + p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx + dwdx*dwdx), deFloatSqrt(dudy*dudy + dvdy*dvdy + dwdy*dwdy)); + break; + + case LODMODE_MIN_BOUND: + case LODMODE_MAX_BOUND: + { + float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy)); + float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy)); + float mw = de::max(deFloatAbs(dwdx), deFloatAbs(dwdy)); + + p = mode == LODMODE_MIN_BOUND ? de::max(de::max(mu, mv), mw) : (mu + mv + mw); + break; + } + + default: + DE_ASSERT(DE_FALSE); + } + + return deFloatLog2(p); +} + +static const LodMode DEFAULT_LOD_MODE = LODMODE_EXACT; + +inline float computeLodFromGrad2D (const ShaderEvalContext& c) +{ + float w = (float)c.textures[0].tex2D->getWidth(); + float h = (float)c.textures[0].tex2D->getHeight(); + return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[1].y()*h, c.in[2].x()*w, c.in[2].y()*h); +} + +inline float computeLodFromGrad2DArray (const ShaderEvalContext& c) +{ + float w = (float)c.textures[0].tex2DArray->getWidth(); + float h = (float)c.textures[0].tex2DArray->getHeight(); + return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[1].y()*h, c.in[2].x()*w, c.in[2].y()*h); +} + +inline float computeLodFromGrad3D (const ShaderEvalContext& c) +{ + float w = (float)c.textures[0].tex3D->getWidth(); + float h = (float)c.textures[0].tex3D->getHeight(); + float d = (float)c.textures[0].tex3D->getDepth(); + return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[1].y()*h, c.in[1].z()*d, c.in[2].x()*w, c.in[2].y()*h, c.in[2].z()*d); +} + +inline float computeLodFromGradCube (const ShaderEvalContext& c) +{ + // \note Major axis is always -Z or +Z + float m = de::abs(c.in[0].z()); + float d = (float)c.textures[0].texCube->getSize(); + float s = d/(2.0f*m); + float t = d/(2.0f*m); + return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*s, c.in[1].y()*t, c.in[2].x()*s, c.in[2].y()*t); +} + +typedef void (*TexEvalFunc) (ShaderEvalContext& c, const TexLookupParams& lookupParams); + +inline Vec4 texture2D (const 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 ShaderEvalContext& c, float s, float t, float r, float lod) { return c.textures[0].texCube->sample(c.textures[0].sampler, s, t, r, lod); } +inline Vec4 texture2DArray (const ShaderEvalContext& c, float s, float t, float r, float lod) { return c.textures[0].tex2DArray->sample(c.textures[0].sampler, s, t, r, lod); } +inline Vec4 texture3D (const ShaderEvalContext& c, float s, float t, float r, float lod) { return c.textures[0].tex3D->sample(c.textures[0].sampler, s, t, r, lod); } + +inline float texture2DShadow (const ShaderEvalContext& c, float ref, float s, float t, float lod) { return c.textures[0].tex2D->sampleCompare(c.textures[0].sampler, ref, s, t, lod); } +inline float textureCubeShadow (const ShaderEvalContext& c, float ref, float s, float t, float r, float lod) { return c.textures[0].texCube->sampleCompare(c.textures[0].sampler, ref, s, t, r, lod); } +inline float texture2DArrayShadow (const ShaderEvalContext& c, float ref, float s, float t, float r, float lod) { return c.textures[0].tex2DArray->sampleCompare(c.textures[0].sampler, ref, s, t, r, lod); } + +inline Vec4 texture2DOffset (const ShaderEvalContext& c, float s, float t, float lod, IVec2 offset) { return c.textures[0].tex2D->sampleOffset(c.textures[0].sampler, s, t, lod, offset); } +inline Vec4 texture2DArrayOffset (const ShaderEvalContext& c, float s, float t, float r, float lod, IVec2 offset) { return c.textures[0].tex2DArray->sampleOffset(c.textures[0].sampler, s, t, r, lod, offset); } +inline Vec4 texture3DOffset (const ShaderEvalContext& c, float s, float t, float r, float lod, IVec3 offset) { return c.textures[0].tex3D->sampleOffset(c.textures[0].sampler, s, t, r, lod, offset); } + +inline float texture2DShadowOffset (const ShaderEvalContext& c, float ref, float s, float t, float lod, IVec2 offset) { return c.textures[0].tex2D->sampleCompareOffset(c.textures[0].sampler, ref, s, t, lod, offset); } +inline float texture2DArrayShadowOffset (const ShaderEvalContext& c, float ref, float s, float t, float r, float lod, IVec2 offset) { return c.textures[0].tex2DArray->sampleCompareOffset(c.textures[0].sampler, ref, s, t, r, lod, offset); } + +// Eval functions. +static void evalTexture2D (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 (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 evalTexture2DArray (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; } +static void evalTexture3D (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; } + +static void evalTexture2DBias (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 (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 evalTexture2DArrayBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArray(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 evalTexture3DBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(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 (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 (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 (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 (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 evalTexture3DProj (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod)*p.scale + p.bias; } +static void evalTexture3DProjBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod+c.in[1].x())*p.scale + p.bias; } + +static void evalTexture2DLod (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 (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 evalTexture2DArrayLod (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; } +static void evalTexture3DLod (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; } + +static void evalTexture2DProjLod3 (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 (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; } +static void evalTexture3DProjLod (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), c.in[1].x())*p.scale + p.bias; } + +// Offset variants + +static void evalTexture2DOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DArrayOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture3DOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod, p.offset)*p.scale + p.bias; } + +static void evalTexture2DOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DArrayOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture3DOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x(), p.offset)*p.scale + p.bias; } + +static void evalTexture2DLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DArrayLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture3DLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x(), p.offset)*p.scale + p.bias; } + +static void evalTexture2DProj3Offset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DProj3OffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DProjOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DProjOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture3DProjOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod, p.offset)*p.scale + p.bias; } +static void evalTexture3DProjOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod+c.in[1].x(), p.offset)*p.scale + p.bias; } + +static void evalTexture2DProjLod3Offset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DProjLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture3DProjLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), c.in[1].x(), p.offset)*p.scale + p.bias; } + +// Shadow variants + +static void evalTexture2DShadow (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod); } +static void evalTexture2DShadowBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x()); } + +static void evalTextureCubeShadow (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = textureCubeShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod); } +static void evalTextureCubeShadowBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = textureCubeShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x()); } + +static void evalTexture2DArrayShadow (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DArrayShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod); } + +static void evalTexture2DShadowLod (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), c.in[1].x()); } +static void evalTexture2DShadowLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), c.in[1].x(), p.offset.swizzle(0,1)); } + +static void evalTexture2DShadowProj (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod); } +static void evalTexture2DShadowProjBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x()); } + +static void evalTexture2DShadowProjLod (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x()); } +static void evalTexture2DShadowProjLodOffset(ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x(), p.offset.swizzle(0,1)); } + +static void evalTexture2DShadowOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod, p.offset.swizzle(0,1)); } +static void evalTexture2DShadowOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x(), p.offset.swizzle(0,1)); } + +static void evalTexture2DShadowProjOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod, p.offset.swizzle(0,1)); } +static void evalTexture2DShadowProjOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x(), p.offset.swizzle(0,1)); } + +// Gradient variarts + +static void evalTexture2DGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c))*p.scale + p.bias; } +static void evalTextureCubeGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGradCube(c))*p.scale + p.bias; } +static void evalTexture2DArrayGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c))*p.scale + p.bias; } +static void evalTexture3DGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad3D(c))*p.scale + p.bias; } + +static void evalTexture2DShadowGrad (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c)); } +static void evalTextureCubeShadowGrad (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = textureCubeShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGradCube(c)); } +static void evalTexture2DArrayShadowGrad (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture2DArrayShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c)); } + +static void evalTexture2DGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DArrayGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture3DGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad3D(c), p.offset)*p.scale + p.bias; } + +static void evalTexture2DShadowGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c), p.offset.swizzle(0,1)); } +static void evalTexture2DArrayShadowGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DArrayShadowOffset(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c), p.offset.swizzle(0,1)); } + +static void evalTexture2DShadowProjGrad (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), computeLodFromGrad2D(c)); } +static void evalTexture2DShadowProjGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), computeLodFromGrad2D(c), p.offset.swizzle(0,1)); } + +static void evalTexture2DProjGrad3 (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(), computeLodFromGrad2D(c))*p.scale + p.bias; } +static void evalTexture2DProjGrad (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(), computeLodFromGrad2D(c))*p.scale + p.bias; } +static void evalTexture3DProjGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), computeLodFromGrad3D(c))*p.scale + p.bias; } + +static void evalTexture2DProjGrad3Offset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), computeLodFromGrad2D(c), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture2DProjGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), computeLodFromGrad2D(c), p.offset.swizzle(0,1))*p.scale + p.bias; } +static void evalTexture3DProjGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), computeLodFromGrad3D(c), p.offset)*p.scale + p.bias; } + +// Texel fetch variants + +static void evalTexelFetch2D (ShaderEvalContext& c, const TexLookupParams& p) +{ + int x = deChopFloatToInt32(c.in[0].x())+p.offset.x(); + int y = deChopFloatToInt32(c.in[0].y())+p.offset.y(); + int lod = deChopFloatToInt32(c.in[1].x()); + c.color = c.textures[0].tex2D->getLevel(lod).getPixel(x, y)*p.scale + p.bias; +} + +static void evalTexelFetch2DArray (ShaderEvalContext& c, const TexLookupParams& p) +{ + int x = deChopFloatToInt32(c.in[0].x())+p.offset.x(); + int y = deChopFloatToInt32(c.in[0].y())+p.offset.y(); + int l = deChopFloatToInt32(c.in[0].z()); + int lod = deChopFloatToInt32(c.in[1].x()); + c.color = c.textures[0].tex2DArray->getLevel(lod).getPixel(x, y, l)*p.scale + p.bias; +} + +static void evalTexelFetch3D (ShaderEvalContext& c, const TexLookupParams& p) +{ + int x = deChopFloatToInt32(c.in[0].x())+p.offset.x(); + int y = deChopFloatToInt32(c.in[0].y())+p.offset.y(); + int z = deChopFloatToInt32(c.in[0].z())+p.offset.z(); + int lod = deChopFloatToInt32(c.in[1].x()); + c.color = c.textures[0].tex3D->getLevel(lod).getPixel(x, y, z)*p.scale + p.bias; +} + +class TexLookupEvaluator : public ShaderEvaluator +{ +public: + TexLookupEvaluator (TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {} + virtual ~TexLookupEvaluator (void) {} + + virtual void evaluate (ShaderEvalContext& ctx) const { m_evalFunc(ctx, m_lookupParams); } + +private: + TexEvalFunc m_evalFunc; + const TexLookupParams& m_lookupParams; +}; + +class ShaderTextureFunctionInstance : public ShaderRenderCaseInstance +{ +public: + ShaderTextureFunctionInstance (Context& context, + const bool isVertexCase, + const ShaderEvaluator& evaluator, + const UniformSetup& uniformSetup, + const TextureLookupSpec& lookupSpec, + const TextureSpec& textureSpec, + const TexLookupParams& lookupParams); + virtual ~ShaderTextureFunctionInstance (void); + +protected: + virtual void setupUniforms (const tcu::Vec4&); + void initTexture (void); + +private: + const TextureLookupSpec& m_lookupSpec; + const TextureSpec& m_textureSpec; + const TexLookupParams& m_lookupParams; +}; + +ShaderTextureFunctionInstance::ShaderTextureFunctionInstance (Context& context, + const bool isVertexCase, + const ShaderEvaluator& evaluator, + const UniformSetup& uniformSetup, + const TextureLookupSpec& lookupSpec, + const TextureSpec& textureSpec, + const TexLookupParams& lookupParams) + : ShaderRenderCaseInstance (context, isVertexCase, evaluator, uniformSetup, DE_NULL) + , m_lookupSpec (lookupSpec) + , m_textureSpec (textureSpec) + , m_lookupParams (lookupParams) +{ + { + // 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)); + + useAttribute(4u, A_IN0); + } + + bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias; + bool isGrad = functionHasGrad(m_lookupSpec.function); + DE_ASSERT(!isGrad || !hasLodBias); + + if (hasLodBias) + { + 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)); + + useAttribute(5u, A_IN1); + } + else if (isGrad) + { + Vec3 sx = m_lookupSpec.maxDX-m_lookupSpec.minDX; + Vec3 sy = m_lookupSpec.maxDY-m_lookupSpec.minDY; + float gradDxTrans[] = + { + sx.x()/2.0f, sx.x()/2.0f, 0.f, m_lookupSpec.minDX.x(), + sx.y()/2.0f, sx.y()/2.0f, 0.0f, m_lookupSpec.minDX.y(), + sx.z()/2.0f, sx.z()/2.0f, 0.0f, m_lookupSpec.minDX.z(), + 0.0f, 0.0f, 0.0f, 0.0f + }; + float gradDyTrans[] = + { + -sy.x()/2.0f, -sy.x()/2.0f, 0.f, m_lookupSpec.maxDY.x(), + -sy.y()/2.0f, -sy.y()/2.0f, 0.0f, m_lookupSpec.maxDY.y(), + -sy.z()/2.0f, -sy.z()/2.0f, 0.0f, m_lookupSpec.maxDY.z(), + 0.0f, 0.0f, 0.0f, 0.0f + }; + + m_userAttribTransforms.push_back(tcu::Mat4(gradDxTrans)); + m_userAttribTransforms.push_back(tcu::Mat4(gradDyTrans)); + + useAttribute(5u, A_IN1); + useAttribute(6u, A_IN2); + } + + initTexture(); +} + +ShaderTextureFunctionInstance::~ShaderTextureFunctionInstance (void) +{ +} + +void ShaderTextureFunctionInstance::setupUniforms (const tcu::Vec4&) +{ + useSampler(0u, 0u); + addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec4), m_lookupParams.scale.getPtr()); + addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec4), m_lookupParams.bias.getPtr()); +} + +void ShaderTextureFunctionInstance::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::mapGLInternalFormat(m_textureSpec.format); + tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); + tcu::UVec2 viewportSize = getViewportSize(); + bool isProj = functionHasProj(m_lookupSpec.function); + bool isAutoLod = functionHasAutoLod(m_isVertexCase ? glu::SHADERTYPE_VERTEX : glu::SHADERTYPE_FRAGMENT, + m_lookupSpec.function); // LOD can vary significantly + float proj = isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f; + TexLookupParams lookupParams; + + switch (m_textureSpec.type) + { + case TEXTURETYPE_2D: + { + float levelStep = isAutoLod ? 0.0f : 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::MovePtr texture2D; + + texture2D = de::MovePtr(new tcu::Texture2D(texFmt, m_textureSpec.width, m_textureSpec.height)); + + for (int level = 0; level < m_textureSpec.numLevels; level++) + { + float fA = float(level)*levelStep; + float fB = 1.0f-fA; + Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB); + Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA); + + texture2D->allocLevel(level); + tcu::fillWithGrid(texture2D->getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB); + } + + // 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]; + lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, 0.0f, dvdy); + + // Append to texture list. + m_textures.push_back(TextureBindingSp(new TextureBinding(texture2D.release(), m_textureSpec.sampler))); + break; + } + + case TEXTURETYPE_CUBE_MAP: + { + float levelStep = isAutoLod ? 0.0f : 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); + Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; + Vec4 cBias = fmtInfo.valueMin; + Vec4 cCorner = cBias + cScale*0.5f; + int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); + de::MovePtr textureCube; + + DE_ASSERT(m_textureSpec.width == m_textureSpec.height); + textureCube = de::MovePtr(new tcu::TextureCube(texFmt, m_textureSpec.width)); + + for (int level = 0; level < m_textureSpec.numLevels; level++) + { + float fA = float(level)*levelStep; + 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]); + + textureCube->allocLevel((tcu::CubeFace)face, level); + + { + const tcu::PixelBufferAccess access = textureCube->getLevelFace(level, (tcu::CubeFace)face); + const int lastPix = access.getWidth()-1; + + tcu::fillWithGrid(access, de::max(1, baseCellSize>>level), colorA, colorB); + + // Ensure all corners have identical colors in order to avoid dealing with ambiguous corner texel filtering + access.setPixel(cCorner, 0, 0); + access.setPixel(cCorner, 0, lastPix); + access.setPixel(cCorner, lastPix, 0); + access.setPixel(cCorner, lastPix, lastPix); + } + } + } + + // 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]; + lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, 0.0f, dvdy); + + // Append to texture list. + m_textures.push_back(TextureBindingSp(new TextureBinding(textureCube.release(), m_textureSpec.sampler))); + break; + } + + case TEXTURETYPE_2D_ARRAY: + { + float layerStep = 1.0f / (float)m_textureSpec.depth; + float levelStep = isAutoLod ? 0.0f : 1.0f / (float)(de::max(1, m_textureSpec.numLevels-1)*m_textureSpec.depth); + Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; + Vec4 cBias = fmtInfo.valueMin; + int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); + de::MovePtr texture2DArray; + + texture2DArray = de::MovePtr(new tcu::Texture2DArray(texFmt, m_textureSpec.width, m_textureSpec.height, m_textureSpec.depth)); + + for (int level = 0; level < m_textureSpec.numLevels; level++) + { + texture2DArray->allocLevel(level); + tcu::PixelBufferAccess levelAccess = texture2DArray->getLevel(level); + + for (int layer = 0; layer < levelAccess.getDepth(); layer++) + { + float fA = (float)layer*layerStep + (float)level*levelStep; + float fB = 1.0f-fA; + Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB); + Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA); + + tcu::fillWithGrid(tcu::getSubregion(levelAccess, 0, 0, layer, levelAccess.getWidth(), levelAccess.getHeight(), 1), de::max(1, baseCellSize>>level), colorA, colorB); + } + } + + // 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]; + lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, 0.0f, dvdy); + + // Append to texture list. + m_textures.push_back(TextureBindingSp(new TextureBinding(texture2DArray.release(), m_textureSpec.sampler))); + break; + } + + case TEXTURETYPE_3D: + { + float levelStep = isAutoLod ? 0.0f : 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); + Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; + Vec4 cBias = fmtInfo.valueMin; + int baseCellSize = de::min(de::min(m_textureSpec.width/2, m_textureSpec.height/2), m_textureSpec.depth/2); + de::MovePtr texture3D; + + texture3D = de::MovePtr(new tcu::Texture3D(texFmt, m_textureSpec.width, m_textureSpec.height, m_textureSpec.depth)); + + for (int level = 0; level < m_textureSpec.numLevels; level++) + { + float fA = (float)level*levelStep; + float fB = 1.0f-fA; + Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB); + Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA); + + texture3D->allocLevel(level); + tcu::fillWithGrid(texture3D->getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB); + } + + // 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]; + float dwdx = (m_lookupSpec.maxCoord[2]-m_lookupSpec.minCoord[2])*0.5f*proj*(float)m_textureSpec.depth / (float)viewportSize[0]; + float dwdy = (m_lookupSpec.maxCoord[2]-m_lookupSpec.minCoord[2])*0.5f*proj*(float)m_textureSpec.depth / (float)viewportSize[1]; + lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, dwdx, 0.0f, dvdy, dwdy); + + // Append to texture list. + m_textures.push_back(TextureBindingSp(new TextureBinding(texture3D.release(), m_textureSpec.sampler))); + break; + } + + default: + DE_ASSERT(DE_FALSE); + } + + // Set lookup scale & bias + lookupParams.scale = fmtInfo.lookupScale; + lookupParams.bias = fmtInfo.lookupBias; + lookupParams.offset = m_lookupSpec.offset; + + // \todo [dirnerakos] Avoid const cast somehow + const_cast(m_lookupParams) = lookupParams; +} + +class ShaderTextureFunctionCase : public ShaderRenderCase +{ +public: + ShaderTextureFunctionCase (tcu::TestContext& testCtx, + const std::string& name, + const std::string& desc, + const TextureLookupSpec& lookup, + const TextureSpec& texture, + TexEvalFunc evalFunc, + bool isVertexCase); + virtual ~ShaderTextureFunctionCase (void); + + virtual TestInstance* createInstance (Context& context) const; + +private: + void initShaderSources (void); + + TextureLookupSpec m_lookupSpec; + TextureSpec m_textureSpec; + TexLookupParams m_lookupParams; +}; + +ShaderTextureFunctionCase::ShaderTextureFunctionCase (tcu::TestContext& testCtx, + const std::string& name, + const std::string& desc, + const TextureLookupSpec& lookup, + const TextureSpec& texture, + TexEvalFunc evalFunc, + bool isVertexCase) + : ShaderRenderCase (testCtx, name, desc, isVertexCase, new TexLookupEvaluator(evalFunc, m_lookupParams), NULL, NULL) + , m_lookupSpec (lookup) + , m_textureSpec (texture) +{ + initShaderSources(); +} + +ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void) +{ +} + +TestInstance* ShaderTextureFunctionCase::createInstance (Context& context) const +{ + DE_ASSERT(m_evaluator != DE_NULL); + DE_ASSERT(m_uniformSetup != DE_NULL); + return new ShaderTextureFunctionInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_lookupSpec, m_textureSpec, m_lookupParams); +} + +void ShaderTextureFunctionCase::initShaderSources (void) +{ + Function function = m_lookupSpec.function; + bool isVtxCase = m_isVertexCase; + bool isProj = functionHasProj(function); + bool isGrad = functionHasGrad(function); + bool isShadow = m_textureSpec.sampler.compare != tcu::Sampler::COMPAREMODE_NONE; + bool is2DProj4 = !isShadow && m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD || function == FUNCTION_TEXTUREPROJGRAD); + bool isIntCoord = function == FUNCTION_TEXELFETCH; + 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) + (isShadow ? 1 : 0); + glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps+extraCoordComps); + glu::Precision coordPrec = glu::PRECISION_HIGHP; + const char* coordTypeName = glu::getDataTypeName(coordType); + const char* coordPrecName = glu::getPrecisionName(coordPrec); + tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_textureSpec.format); + glu::DataType samplerType = glu::TYPE_LAST; + glu::DataType gradType = (m_textureSpec.type == TEXTURETYPE_CUBE_MAP || m_textureSpec.type == TEXTURETYPE_3D) ? glu::TYPE_FLOAT_VEC3 : glu::TYPE_FLOAT_VEC2; + const char* gradTypeName = glu::getDataTypeName(gradType); + const char* baseFuncName = DE_NULL; + + DE_ASSERT(!isGrad || !hasLodBias); + + switch (m_textureSpec.type) + { + case TEXTURETYPE_2D: samplerType = isShadow ? glu::TYPE_SAMPLER_2D_SHADOW : glu::getSampler2DType(texFmt); break; + case TEXTURETYPE_CUBE_MAP: samplerType = isShadow ? glu::TYPE_SAMPLER_CUBE_SHADOW : glu::getSamplerCubeType(texFmt); break; + case TEXTURETYPE_2D_ARRAY: samplerType = isShadow ? glu::TYPE_SAMPLER_2D_ARRAY_SHADOW : glu::getSampler2DArrayType(texFmt); break; + case TEXTURETYPE_3D: DE_ASSERT(!isShadow); samplerType = glu::getSampler3DType(texFmt); break; + default: + DE_ASSERT(DE_FALSE); + } + + switch (m_lookupSpec.function) + { + case FUNCTION_TEXTURE: baseFuncName = "texture"; break; + case FUNCTION_TEXTUREPROJ: baseFuncName = "textureProj"; break; + case FUNCTION_TEXTUREPROJ3: baseFuncName = "textureProj"; break; + case FUNCTION_TEXTURELOD: baseFuncName = "textureLod"; break; + case FUNCTION_TEXTUREPROJLOD: baseFuncName = "textureProjLod"; break; + case FUNCTION_TEXTUREPROJLOD3: baseFuncName = "textureProjLod"; break; + case FUNCTION_TEXTUREGRAD: baseFuncName = "textureGrad"; break; + case FUNCTION_TEXTUREPROJGRAD: baseFuncName = "textureProjGrad"; break; + case FUNCTION_TEXTUREPROJGRAD3: baseFuncName = "textureProjGrad"; break; + case FUNCTION_TEXELFETCH: baseFuncName = "texelFetch"; break; + default: + DE_ASSERT(DE_FALSE); + } + + std::ostringstream vert; + std::ostringstream frag; + std::ostringstream& op = isVtxCase ? vert : frag; + + vert << "#version 310 es\n" + << "layout(location = 0) in highp vec4 a_position;\n" + << "layout(location = 4) in " << coordPrecName << " " << coordTypeName << " a_in0;\n"; + + if (isGrad) + { + vert << "layout(location = 5) in " << coordPrecName << " " << gradTypeName << " a_in1;\n"; + vert << "layout(location = 6) in " << coordPrecName << " " << gradTypeName << " a_in2;\n"; + } + else if (hasLodBias) + vert << "layout(location = 5) in " << coordPrecName << " float a_in1;\n"; + + frag << "#version 310 es\n" + << "layout(location = 0) out mediump vec4 o_color;\n"; + + if (isVtxCase) + { + vert << "layout(location = 0) out mediump vec4 v_color;\n"; + frag << "layout(location = 0) in mediump vec4 v_color;\n"; + } + else + { + vert << "layout(location = 0) out " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; + frag << "layout(location = 0) in " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; + + if (isGrad) + { + vert << "layout(location = 1) out " << coordPrecName << " " << gradTypeName << " v_gradX;\n"; + vert << "layout(location = 2) out " << coordPrecName << " " << gradTypeName << " v_gradY;\n"; + frag << "layout(location = 1) in " << coordPrecName << " " << gradTypeName << " v_gradX;\n"; + frag << "layout(location = 2) in " << coordPrecName << " " << gradTypeName << " v_gradY;\n"; + } + else if (hasLodBias) + { + vert << "layout(location = 1) out " << coordPrecName << " float v_lodBias;\n"; + frag << "layout(location = 1) in " << coordPrecName << " float v_lodBias;\n"; + } + } + + // Uniforms + op << "layout(set = 0, binding = 0) uniform highp " << glu::getDataTypeName(samplerType) << " u_sampler;\n" + << "layout(set = 0, binding = 1) uniform buf0 { highp vec4 u_scale; };\n" + << "layout(set = 0, binding = 2) uniform buf1 { highp vec4 u_bias; };\n"; + + vert << "\nvoid main()\n{\n" + << "\tgl_Position = a_position;\n"; + frag << "\nvoid main()\n{\n"; + + if (isVtxCase) + vert << "\tv_color = "; + else + frag << "\to_color = "; + + // Op. + { + const char* texCoord = isVtxCase ? "a_in0" : "v_texCoord"; + const char* gradX = isVtxCase ? "a_in1" : "v_gradX"; + const char* gradY = isVtxCase ? "a_in2" : "v_gradY"; + const char* lodBias = isVtxCase ? "a_in1" : "v_lodBias"; + + op << "vec4(" << baseFuncName; + if (m_lookupSpec.useOffset) + op << "Offset"; + op << "(u_sampler, "; + + if (isIntCoord) + op << "ivec" << (texCoordComps+extraCoordComps) << "("; + + op << texCoord; + + if (isIntCoord) + op << ")"; + + if (isGrad) + op << ", " << gradX << ", " << gradY; + + if (functionHasLod(function)) + { + if (isIntCoord) + op << ", int(" << lodBias << ")"; + else + op << ", " << lodBias; + } + + if (m_lookupSpec.useOffset) + { + int offsetComps = m_textureSpec.type == TEXTURETYPE_3D ? 3 : 2; + + op << ", ivec" << offsetComps << "("; + for (int ndx = 0; ndx < offsetComps; ndx++) + { + if (ndx != 0) + op << ", "; + op << m_lookupSpec.offset[ndx]; + } + op << ")"; + } + + if (m_lookupSpec.useBias) + op << ", " << lodBias; + + op << ")"; + + if (isShadow) + op << ", 0.0, 0.0, 1.0)"; + else + op << ")*u_scale + u_bias"; + + op << ";\n"; + } + + if (isVtxCase) + frag << "\to_color = v_color;\n"; + else + { + vert << "\tv_texCoord = a_in0;\n"; + + if (isGrad) + { + vert << "\tv_gradX = a_in1;\n"; + vert << "\tv_gradY = a_in2;\n"; + } + else if (hasLodBias) + vert << "\tv_lodBias = a_in1;\n"; + } + + vert << "}\n"; + frag << "}\n"; + + m_vertShaderSource = vert.str(); + m_fragShaderSource = frag.str(); +} + +class TextureSizeInstance : public ShaderRenderCaseInstance +{ +public: + TextureSizeInstance (Context& context, + const bool isVertexCase, + const TextureSpec& textureSpec); + virtual ~TextureSizeInstance (void); + + virtual tcu::TestStatus iterate (void); + +protected: + virtual void setupDefaultInputs (void); + virtual void setupUniforms (const tcu::Vec4&); + +private: + struct TestSize + { + tcu::IVec3 textureSize; + int lod; + int lodBase; + tcu::IVec3 expectedSize; + }; + + void initTexture (void); + bool testTextureSize (void); + + const TextureSpec& m_textureSpec; + TestSize m_testSize; + int m_iterationCounter; +}; + +TextureSizeInstance::TextureSizeInstance (Context& context, + const bool isVertexCase, + const TextureSpec& textureSpec) + : ShaderRenderCaseInstance (context, isVertexCase, DE_NULL, DE_NULL, DE_NULL) + , m_textureSpec (textureSpec) + , m_testSize () + , m_iterationCounter (0) +{ + deMemset(&m_testSize, 0, sizeof(TestSize)); + + m_renderSize = tcu::UVec2(1, 1); +} + +TextureSizeInstance::~TextureSizeInstance (void) +{ +} + +void TextureSizeInstance::setupDefaultInputs (void) +{ + const tcu::Vec4 triangle[3] = // covers entire viewport + { + tcu::Vec4(-1, -1, 0, 1), + tcu::Vec4( 4, -1, 0, 1), + tcu::Vec4(-1, 4, 0, 1), + }; + + addAttribute(0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), 3, triangle); +} + +void TextureSizeInstance::setupUniforms (const tcu::Vec4&) +{ + const tcu::IVec3 expectedSize = m_textureSpec.type == TEXTURETYPE_2D_ARRAY ? tcu::IVec3(m_testSize.expectedSize.x(), m_testSize.expectedSize.y(), m_testSize.textureSize.z()) : m_testSize.expectedSize; + + useSampler(0u, 0u); + addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec3), expectedSize.getPtr()); + addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(int), &m_testSize.lod); +} + +void TextureSizeInstance::initTexture (void) +{ + tcu::TestLog& log = m_context.getTestContext().getLog(); + const tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_textureSpec.format); + const int maxLevel = m_testSize.lod + m_testSize.lodBase; + const int levels = maxLevel + 1; + const TextureBinding::Parameters params (m_testSize.lodBase); + TextureBindingSp textureBinding; + + switch (m_textureSpec.type) + { + case TEXTURETYPE_3D: + { + de::MovePtr texture (new tcu::Texture3D(texFmt, m_testSize.textureSize.x(), m_testSize.textureSize.y(), m_testSize.textureSize.z())); + + for (int level = 0; level < levels; level++) + texture->allocLevel(level); + + log << tcu::TestLog::Message << "Testing image size " << m_testSize.textureSize.x() << "x" << m_testSize.textureSize.y() << "x" << m_testSize.textureSize.z() << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Lod: " << m_testSize.lod << ", base level: " << m_testSize.lodBase << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << "x" << m_testSize.expectedSize.z() << tcu::TestLog::EndMessage; + + textureBinding = TextureBindingSp(new TextureBinding(texture.release(), m_textureSpec.sampler)); + break; + } + + case TEXTURETYPE_2D: + { + de::MovePtr texture (new tcu::Texture2D(texFmt, m_testSize.textureSize.x(), m_testSize.textureSize.y())); + + for (int level = 0; level < levels; level++) + texture->allocLevel(level); + + log << tcu::TestLog::Message << "Testing image size " << m_testSize.textureSize.x() << "x" << m_testSize.textureSize.y() << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Lod: " << m_testSize.lod << ", base level: " << m_testSize.lodBase << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << tcu::TestLog::EndMessage; + + textureBinding = TextureBindingSp(new TextureBinding(texture.release(), m_textureSpec.sampler)); + break; + } + + case TEXTURETYPE_CUBE_MAP: + { + de::MovePtr texture (new tcu::TextureCube(texFmt, m_testSize.textureSize.x())); + + for (int level = 0; level < levels; level++) + for (int face = 0; face < tcu::CUBEFACE_LAST; face++) + texture->allocLevel((tcu::CubeFace)face, level); + + log << tcu::TestLog::Message << "Testing image size " << m_testSize.textureSize.x() << "x" << m_testSize.textureSize.y() << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Lod: " << m_testSize.lod << ", base level: " << m_testSize.lodBase << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << tcu::TestLog::EndMessage; + + textureBinding = TextureBindingSp(new TextureBinding(texture.release(), m_textureSpec.sampler)); + break; + } + + case TEXTURETYPE_2D_ARRAY: + { + de::MovePtr texture (new tcu::Texture2DArray(texFmt, m_testSize.textureSize.x(), m_testSize.textureSize.y(), m_testSize.textureSize.z())); + + for (int level = 0; level < levels; level++) + texture->allocLevel(level); + + log << tcu::TestLog::Message << "Testing image size " << m_testSize.textureSize.x() << "x" << m_testSize.textureSize.y() << " with " << m_testSize.textureSize.z() << " layer(s)" << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Lod: " << m_testSize.lod << ", base level: " << m_testSize.lodBase << tcu::TestLog::EndMessage; + log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << " and " << m_testSize.textureSize.z() << " layer(s)" << tcu::TestLog::EndMessage; + + textureBinding = TextureBindingSp(new TextureBinding(texture.release(), m_textureSpec.sampler)); + break; + } + + default: + DE_ASSERT(false); + break; + } + + m_textures.clear(); + + textureBinding->setParameters(params); + m_textures.push_back(textureBinding); +} + +tcu::TestStatus TextureSizeInstance::iterate (void) +{ + const TestSize testSizes[] = + { + { tcu::IVec3(1, 2, 1), 1, 0, tcu::IVec3(1, 1, 1) }, + { tcu::IVec3(1, 2, 1), 0, 0, tcu::IVec3(1, 2, 1) }, + + { tcu::IVec3(1, 3, 2), 0, 0, tcu::IVec3(1, 3, 2) }, + { tcu::IVec3(1, 3, 2), 1, 0, tcu::IVec3(1, 1, 1) }, + + { tcu::IVec3(100, 31, 18), 0, 0, tcu::IVec3(100, 31, 18) }, + { tcu::IVec3(100, 31, 18), 1, 0, tcu::IVec3(50, 15, 9) }, + { tcu::IVec3(100, 31, 18), 2, 0, tcu::IVec3(25, 7, 4) }, + { tcu::IVec3(100, 31, 18), 3, 0, tcu::IVec3(12, 3, 2) }, + { tcu::IVec3(100, 31, 18), 4, 0, tcu::IVec3(6, 1, 1) }, + { tcu::IVec3(100, 31, 18), 5, 0, tcu::IVec3(3, 1, 1) }, + { tcu::IVec3(100, 31, 18), 6, 0, tcu::IVec3(1, 1, 1) }, + + { tcu::IVec3(100, 128, 32), 0, 0, tcu::IVec3(100, 128, 32) }, + { tcu::IVec3(100, 128, 32), 1, 0, tcu::IVec3(50, 64, 16) }, + { tcu::IVec3(100, 128, 32), 2, 0, tcu::IVec3(25, 32, 8) }, + { tcu::IVec3(100, 128, 32), 3, 0, tcu::IVec3(12, 16, 4) }, + { tcu::IVec3(100, 128, 32), 4, 0, tcu::IVec3(6, 8, 2) }, + { tcu::IVec3(100, 128, 32), 5, 0, tcu::IVec3(3, 4, 1) }, + { tcu::IVec3(100, 128, 32), 6, 0, tcu::IVec3(1, 2, 1) }, + { tcu::IVec3(100, 128, 32), 7, 0, tcu::IVec3(1, 1, 1) }, + + // pow 2 + { tcu::IVec3(128, 64, 32), 0, 0, tcu::IVec3(128, 64, 32) }, + { tcu::IVec3(128, 64, 32), 1, 0, tcu::IVec3(64, 32, 16) }, + { tcu::IVec3(128, 64, 32), 2, 0, tcu::IVec3(32, 16, 8) }, + { tcu::IVec3(128, 64, 32), 3, 0, tcu::IVec3(16, 8, 4) }, + { tcu::IVec3(128, 64, 32), 4, 0, tcu::IVec3(8, 4, 2) }, + { tcu::IVec3(128, 64, 32), 5, 0, tcu::IVec3(4, 2, 1) }, + { tcu::IVec3(128, 64, 32), 6, 0, tcu::IVec3(2, 1, 1) }, + { tcu::IVec3(128, 64, 32), 7, 0, tcu::IVec3(1, 1, 1) }, + + // w == h + { tcu::IVec3(1, 1, 1), 0, 0, tcu::IVec3(1, 1, 1) }, + { tcu::IVec3(64, 64, 64), 0, 0, tcu::IVec3(64, 64, 64) }, + { tcu::IVec3(64, 64, 64), 1, 0, tcu::IVec3(32, 32, 32) }, + { tcu::IVec3(64, 64, 64), 2, 0, tcu::IVec3(16, 16, 16) }, + { tcu::IVec3(64, 64, 64), 3, 0, tcu::IVec3(8, 8, 8) }, + { tcu::IVec3(64, 64, 64), 4, 0, tcu::IVec3(4, 4, 4) }, + + // with lod base + { tcu::IVec3(100, 31, 18), 3, 1, tcu::IVec3(6, 1, 1) }, + { tcu::IVec3(128, 64, 32), 3, 1, tcu::IVec3(8, 4, 2) }, + { tcu::IVec3(64, 64, 64), 1, 1, tcu::IVec3(16, 16, 16) }, + }; + const int lastIterationIndex = DE_LENGTH_OF_ARRAY(testSizes) + 1; + + m_iterationCounter++; + + if (m_iterationCounter == lastIterationIndex) + return tcu::TestStatus::pass("Pass"); + else + { + // set current test size + m_testSize = testSizes[m_iterationCounter - 1]; + + if (!testTextureSize()) + return tcu::TestStatus::fail("Got unexpected texture size"); + + return tcu::TestStatus::incomplete(); + } +} + +bool TextureSizeInstance::testTextureSize (void) +{ + tcu::TestLog& log = m_context.getTestContext().getLog(); + const bool isSquare = m_testSize.textureSize.x() == m_testSize.textureSize.y(); + const bool is2DLodValid = (m_testSize.textureSize.x() >> (m_testSize.lod + m_testSize.lodBase)) != 0 || (m_testSize.textureSize.y() >> (m_testSize.lod + m_testSize.lodBase)) != 0; + bool success = true; + + // Skip incompatible cases + if (m_textureSpec.type == TEXTURETYPE_CUBE_MAP && !isSquare) + return true; + if (m_textureSpec.type == TEXTURETYPE_2D && !is2DLodValid) + return true; + if (m_textureSpec.type == TEXTURETYPE_2D_ARRAY && !is2DLodValid) + return true; + + // setup texture + initTexture(); + + // render + { + const deUint16 indices[3] = { 0, 1, 2 }; + + setup(); + render(3, 1, indices); + } + + // test + { + const float colorTolerance = 0.1f; + const tcu::TextureLevel& result = getResultImage(); + tcu::Vec4 outputColor = result.getAccess().getPixel(0, 0); + + if (outputColor.x() >= 1.0f - colorTolerance && + outputColor.y() >= 1.0f - colorTolerance && + outputColor.z() >= 1.0f - colorTolerance) + { + // success + log << tcu::TestLog::Message << "Passed" << tcu::TestLog::EndMessage; + } + else + { + // failure + log << tcu::TestLog::Message << "Failed" << tcu::TestLog::EndMessage; + success = false; + } + } + + // empty line to format log nicely + log << tcu::TestLog::Message << tcu::TestLog::EndMessage; + + return success; +} + +class TextureSizeCase : public ShaderRenderCase +{ +public: + TextureSizeCase (tcu::TestContext& testCtx, + const std::string& name, + const std::string& desc, + const std::string& samplerType, + const TextureSpec& texture, + bool isVertexCase); + virtual ~TextureSizeCase (void); + + virtual TestInstance* createInstance (Context& context) const; + +private: + std::string genVertexShader (void) const; + std::string genFragmentShader (void) const; + + const std::string m_samplerTypeStr; + const TextureSpec m_textureSpec; + const bool m_isVertexCase; + const bool m_has3DSize; +}; + +TextureSizeCase::TextureSizeCase (tcu::TestContext& testCtx, + const std::string& name, + const std::string& desc, + const std::string& samplerType, + const TextureSpec& texture, + bool isVertexCase) + : ShaderRenderCase (testCtx, name, desc, isVertexCase, (ShaderEvaluator*)DE_NULL, DE_NULL, DE_NULL) + , m_samplerTypeStr (samplerType) + , m_textureSpec (texture) + , m_isVertexCase (isVertexCase) + , m_has3DSize (texture.type == TEXTURETYPE_3D || texture.type == TEXTURETYPE_2D_ARRAY) +{ + m_vertShaderSource = genVertexShader(); + m_fragShaderSource = genFragmentShader(); +} + +TextureSizeCase::~TextureSizeCase (void) +{ +} + +TestInstance* TextureSizeCase::createInstance (Context& context) const +{ + return new TextureSizeInstance(context, m_isVertexCase, m_textureSpec); +} + +std::string TextureSizeCase::genVertexShader() const +{ + std::ostringstream vert; + + vert << "#version 310 es\n" + << "layout(location = 0) in highp vec4 a_position;\n"; + + if (m_isVertexCase) + { + vert << "layout(location = 0) out mediump vec4 v_color;\n"; + vert << "layout(set = 0, binding = 0) uniform highp " << m_samplerTypeStr << " u_sampler;\n"; + vert << "layout(set = 0, binding = 1) uniform buf0 { highp ivec" << (m_has3DSize ? 3 : 2) << " u_texSize; };\n"; + vert << "layout(set = 0, binding = 2) uniform buf1 { highp int u_lod; };\n"; + } + + vert << "void main()\n{\n"; + + if (m_isVertexCase) + vert << " v_color = (textureSize(u_sampler, u_lod) == u_texSize ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.0, 0.0, 1.0, 0.0));\n"; + + vert << " gl_Position = a_position;\n" + << "}\n"; + + return vert.str(); +} + +std::string TextureSizeCase::genFragmentShader() const +{ + std::ostringstream frag; + + frag << "#version 310 es\n" + << "layout(location = 0) out mediump vec4 o_color;\n"; + + if (m_isVertexCase) + frag << "layout(location = 0) in mediump vec4 v_color;\n"; + + if (!m_isVertexCase) + { + frag << "layout(set = 0, binding = 0) uniform highp " << m_samplerTypeStr << " u_sampler;\n"; + frag << "layout(set = 0, binding = 1) uniform buf0 { highp ivec" << (m_has3DSize ? 3 : 2) << " u_texSize; };\n"; + frag << "layout(set = 0, binding = 2) uniform buf1 { highp int u_lod; };\n"; + } + + frag << "void main()\n{\n"; + + if (!m_isVertexCase) + frag << " o_color = (textureSize(u_sampler, u_lod) == u_texSize ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n"; + else + frag << " o_color = v_color;\n"; + + frag << "}\n"; + + return frag.str(); +} + +class ShaderTextureFunctionTests : public tcu::TestCaseGroup +{ +public: + ShaderTextureFunctionTests (tcu::TestContext& context); + virtual ~ShaderTextureFunctionTests (void); + virtual void init (void); + +private: + ShaderTextureFunctionTests (const ShaderTextureFunctionTests&); // not allowed! + ShaderTextureFunctionTests& operator= (const ShaderTextureFunctionTests&); // not allowed! +}; + +ShaderTextureFunctionTests::ShaderTextureFunctionTests (tcu::TestContext& context) + : TestCaseGroup(context, "texture_functions", "Texture Access Function Tests") +{ +} + +ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void) +{ +} + +enum CaseFlags +{ + VERTEX = (1<<0), + FRAGMENT = (1<<1), + BOTH = VERTEX|FRAGMENT +}; + +struct TexFuncCaseSpec +{ + const char* name; + TextureLookupSpec lookupSpec; + TextureSpec texSpec; + TexEvalFunc evalFunc; + deUint32 flags; +}; + +#define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, USEOFFSET, OFFSET, TEXSPEC, EVALFUNC, FLAGS) \ + { #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, tcu::Vec3(0.0f), tcu::Vec3(0.0f), tcu::Vec3(0.0f), tcu::Vec3(0.0f), USEOFFSET, OFFSET), TEXSPEC, EVALFUNC, FLAGS } +#define GRAD_CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, MINDX, MAXDX, MINDY, MAXDY, USEOFFSET, OFFSET, TEXSPEC, EVALFUNC, FLAGS) \ + { #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, false, 0.0f, 0.0f, MINDX, MAXDX, MINDY, MAXDY, USEOFFSET, OFFSET), TEXSPEC, EVALFUNC, FLAGS } + +static void createCaseGroup (tcu::TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases) +{ + de::MovePtr group (new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc)); + + for (int ndx = 0; ndx < numCases; ndx++) + { + std::string name = cases[ndx].name; + if (cases[ndx].flags & VERTEX) + group->addChild(new ShaderTextureFunctionCase(parent->getTestContext(), (name + "_vertex"), "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, true )); + if (cases[ndx].flags & FRAGMENT) + group->addChild(new ShaderTextureFunctionCase(parent->getTestContext(), (name + "_fragment"), "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, false)); + } + + parent->addChild(group.release()); +} + +void ShaderTextureFunctionTests::init (void) +{ + // Samplers + static const tcu::Sampler samplerNearestNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, + tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, + 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE, + 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */); + static const tcu::Sampler samplerLinearNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, + tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, + 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE, + 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */); + static const tcu::Sampler samplerNearestMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, + tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST, + 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE, + 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */); + static const tcu::Sampler samplerLinearMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, + tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR, + 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE, + 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */); + + static const tcu::Sampler samplerShadowNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, + tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, + 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_LESS, + 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */); + static const tcu::Sampler samplerShadowMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, + tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST, + 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_LESS, + 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */); + + static const tcu::Sampler samplerTexelFetch (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, + tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST, + 0.0f /* LOD threshold */, false /* non-normalized coords */, tcu::Sampler::COMPAREMODE_NONE, + 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */); + + // Default textures. + // Type Format W H D L Sampler + static const TextureSpec tex2DFixed (TEXTURETYPE_2D, GL_RGBA8, 256, 256, 1, 1, samplerLinearNoMipmap); + static const TextureSpec tex2DFloat (TEXTURETYPE_2D, GL_RGBA16F, 256, 256, 1, 1, samplerLinearNoMipmap); + static const TextureSpec tex2DInt (TEXTURETYPE_2D, GL_RGBA8I, 256, 256, 1, 1, samplerNearestNoMipmap); + static const TextureSpec tex2DUint (TEXTURETYPE_2D, GL_RGBA8UI, 256, 256, 1, 1, samplerNearestNoMipmap); + static const TextureSpec tex2DMipmapFixed (TEXTURETYPE_2D, GL_RGBA8, 256, 256, 1, 9, samplerLinearMipmap); + static const TextureSpec tex2DMipmapFloat (TEXTURETYPE_2D, GL_RGBA16F, 256, 256, 1, 9, samplerLinearMipmap); + static const TextureSpec tex2DMipmapInt (TEXTURETYPE_2D, GL_RGBA8I, 256, 256, 1, 9, samplerNearestMipmap); + static const TextureSpec tex2DMipmapUint (TEXTURETYPE_2D, GL_RGBA8UI, 256, 256, 1, 9, samplerNearestMipmap); + + static const TextureSpec tex2DShadow (TEXTURETYPE_2D, GL_DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowNoMipmap); + static const TextureSpec tex2DMipmapShadow (TEXTURETYPE_2D, GL_DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowMipmap); + + static const TextureSpec tex2DTexelFetchFixed (TEXTURETYPE_2D, GL_RGBA8, 256, 256, 1, 9, samplerTexelFetch); + static const TextureSpec tex2DTexelFetchFloat (TEXTURETYPE_2D, GL_RGBA16F, 256, 256, 1, 9, samplerTexelFetch); + static const TextureSpec tex2DTexelFetchInt (TEXTURETYPE_2D, GL_RGBA8I, 256, 256, 1, 9, samplerTexelFetch); + static const TextureSpec tex2DTexelFetchUint (TEXTURETYPE_2D, GL_RGBA8UI, 256, 256, 1, 9, samplerTexelFetch); + + static const TextureSpec texCubeFixed (TEXTURETYPE_CUBE_MAP, GL_RGBA8, 256, 256, 1, 1, samplerLinearNoMipmap); + static const TextureSpec texCubeFloat (TEXTURETYPE_CUBE_MAP, GL_RGBA16F, 256, 256, 1, 1, samplerLinearNoMipmap); + static const TextureSpec texCubeInt (TEXTURETYPE_CUBE_MAP, GL_RGBA8I, 256, 256, 1, 1, samplerNearestNoMipmap); + static const TextureSpec texCubeUint (TEXTURETYPE_CUBE_MAP, GL_RGBA8UI, 256, 256, 1, 1, samplerNearestNoMipmap); + static const TextureSpec texCubeMipmapFixed (TEXTURETYPE_CUBE_MAP, GL_RGBA8, 256, 256, 1, 9, samplerLinearMipmap); + static const TextureSpec texCubeMipmapFloat (TEXTURETYPE_CUBE_MAP, GL_RGBA16F, 128, 128, 1, 8, samplerLinearMipmap); + static const TextureSpec texCubeMipmapInt (TEXTURETYPE_CUBE_MAP, GL_RGBA8I, 256, 256, 1, 9, samplerNearestMipmap); + static const TextureSpec texCubeMipmapUint (TEXTURETYPE_CUBE_MAP, GL_RGBA8UI, 256, 256, 1, 9, samplerNearestMipmap); + + static const TextureSpec texCubeShadow (TEXTURETYPE_CUBE_MAP, GL_DEPTH_COMPONENT16, 256, 256, 1, 1, samplerShadowNoMipmap); + static const TextureSpec texCubeMipmapShadow (TEXTURETYPE_CUBE_MAP, GL_DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowMipmap); + + static const TextureSpec tex2DArrayFixed (TEXTURETYPE_2D_ARRAY, GL_RGBA8, 128, 128, 4, 1, samplerLinearNoMipmap); + static const TextureSpec tex2DArrayFloat (TEXTURETYPE_2D_ARRAY, GL_RGBA16F, 128, 128, 4, 1, samplerLinearNoMipmap); + static const TextureSpec tex2DArrayInt (TEXTURETYPE_2D_ARRAY, GL_RGBA8I, 128, 128, 4, 1, samplerNearestNoMipmap); + static const TextureSpec tex2DArrayUint (TEXTURETYPE_2D_ARRAY, GL_RGBA8UI, 128, 128, 4, 1, samplerNearestNoMipmap); + static const TextureSpec tex2DArrayMipmapFixed (TEXTURETYPE_2D_ARRAY, GL_RGBA8, 128, 128, 4, 8, samplerLinearMipmap); + static const TextureSpec tex2DArrayMipmapFloat (TEXTURETYPE_2D_ARRAY, GL_RGBA16F, 128, 128, 4, 8, samplerLinearMipmap); + static const TextureSpec tex2DArrayMipmapInt (TEXTURETYPE_2D_ARRAY, GL_RGBA8I, 128, 128, 4, 8, samplerNearestMipmap); + static const TextureSpec tex2DArrayMipmapUint (TEXTURETYPE_2D_ARRAY, GL_RGBA8UI, 128, 128, 4, 8, samplerNearestMipmap); + + static const TextureSpec tex2DArrayShadow (TEXTURETYPE_2D_ARRAY, GL_DEPTH_COMPONENT16, 128, 128, 4, 1, samplerShadowNoMipmap); + static const TextureSpec tex2DArrayMipmapShadow (TEXTURETYPE_2D_ARRAY, GL_DEPTH_COMPONENT16, 128, 128, 4, 8, samplerShadowMipmap); + + static const TextureSpec tex2DArrayTexelFetchFixed (TEXTURETYPE_2D_ARRAY, GL_RGBA8, 128, 128, 4, 8, samplerTexelFetch); + static const TextureSpec tex2DArrayTexelFetchFloat (TEXTURETYPE_2D_ARRAY, GL_RGBA16F, 128, 128, 4, 8, samplerTexelFetch); + static const TextureSpec tex2DArrayTexelFetchInt (TEXTURETYPE_2D_ARRAY, GL_RGBA8I, 128, 128, 4, 8, samplerTexelFetch); + static const TextureSpec tex2DArrayTexelFetchUint (TEXTURETYPE_2D_ARRAY, GL_RGBA8UI, 128, 128, 4, 8, samplerTexelFetch); + + static const TextureSpec tex3DFixed (TEXTURETYPE_3D, GL_RGBA8, 64, 32, 32, 1, samplerLinearNoMipmap); + static const TextureSpec tex3DFloat (TEXTURETYPE_3D, GL_RGBA16F, 64, 32, 32, 1, samplerLinearNoMipmap); + static const TextureSpec tex3DInt (TEXTURETYPE_3D, GL_RGBA8I, 64, 32, 32, 1, samplerNearestNoMipmap); + static const TextureSpec tex3DUint (TEXTURETYPE_3D, GL_RGBA8UI, 64, 32, 32, 1, samplerNearestNoMipmap); + static const TextureSpec tex3DMipmapFixed (TEXTURETYPE_3D, GL_RGBA8, 64, 32, 32, 7, samplerLinearMipmap); + static const TextureSpec tex3DMipmapFloat (TEXTURETYPE_3D, GL_RGBA16F, 64, 32, 32, 7, samplerLinearMipmap); + static const TextureSpec tex3DMipmapInt (TEXTURETYPE_3D, GL_RGBA8I, 64, 32, 32, 7, samplerNearestMipmap); + static const TextureSpec tex3DMipmapUint (TEXTURETYPE_3D, GL_RGBA8UI, 64, 32, 32, 7, samplerNearestMipmap); + + static const TextureSpec tex3DTexelFetchFixed (TEXTURETYPE_3D, GL_RGBA8, 64, 32, 32, 7, samplerTexelFetch); + static const TextureSpec tex3DTexelFetchFloat (TEXTURETYPE_3D, GL_RGBA16F, 64, 32, 32, 7, samplerTexelFetch); + static const TextureSpec tex3DTexelFetchInt (TEXTURETYPE_3D, GL_RGBA8I, 64, 32, 32, 7, samplerTexelFetch); + static const TextureSpec tex3DTexelFetchUint (TEXTURETYPE_3D, GL_RGBA8UI, 64, 32, 32, 7, samplerTexelFetch); + + // texture() cases + static const TexFuncCaseSpec textureCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_fixed, 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, false, IVec3(0), tex2DFixed, evalTexture2D, VERTEX), + CASE_SPEC(sampler2d_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2D, FRAGMENT), + CASE_SPEC(sampler2d_float, 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, false, IVec3(0), tex2DFloat, evalTexture2D, VERTEX), + CASE_SPEC(sampler2d_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2D, FRAGMENT), + CASE_SPEC(isampler2d, 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, false, IVec3(0), tex2DInt, evalTexture2D, VERTEX), + CASE_SPEC(isampler2d, 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, false, IVec3(0), tex2DMipmapInt, evalTexture2D, FRAGMENT), + CASE_SPEC(usampler2d, 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, false, IVec3(0), tex2DUint, evalTexture2D, VERTEX), + CASE_SPEC(usampler2d, 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, false, IVec3(0), tex2DMipmapUint, evalTexture2D, FRAGMENT), + + CASE_SPEC(sampler2d_bias_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DBias, FRAGMENT), + CASE_SPEC(sampler2d_bias_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DBias, FRAGMENT), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DMipmapInt, evalTexture2DBias, FRAGMENT), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DMipmapUint, evalTexture2DBias, FRAGMENT), + + CASE_SPEC(samplercube_fixed, 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, false, IVec3(0), texCubeFixed, evalTextureCube, VERTEX), + CASE_SPEC(samplercube_fixed, 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, false, IVec3(0), texCubeMipmapFixed, evalTextureCube, FRAGMENT), + CASE_SPEC(samplercube_float, 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, false, IVec3(0), texCubeFloat, evalTextureCube, VERTEX), + CASE_SPEC(samplercube_float, 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, false, IVec3(0), texCubeMipmapFloat, evalTextureCube, FRAGMENT), + CASE_SPEC(isamplercube, 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, false, IVec3(0), texCubeInt, evalTextureCube, VERTEX), + CASE_SPEC(isamplercube, 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, false, IVec3(0), texCubeMipmapInt, evalTextureCube, FRAGMENT), + CASE_SPEC(usamplercube, 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, false, IVec3(0), texCubeUint, evalTextureCube, VERTEX), + CASE_SPEC(usamplercube, 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, false, IVec3(0), texCubeMipmapUint, evalTextureCube, FRAGMENT), + + CASE_SPEC(samplercube_bias_fixed, 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, false, IVec3(0), texCubeMipmapFixed, evalTextureCubeBias, FRAGMENT), + CASE_SPEC(samplercube_bias_float, 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, false, IVec3(0), texCubeMipmapFloat, evalTextureCubeBias, FRAGMENT), + CASE_SPEC(isamplercube_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, false, IVec3(0), texCubeMipmapInt, evalTextureCubeBias, FRAGMENT), + CASE_SPEC(usamplercube_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, false, IVec3(0), texCubeMipmapUint, evalTextureCubeBias, FRAGMENT), + + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayFixed, evalTexture2DArray, VERTEX), + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayMipmapFixed, evalTexture2DArray, FRAGMENT), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayFloat, evalTexture2DArray, VERTEX), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayMipmapFloat, evalTexture2DArray, FRAGMENT), + CASE_SPEC(isampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayInt, evalTexture2DArray, VERTEX), + CASE_SPEC(isampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayMipmapInt, evalTexture2DArray, FRAGMENT), + CASE_SPEC(usampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayUint, evalTexture2DArray, VERTEX), + CASE_SPEC(usampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayMipmapUint, evalTexture2DArray, FRAGMENT), + + CASE_SPEC(sampler2darray_bias_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, false, IVec3(0), tex2DArrayMipmapFixed, evalTexture2DArrayBias, FRAGMENT), + CASE_SPEC(sampler2darray_bias_float, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, false, IVec3(0), tex2DArrayMipmapFloat, evalTexture2DArrayBias, FRAGMENT), + CASE_SPEC(isampler2darray_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, false, IVec3(0), tex2DArrayMipmapInt, evalTexture2DArrayBias, FRAGMENT), + CASE_SPEC(usampler2darray_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, false, IVec3(0), tex2DArrayMipmapUint, evalTexture2DArrayBias, FRAGMENT), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DFixed, evalTexture3D, VERTEX), + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapFixed, evalTexture3D, FRAGMENT), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DFloat, evalTexture3D, VERTEX), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapFloat, evalTexture3D, FRAGMENT), + CASE_SPEC(isampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DInt, evalTexture3D, VERTEX), + CASE_SPEC(isampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapInt, evalTexture3D, FRAGMENT), + CASE_SPEC(usampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DUint, evalTexture3D, VERTEX), + CASE_SPEC(usampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapUint, evalTexture3D, FRAGMENT), + + CASE_SPEC(sampler3d_bias_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 1.0f, false, IVec3(0), tex3DMipmapFixed, evalTexture3DBias, FRAGMENT), + CASE_SPEC(sampler3d_bias_float, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 1.0f, false, IVec3(0), tex3DMipmapFloat, evalTexture3DBias, FRAGMENT), + CASE_SPEC(isampler3d_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 2.0f, false, IVec3(0), tex3DMipmapInt, evalTexture3DBias, FRAGMENT), + CASE_SPEC(usampler3d_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 2.0f, false, IVec3(0), tex3DMipmapUint, evalTexture3DBias, FRAGMENT), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DShadow, evalTexture2DShadow, VERTEX), + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadow, FRAGMENT), + CASE_SPEC(sampler2dshadow_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), true, -2.0f, 2.0f, false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowBias, FRAGMENT), + + CASE_SPEC(samplercubeshadow, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 1.0f), false, 0.0f, 0.0f, false, IVec3(0), texCubeShadow, evalTextureCubeShadow, VERTEX), + CASE_SPEC(samplercubeshadow, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 1.0f), false, 0.0f, 0.0f, false, IVec3(0), texCubeMipmapShadow, evalTextureCubeShadow, FRAGMENT), + CASE_SPEC(samplercubeshadow_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 1.0f), true, -2.0f, 2.0f, false, IVec3(0), texCubeMipmapShadow, evalTextureCubeShadowBias, FRAGMENT), + + CASE_SPEC(sampler2darrayshadow, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 1.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayShadow, evalTexture2DArrayShadow, VERTEX), + CASE_SPEC(sampler2darrayshadow, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 1.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayMipmapShadow, evalTexture2DArrayShadow, FRAGMENT) + + // Not in spec. +// CASE_SPEC(sampler2darrayshadow_bias, (FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 1.0f), true, -2.0f, 2.0f, Vec2(0.0f), Vec2(0.0f), false, IVec3(0)), tex2DArrayMipmapShadow, evalTexture2DArrayShadowBias, FRAGMENT) + }; + createCaseGroup(this, "texture", "texture() Tests", textureCases, DE_LENGTH_OF_ARRAY(textureCases)); + + // textureOffset() cases + // \note _bias variants are not using mipmap thanks to wide allowed range for LOD computation + static const TexFuncCaseSpec textureOffsetCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_fixed, 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, true, IVec3(-8, 7, 0), tex2DFixed, evalTexture2DOffset, VERTEX), + CASE_SPEC(sampler2d_fixed, 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, true, IVec3(7, -8, 0), tex2DMipmapFixed, evalTexture2DOffset, FRAGMENT), + CASE_SPEC(sampler2d_float, 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, true, IVec3(-8, 7, 0), tex2DFloat, evalTexture2DOffset, VERTEX), + CASE_SPEC(sampler2d_float, 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, true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DOffset, FRAGMENT), + CASE_SPEC(isampler2d, 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, true, IVec3(-8, 7, 0), tex2DInt, evalTexture2DOffset, VERTEX), + CASE_SPEC(isampler2d, 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, true, IVec3(7, -8, 0), tex2DMipmapInt, evalTexture2DOffset, FRAGMENT), + CASE_SPEC(usampler2d, 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, true, IVec3(-8, 7, 0), tex2DUint, evalTexture2DOffset, VERTEX), + CASE_SPEC(usampler2d, 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, true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DOffset, FRAGMENT), + + CASE_SPEC(sampler2d_bias_fixed, 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, true, IVec3(-8, 7, 0), tex2DFixed, evalTexture2DOffsetBias, FRAGMENT), + CASE_SPEC(sampler2d_bias_float, 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, true, IVec3(7, -8, 0), tex2DFloat, evalTexture2DOffsetBias, FRAGMENT), + CASE_SPEC(isampler2d_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, true, IVec3(-8, 7, 0), tex2DInt, evalTexture2DOffsetBias, FRAGMENT), + CASE_SPEC(usampler2d_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, true, IVec3(7, -8, 0), tex2DUint, evalTexture2DOffsetBias, FRAGMENT), + + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DArrayFixed, evalTexture2DArrayOffset, VERTEX), + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, -8, 0), tex2DArrayMipmapFixed, evalTexture2DArrayOffset, FRAGMENT), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DArrayFloat, evalTexture2DArrayOffset, VERTEX), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, -8, 0), tex2DArrayMipmapFloat, evalTexture2DArrayOffset, FRAGMENT), + CASE_SPEC(isampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DArrayInt, evalTexture2DArrayOffset, VERTEX), + CASE_SPEC(isampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, -8, 0), tex2DArrayMipmapInt, evalTexture2DArrayOffset, FRAGMENT), + CASE_SPEC(usampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DArrayUint, evalTexture2DArrayOffset, VERTEX), + CASE_SPEC(usampler2darray, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, -8, 0), tex2DArrayMipmapUint, evalTexture2DArrayOffset, FRAGMENT), + + CASE_SPEC(sampler2darray_bias_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, true, IVec3(-8, 7, 0), tex2DArrayFixed, evalTexture2DArrayOffsetBias, FRAGMENT), + CASE_SPEC(sampler2darray_bias_float, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, true, IVec3(7, -8, 0), tex2DArrayFloat, evalTexture2DArrayOffsetBias, FRAGMENT), + CASE_SPEC(isampler2darray_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, true, IVec3(-8, 7, 0), tex2DArrayInt, evalTexture2DArrayOffsetBias, FRAGMENT), + CASE_SPEC(usampler2darray_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), true, -2.0f, 2.0f, true, IVec3(7, -8, 0), tex2DArrayUint, evalTexture2DArrayOffsetBias, FRAGMENT), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DFixed, evalTexture3DOffset, VERTEX), + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, 3, -8), tex3DMipmapFixed, evalTexture3DOffset, FRAGMENT), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(3, -8, 7), tex3DFloat, evalTexture3DOffset, VERTEX), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DMipmapFloat, evalTexture3DOffset, FRAGMENT), + CASE_SPEC(isampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, 3, -8), tex3DInt, evalTexture3DOffset, VERTEX), + CASE_SPEC(isampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(3, -8, 7), tex3DMipmapInt, evalTexture3DOffset, FRAGMENT), + CASE_SPEC(usampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DUint, evalTexture3DOffset, VERTEX), + CASE_SPEC(usampler3d, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, 3, -8), tex3DMipmapUint, evalTexture3DOffset, FRAGMENT), + + CASE_SPEC(sampler3d_bias_fixed, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 1.0f, true, IVec3(-8, 7, 3), tex3DFixed, evalTexture3DOffsetBias, FRAGMENT), + CASE_SPEC(sampler3d_bias_float, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 1.0f, true, IVec3(7, 3, -8), tex3DFloat, evalTexture3DOffsetBias, FRAGMENT), + CASE_SPEC(isampler3d_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 2.0f, true, IVec3(3, -8, 7), tex3DInt, evalTexture3DOffsetBias, FRAGMENT), + CASE_SPEC(usampler3d_bias, FUNCTION_TEXTURE, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), true, -2.0f, 2.0f, true, IVec3(-8, 7, 3), tex3DUint, evalTexture3DOffsetBias, FRAGMENT), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DShadow, evalTexture2DShadowOffset, VERTEX), + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), false, 0.0f, 0.0f, true, IVec3(7, -8, 0), tex2DMipmapShadow, evalTexture2DShadowOffset, FRAGMENT), + CASE_SPEC(sampler2dshadow_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), true, -2.0f, 2.0f, true, IVec3(-8, 7, 0), tex2DShadow, evalTexture2DShadowOffsetBias, FRAGMENT) + }; + createCaseGroup(this, "textureoffset", "textureOffset() Tests", textureOffsetCases, DE_LENGTH_OF_ARRAY(textureOffsetCases)); + + // textureProj() cases + // \note Currently uses constant divider! + static const TexFuncCaseSpec textureProjCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_vec3_fixed, 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, false, IVec3(0), tex2DFixed, evalTexture2DProj3, VERTEX), + CASE_SPEC(sampler2d_vec3_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DProj3, FRAGMENT), + CASE_SPEC(sampler2d_vec3_float, 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, false, IVec3(0), tex2DFloat, evalTexture2DProj3, VERTEX), + CASE_SPEC(sampler2d_vec3_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DProj3, FRAGMENT), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DInt, evalTexture2DProj3, VERTEX), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DMipmapInt, evalTexture2DProj3, FRAGMENT), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DUint, evalTexture2DProj3, VERTEX), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DMipmapUint, evalTexture2DProj3, FRAGMENT), + + CASE_SPEC(sampler2d_vec3_bias_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DProj3Bias, FRAGMENT), + CASE_SPEC(sampler2d_vec3_bias_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DProj3Bias, FRAGMENT), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DMipmapInt, evalTexture2DProj3Bias, FRAGMENT), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DMipmapUint, evalTexture2DProj3Bias, FRAGMENT), + + CASE_SPEC(sampler2d_vec4_fixed, 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, false, IVec3(0), tex2DFixed, evalTexture2DProj, VERTEX), + CASE_SPEC(sampler2d_vec4_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DProj, FRAGMENT), + CASE_SPEC(sampler2d_vec4_float, 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, false, IVec3(0), tex2DFloat, evalTexture2DProj, VERTEX), + CASE_SPEC(sampler2d_vec4_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DProj, FRAGMENT), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DInt, evalTexture2DProj, VERTEX), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DMipmapInt, evalTexture2DProj, FRAGMENT), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DUint, evalTexture2DProj, VERTEX), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DMipmapUint, evalTexture2DProj, FRAGMENT), + + CASE_SPEC(sampler2d_vec4_bias_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DProjBias, FRAGMENT), + CASE_SPEC(sampler2d_vec4_bias_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DProjBias, FRAGMENT), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DMipmapInt, evalTexture2DProjBias, FRAGMENT), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DMipmapUint, evalTexture2DProjBias, FRAGMENT), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DFixed, evalTexture3DProj, VERTEX), + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapFixed, evalTexture3DProj, FRAGMENT), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DFloat, evalTexture3DProj, VERTEX), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapFloat, evalTexture3DProj, FRAGMENT), + CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DInt, evalTexture3DProj, VERTEX), + CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapInt, evalTexture3DProj, FRAGMENT), + CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DUint, evalTexture3DProj, VERTEX), + CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, false, IVec3(0), tex3DMipmapUint, evalTexture3DProj, FRAGMENT), + + CASE_SPEC(sampler3d_bias_fixed, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 1.0f, false, IVec3(0), tex3DMipmapFixed, evalTexture3DProjBias, FRAGMENT), + CASE_SPEC(sampler3d_bias_float, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 1.0f, false, IVec3(0), tex3DMipmapFloat, evalTexture3DProjBias, FRAGMENT), + CASE_SPEC(isampler3d_bias, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 2.0f, false, IVec3(0), tex3DMipmapInt, evalTexture3DProjBias, FRAGMENT), + CASE_SPEC(usampler3d_bias, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 2.0f, false, IVec3(0), tex3DMipmapUint, evalTexture3DProjBias, FRAGMENT), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJ, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), false, 0.0f, 0.0f, false, IVec3(0), tex2DShadow, evalTexture2DShadowProj, VERTEX), + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJ, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), false, 0.0f, 0.0f, false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowProj, FRAGMENT), + CASE_SPEC(sampler2dshadow_bias, FUNCTION_TEXTUREPROJ, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), true, -2.0f, 2.0f, false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowProjBias, FRAGMENT) + }; + createCaseGroup(this, "textureproj", "textureProj() Tests", textureProjCases, DE_LENGTH_OF_ARRAY(textureProjCases)); + + // textureProjOffset() cases + // \note Currently uses constant divider! + static const TexFuncCaseSpec textureProjOffsetCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_vec3_fixed, 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, true, IVec3(-8, 7, 0), tex2DFixed, evalTexture2DProj3Offset, VERTEX), + CASE_SPEC(sampler2d_vec3_fixed, 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, true, IVec3(7, -8, 0), tex2DMipmapFixed, evalTexture2DProj3Offset, FRAGMENT), + CASE_SPEC(sampler2d_vec3_float, 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, true, IVec3(-8, 7, 0), tex2DFloat, evalTexture2DProj3Offset, VERTEX), + CASE_SPEC(sampler2d_vec3_float, 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, true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DProj3Offset, FRAGMENT), + CASE_SPEC(isampler2d_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, true, IVec3(-8, 7, 0), tex2DInt, evalTexture2DProj3Offset, VERTEX), + CASE_SPEC(isampler2d_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, true, IVec3(7, -8, 0), tex2DMipmapInt, evalTexture2DProj3Offset, FRAGMENT), + CASE_SPEC(usampler2d_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, true, IVec3(-8, 7, 0), tex2DUint, evalTexture2DProj3Offset, VERTEX), + CASE_SPEC(usampler2d_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, true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DProj3Offset, FRAGMENT), + + CASE_SPEC(sampler2d_vec3_bias_fixed, 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, true, IVec3(-8, 7, 0), tex2DFixed, evalTexture2DProj3OffsetBias, FRAGMENT), + CASE_SPEC(sampler2d_vec3_bias_float, 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, true, IVec3(7, -8, 0), tex2DFloat, evalTexture2DProj3OffsetBias, FRAGMENT), + CASE_SPEC(isampler2d_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, true, IVec3(-8, 7, 0), tex2DInt, evalTexture2DProj3OffsetBias, FRAGMENT), + CASE_SPEC(usampler2d_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, true, IVec3(7, -8, 0), tex2DUint, evalTexture2DProj3OffsetBias, FRAGMENT), + + CASE_SPEC(sampler2d_vec4_fixed, 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, true, IVec3(-8, 7, 0), tex2DFixed, evalTexture2DProjOffset, VERTEX), + CASE_SPEC(sampler2d_vec4_fixed, 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, true, IVec3(7, -8, 0), tex2DMipmapFixed, evalTexture2DProjOffset, FRAGMENT), + CASE_SPEC(sampler2d_vec4_float, 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, true, IVec3(-8, 7, 0), tex2DFloat, evalTexture2DProjOffset, VERTEX), + CASE_SPEC(sampler2d_vec4_float, 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, true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DProjOffset, FRAGMENT), + CASE_SPEC(isampler2d_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, true, IVec3(-8, 7, 0), tex2DInt, evalTexture2DProjOffset, VERTEX), + CASE_SPEC(isampler2d_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, true, IVec3(7, -8, 0), tex2DMipmapInt, evalTexture2DProjOffset, FRAGMENT), + CASE_SPEC(usampler2d_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, true, IVec3(-8, 7, 0), tex2DUint, evalTexture2DProjOffset, VERTEX), + CASE_SPEC(usampler2d_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, true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DProjOffset, FRAGMENT), + + CASE_SPEC(sampler2d_vec4_bias_fixed, 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, true, IVec3(-8, 7, 0), tex2DFixed, evalTexture2DProjOffsetBias, FRAGMENT), + CASE_SPEC(sampler2d_vec4_bias_float, 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, true, IVec3(7, -8, 0), tex2DFloat, evalTexture2DProjOffsetBias, FRAGMENT), + CASE_SPEC(isampler2d_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, true, IVec3(-8, 7, 0), tex2DInt, evalTexture2DProjOffsetBias, FRAGMENT), + CASE_SPEC(usampler2d_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, true, IVec3(7, -8, 0), tex2DUint, evalTexture2DProjOffsetBias, FRAGMENT), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DFixed, evalTexture3DProjOffset, VERTEX), + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(7, 3, -8), tex3DMipmapFixed, evalTexture3DProjOffset, FRAGMENT), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(3, -8, 7), tex3DFloat, evalTexture3DProjOffset, VERTEX), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DMipmapFloat, evalTexture3DProjOffset, FRAGMENT), + CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(7, 3, -8), tex3DInt, evalTexture3DProjOffset, VERTEX), + CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(3, -8, 7), tex3DMipmapInt, evalTexture3DProjOffset, FRAGMENT), + CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DUint, evalTexture3DProjOffset, VERTEX), + CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, 0.0f, 0.0f, true, IVec3(7, 3, -8), tex3DMipmapUint, evalTexture3DProjOffset, FRAGMENT), + + CASE_SPEC(sampler3d_bias_fixed, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 2.0f, true, IVec3(-8, 7, 3), tex3DFixed, evalTexture3DProjOffsetBias, FRAGMENT), + CASE_SPEC(sampler3d_bias_float, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 2.0f, true, IVec3(7, 3, -8), tex3DFloat, evalTexture3DProjOffsetBias, FRAGMENT), + CASE_SPEC(isampler3d_bias, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 2.0f, true, IVec3(3, -8, 7), tex3DInt, evalTexture3DProjOffsetBias, FRAGMENT), + CASE_SPEC(usampler3d_bias, FUNCTION_TEXTUREPROJ, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), true, -2.0f, 2.0f, true, IVec3(-8, 7, 3), tex3DUint, evalTexture3DProjOffsetBias, FRAGMENT), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJ, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DShadow, evalTexture2DShadowProjOffset, VERTEX), + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJ, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), false, 0.0f, 0.0f, true, IVec3(7, -8, 0), tex2DMipmapShadow, evalTexture2DShadowProjOffset, FRAGMENT), + CASE_SPEC(sampler2dshadow_bias, FUNCTION_TEXTUREPROJ, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), true, -2.0f, 2.0f, true, IVec3(-8, 7, 0), tex2DShadow, evalTexture2DShadowProjOffsetBias, FRAGMENT) + }; + createCaseGroup(this, "textureprojoffset", "textureOffsetProj() Tests", textureProjOffsetCases, DE_LENGTH_OF_ARRAY(textureProjOffsetCases)); + + // textureLod() cases + static const TexFuncCaseSpec textureLodCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DLod, BOTH), + CASE_SPEC(sampler2d_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DLod, BOTH), + CASE_SPEC(isampler2d, 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, false, IVec3(0), tex2DMipmapInt, evalTexture2DLod, BOTH), + CASE_SPEC(usampler2d, 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, false, IVec3(0), tex2DMipmapUint, evalTexture2DLod, BOTH), + + CASE_SPEC(samplercube_fixed, 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, false, IVec3(0), texCubeMipmapFixed, evalTextureCubeLod, BOTH), + CASE_SPEC(samplercube_float, 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, false, IVec3(0), texCubeMipmapFloat, evalTextureCubeLod, BOTH), + CASE_SPEC(isamplercube, 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, false, IVec3(0), texCubeMipmapInt, evalTextureCubeLod, BOTH), + CASE_SPEC(usamplercube, 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, false, IVec3(0), texCubeMipmapUint, evalTextureCubeLod, BOTH), + + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, false, IVec3(0), tex2DArrayMipmapFixed, evalTexture2DArrayLod, BOTH), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, false, IVec3(0), tex2DArrayMipmapFloat, evalTexture2DArrayLod, BOTH), + CASE_SPEC(isampler2darray, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, false, IVec3(0), tex2DArrayMipmapInt, evalTexture2DArrayLod, BOTH), + CASE_SPEC(usampler2darray, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, false, IVec3(0), tex2DArrayMipmapUint, evalTexture2DArrayLod, BOTH), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapFixed, evalTexture3DLod, BOTH), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapFloat, evalTexture3DLod, BOTH), + CASE_SPEC(isampler3d, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapInt, evalTexture3DLod, BOTH), + CASE_SPEC(usampler3d, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapUint, evalTexture3DLod, BOTH), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTURELOD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), false, -1.0f, 9.0f, false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowLod, BOTH) + }; + createCaseGroup(this, "texturelod", "textureLod() Tests", textureLodCases, DE_LENGTH_OF_ARRAY(textureLodCases)); + + // textureLodOffset() cases + static const TexFuncCaseSpec textureLodOffsetCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_fixed, 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, true, IVec3(-8, 7, 0), tex2DMipmapFixed, evalTexture2DLodOffset, BOTH), + CASE_SPEC(sampler2d_float, 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, true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DLodOffset, BOTH), + CASE_SPEC(isampler2d, 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, true, IVec3(-8, 7, 0), tex2DMipmapInt, evalTexture2DLodOffset, BOTH), + CASE_SPEC(usampler2d, 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, true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DLodOffset, BOTH), + + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, true, IVec3(-8, 7, 0), tex2DArrayMipmapFixed, evalTexture2DArrayLodOffset, BOTH), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, true, IVec3(7, -8, 0), tex2DArrayMipmapFloat, evalTexture2DArrayLodOffset, BOTH), + CASE_SPEC(isampler2darray, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, true, IVec3(-8, 7, 0), tex2DArrayMipmapInt, evalTexture2DArrayLodOffset, BOTH), + CASE_SPEC(usampler2darray, FUNCTION_TEXTURELOD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), false, -1.0f, 8.0f, true, IVec3(7, -8, 0), tex2DArrayMipmapUint, evalTexture2DArrayLodOffset, BOTH), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, true, IVec3(-8, 7, 3), tex3DMipmapFixed, evalTexture3DLodOffset, BOTH), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, true, IVec3(7, 3, -8), tex3DMipmapFloat, evalTexture3DLodOffset, BOTH), + CASE_SPEC(isampler3d, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, true, IVec3(3, -8, 7), tex3DMipmapInt, evalTexture3DLodOffset, BOTH), + CASE_SPEC(usampler3d, FUNCTION_TEXTURELOD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), false, -1.0f, 7.0f, true, IVec3(-8, 7, 3), tex3DMipmapUint, evalTexture3DLodOffset, BOTH), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTURELOD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), false, -1.0f, 9.0f, true, IVec3(-8, 7, 0), tex2DMipmapShadow, evalTexture2DShadowLodOffset, BOTH) + }; + createCaseGroup(this, "texturelodoffset", "textureLodOffset() Tests", textureLodOffsetCases, DE_LENGTH_OF_ARRAY(textureLodOffsetCases)); + + // textureProjLod() cases + static const TexFuncCaseSpec textureProjLodCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_vec3_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DProjLod3, BOTH), + CASE_SPEC(sampler2d_vec3_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DProjLod3, BOTH), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DMipmapInt, evalTexture2DProjLod3, BOTH), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DMipmapUint, evalTexture2DProjLod3, BOTH), + + CASE_SPEC(sampler2d_vec4_fixed, 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, false, IVec3(0), tex2DMipmapFixed, evalTexture2DProjLod, BOTH), + CASE_SPEC(sampler2d_vec4_float, 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, false, IVec3(0), tex2DMipmapFloat, evalTexture2DProjLod, BOTH), + CASE_SPEC(isampler2d_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, false, IVec3(0), tex2DMipmapInt, evalTexture2DProjLod, BOTH), + CASE_SPEC(usampler2d_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, false, IVec3(0), tex2DMipmapUint, evalTexture2DProjLod, BOTH), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapFixed, evalTexture3DProjLod, BOTH), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapFloat, evalTexture3DProjLod, BOTH), + CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapInt, evalTexture3DProjLod, BOTH), + CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, false, IVec3(0), tex3DMipmapUint, evalTexture3DProjLod, BOTH), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJLOD, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), false, -1.0f, 9.0f, false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowProjLod, BOTH) + }; + createCaseGroup(this, "textureprojlod", "textureProjLod() Tests", textureProjLodCases, DE_LENGTH_OF_ARRAY(textureProjLodCases)); + + // textureProjLodOffset() cases + static const TexFuncCaseSpec textureProjLodOffsetCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_vec3_fixed, 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, true, IVec3(-8, 7, 0), tex2DMipmapFixed, evalTexture2DProjLod3Offset, BOTH), + CASE_SPEC(sampler2d_vec3_float, 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, true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DProjLod3Offset, BOTH), + CASE_SPEC(isampler2d_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, true, IVec3(-8, 7, 0), tex2DMipmapInt, evalTexture2DProjLod3Offset, BOTH), + CASE_SPEC(usampler2d_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, true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DProjLod3Offset, BOTH), + + CASE_SPEC(sampler2d_vec4_fixed, 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, true, IVec3(-8, 7, 0), tex2DMipmapFixed, evalTexture2DProjLodOffset, BOTH), + CASE_SPEC(sampler2d_vec4_float, 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, true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DProjLodOffset, BOTH), + CASE_SPEC(isampler2d_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, true, IVec3(-8, 7, 0), tex2DMipmapInt, evalTexture2DProjLodOffset, BOTH), + CASE_SPEC(usampler2d_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, true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DProjLodOffset, BOTH), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, true, IVec3(-8, 7, 3), tex3DMipmapFixed, evalTexture3DProjLodOffset, BOTH), + CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, true, IVec3(7, 3, -8), tex3DMipmapFloat, evalTexture3DProjLodOffset, BOTH), + CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, true, IVec3(3, -8, 7), tex3DMipmapInt, evalTexture3DProjLodOffset, BOTH), + CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJLOD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), false, -1.0f, 7.0f, true, IVec3(-8, 7, 3), tex3DMipmapUint, evalTexture3DProjLodOffset, BOTH), + + CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJLOD, Vec4( 0.2f, 0.6f, 0.0f, 1.5f), Vec4(-2.25f, -3.45f, 1.5f, 1.5f), false, -1.0f, 9.0f, true, IVec3(-8, 7, 0), tex2DMipmapShadow, evalTexture2DShadowProjLodOffset, BOTH) + }; + createCaseGroup(this, "textureprojlodoffset", "textureProjLodOffset() Tests", textureProjLodOffsetCases, DE_LENGTH_OF_ARRAY(textureProjLodOffsetCases)); + + // textureGrad() cases + // \note Only one of dudx, dudy, dvdx, dvdy is non-zero since spec allows approximating p from derivates by various methods. + static const TexFuncCaseSpec textureGradCases[] = + { + // Name Function MinCoord MaxCoord MinDx MaxDx MinDy MaxDy Offset? Offset Format EvalFunc Flags + GRAD_CASE_SPEC(sampler2d_fixed, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapFixed, evalTexture2DGrad, BOTH), + GRAD_CASE_SPEC(sampler2d_float, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapFloat, evalTexture2DGrad, BOTH), + GRAD_CASE_SPEC(isampler2d, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapInt, evalTexture2DGrad, BOTH), + GRAD_CASE_SPEC(usampler2d, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), false, IVec3(0), tex2DMipmapUint, evalTexture2DGrad, BOTH), + + GRAD_CASE_SPEC(samplercube_fixed, FUNCTION_TEXTUREGRAD, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), texCubeMipmapFixed, evalTextureCubeGrad, BOTH), + GRAD_CASE_SPEC(samplercube_float, FUNCTION_TEXTUREGRAD, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), texCubeMipmapFloat, evalTextureCubeGrad, BOTH), + GRAD_CASE_SPEC(isamplercube, FUNCTION_TEXTUREGRAD, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), false, IVec3(0), texCubeMipmapInt, evalTextureCubeGrad, BOTH), + GRAD_CASE_SPEC(usamplercube, FUNCTION_TEXTUREGRAD, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), false, IVec3(0), texCubeMipmapUint, evalTextureCubeGrad, BOTH), + + GRAD_CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DArrayMipmapFixed, evalTexture2DArrayGrad, BOTH), + GRAD_CASE_SPEC(sampler2darray_float, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DArrayMipmapFloat, evalTexture2DArrayGrad, BOTH), + GRAD_CASE_SPEC(isampler2darray, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), false, IVec3(0), tex2DArrayMipmapInt, evalTexture2DArrayGrad, BOTH), + GRAD_CASE_SPEC(usampler2darray, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), false, IVec3(0), tex2DArrayMipmapUint, evalTexture2DArrayGrad, BOTH), + + GRAD_CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapFixed, evalTexture3DGrad, BOTH), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapFloat, evalTexture3DGrad, VERTEX), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.2f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapFloat, evalTexture3DGrad, FRAGMENT), + GRAD_CASE_SPEC(isampler3d, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapInt, evalTexture3DGrad, BOTH), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), false, IVec3(0), tex3DMipmapUint, evalTexture3DGrad, VERTEX), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, -0.2f), false, IVec3(0), tex3DMipmapUint, evalTexture3DGrad, FRAGMENT), + + GRAD_CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowGrad, BOTH), + GRAD_CASE_SPEC(samplercubeshadow, FUNCTION_TEXTUREGRAD, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 1.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), texCubeMipmapShadow, evalTextureCubeShadowGrad, BOTH), + GRAD_CASE_SPEC(sampler2darrayshadow, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 1.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), false, IVec3(0), tex2DArrayMipmapShadow, evalTexture2DArrayShadowGrad, VERTEX), + GRAD_CASE_SPEC(sampler2darrayshadow, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 1.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), false, IVec3(0), tex2DArrayMipmapShadow, evalTexture2DArrayShadowGrad, FRAGMENT) + }; + createCaseGroup(this, "texturegrad", "textureGrad() Tests", textureGradCases, DE_LENGTH_OF_ARRAY(textureGradCases)); + + // textureGradOffset() cases + static const TexFuncCaseSpec textureGradOffsetCases[] = + { + // Name Function MinCoord MaxCoord MinDx MaxDx MinDy MaxDy Offset? Offset Format EvalFunc Flags + GRAD_CASE_SPEC(sampler2d_fixed, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapFixed, evalTexture2DGradOffset, BOTH), + GRAD_CASE_SPEC(sampler2d_float, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DGradOffset, BOTH), + GRAD_CASE_SPEC(isampler2d, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapInt, evalTexture2DGradOffset, BOTH), + GRAD_CASE_SPEC(usampler2d, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DGradOffset, BOTH), + + GRAD_CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DArrayMipmapFixed, evalTexture2DArrayGradOffset, BOTH), + GRAD_CASE_SPEC(sampler2darray_float, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(7, -8, 0), tex2DArrayMipmapFloat, evalTexture2DArrayGradOffset, BOTH), + GRAD_CASE_SPEC(isampler2darray, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DArrayMipmapInt, evalTexture2DArrayGradOffset, BOTH), + GRAD_CASE_SPEC(usampler2darray, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), true, IVec3(7, -8, 0), tex2DArrayMipmapUint, evalTexture2DArrayGradOffset, BOTH), + + GRAD_CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 3), tex3DMipmapFixed, evalTexture3DGradOffset, BOTH), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(7, 3, -8), tex3DMipmapFloat, evalTexture3DGradOffset, VERTEX), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.2f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(3, -8, 7), tex3DMipmapFloat, evalTexture3DGradOffset, FRAGMENT), + GRAD_CASE_SPEC(isampler3d, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), true, IVec3(-8, 7, 3), tex3DMipmapInt, evalTexture3DGradOffset, BOTH), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), true, IVec3(7, 3, -8), tex3DMipmapUint, evalTexture3DGradOffset, VERTEX), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -1.4f, 0.1f, 0.0f), Vec4( 1.5f, 2.3f, 2.3f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, -0.2f), true, IVec3(3, -8, 7), tex3DMipmapUint, evalTexture3DGradOffset, FRAGMENT), + + GRAD_CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapShadow, evalTexture2DShadowGradOffset, VERTEX), + GRAD_CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREGRAD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 1.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapShadow, evalTexture2DShadowGradOffset, FRAGMENT), + GRAD_CASE_SPEC(sampler2darrayshadow, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 1.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DArrayMipmapShadow, evalTexture2DArrayShadowGradOffset, VERTEX), + GRAD_CASE_SPEC(sampler2darrayshadow, FUNCTION_TEXTUREGRAD, Vec4(-1.2f, -0.4f, -0.5f, 0.0f), Vec4( 1.5f, 2.3f, 3.5f, 1.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), true, IVec3(7, -8, 0), tex2DArrayMipmapShadow, evalTexture2DArrayShadowGradOffset, FRAGMENT) + }; + createCaseGroup(this, "texturegradoffset", "textureGradOffset() Tests", textureGradOffsetCases, DE_LENGTH_OF_ARRAY(textureGradOffsetCases)); + + // textureProjGrad() cases + static const TexFuncCaseSpec textureProjGradCases[] = + { + // Name Function MinCoord MaxCoord MinDx MaxDx MinDy MaxDy Offset? Offset Format EvalFunc Flags + GRAD_CASE_SPEC(sampler2d_vec3_fixed, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapFixed, evalTexture2DProjGrad3, BOTH), + GRAD_CASE_SPEC(sampler2d_vec3_float, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapFloat, evalTexture2DProjGrad3, BOTH), + GRAD_CASE_SPEC(isampler2d_vec3, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapInt, evalTexture2DProjGrad3, BOTH), + GRAD_CASE_SPEC(usampler2d_vec3, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), false, IVec3(0), tex2DMipmapUint, evalTexture2DProjGrad3, BOTH), + + GRAD_CASE_SPEC(sampler2d_vec4_fixed, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapFixed, evalTexture2DProjGrad, BOTH), + GRAD_CASE_SPEC(sampler2d_vec4_float, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapFloat, evalTexture2DProjGrad, BOTH), + GRAD_CASE_SPEC(isampler2d_vec4, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapInt, evalTexture2DProjGrad, BOTH), + GRAD_CASE_SPEC(usampler2d_vec4, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), false, IVec3(0), tex2DMipmapUint, evalTexture2DProjGrad, BOTH), + + GRAD_CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapFixed, evalTexture3DProjGrad, BOTH), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapFloat, evalTexture3DProjGrad, VERTEX), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.2f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapFloat, evalTexture3DProjGrad, FRAGMENT), + GRAD_CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), false, IVec3(0), tex3DMipmapInt, evalTexture3DProjGrad, BOTH), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), false, IVec3(0), tex3DMipmapUint, evalTexture3DProjGrad, VERTEX), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, -0.2f), false, IVec3(0), tex3DMipmapUint, evalTexture3DProjGrad, FRAGMENT), + + GRAD_CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJGRAD, Vec4( 0.2f, 0.6f, 0.0f, -1.5f), Vec4(-2.25f, -3.45f, -1.5f, -1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowProjGrad, VERTEX), + GRAD_CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJGRAD, Vec4( 0.2f, 0.6f, 0.0f, -1.5f), Vec4(-2.25f, -3.45f, -1.5f, -1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), false, IVec3(0), tex2DMipmapShadow, evalTexture2DShadowProjGrad, FRAGMENT) + }; + createCaseGroup(this, "textureprojgrad", "textureProjGrad() Tests", textureProjGradCases, DE_LENGTH_OF_ARRAY(textureProjGradCases)); + + // textureProjGradOffset() cases + static const TexFuncCaseSpec textureProjGradOffsetCases[] = + { + // Name Function MinCoord MaxCoord MinDx MaxDx MinDy MaxDy Offset? Offset Format EvalFunc Flags + GRAD_CASE_SPEC(sampler2d_vec3_fixed, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapFixed, evalTexture2DProjGrad3Offset, BOTH), + GRAD_CASE_SPEC(sampler2d_vec3_float, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DProjGrad3Offset, BOTH), + GRAD_CASE_SPEC(isampler2d_vec3, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapInt, evalTexture2DProjGrad3Offset, BOTH), + GRAD_CASE_SPEC(usampler2d_vec3, FUNCTION_TEXTUREPROJGRAD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DProjGrad3Offset, BOTH), + + GRAD_CASE_SPEC(sampler2d_vec4_fixed, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapFixed, evalTexture2DProjGradOffset, BOTH), + GRAD_CASE_SPEC(sampler2d_vec4_float, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapFloat, evalTexture2DProjGradOffset, BOTH), + GRAD_CASE_SPEC(isampler2d_vec4, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapInt, evalTexture2DProjGradOffset, BOTH), + GRAD_CASE_SPEC(usampler2d_vec4, FUNCTION_TEXTUREPROJGRAD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapUint, evalTexture2DProjGradOffset, BOTH), + + GRAD_CASE_SPEC(sampler3d_fixed, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 3), tex3DMipmapFixed, evalTexture3DProjGradOffset, BOTH), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(7, 3, -8), tex3DMipmapFloat, evalTexture3DProjGradOffset, VERTEX), + GRAD_CASE_SPEC(sampler3d_float, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.2f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(3, -8, 7), tex3DMipmapFloat, evalTexture3DProjGradOffset, FRAGMENT), + GRAD_CASE_SPEC(isampler3d, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3(-0.2f, 0.0f, 0.0f), true, IVec3(-8, 7, 3), tex3DMipmapInt, evalTexture3DProjGradOffset, BOTH), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.2f, 0.0f), true, IVec3(7, 3, -8), tex3DMipmapUint, evalTexture3DProjGradOffset, VERTEX), + GRAD_CASE_SPEC(usampler3d, FUNCTION_TEXTUREPROJGRAD, Vec4(0.9f, 1.05f, -0.08f, -0.75f), Vec4(-1.13f, -1.7f, -1.7f, -0.75f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, -0.2f), true, IVec3(3, -8, 7), tex3DMipmapUint, evalTexture3DProjGradOffset, FRAGMENT), + + GRAD_CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJGRAD, Vec4( 0.2f, 0.6f, 0.0f, -1.5f), Vec4(-2.25f, -3.45f, -1.5f, -1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.2f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), true, IVec3(-8, 7, 0), tex2DMipmapShadow, evalTexture2DShadowProjGradOffset, VERTEX), + GRAD_CASE_SPEC(sampler2dshadow, FUNCTION_TEXTUREPROJGRAD, Vec4( 0.2f, 0.6f, 0.0f, -1.5f), Vec4(-2.25f, -3.45f, -1.5f, -1.5f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, 0.0f, 0.0f), Vec3( 0.0f, -0.2f, 0.0f), true, IVec3(7, -8, 0), tex2DMipmapShadow, evalTexture2DShadowProjGradOffset, FRAGMENT) + }; + createCaseGroup(this, "textureprojgradoffset", "textureProjGradOffset() Tests", textureProjGradOffsetCases, DE_LENGTH_OF_ARRAY(textureProjGradOffsetCases)); + + // texelFetch() cases + // \note Level is constant across quad + static const TexFuncCaseSpec texelFetchCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_fixed, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(255.9f, 255.9f, 0.0f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DTexelFetchFixed, evalTexelFetch2D, BOTH), + CASE_SPEC(sampler2d_float, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(127.9f, 127.9f, 0.0f, 0.0f), false, 1.0f, 1.0f, false, IVec3(0), tex2DTexelFetchFloat, evalTexelFetch2D, BOTH), + CASE_SPEC(isampler2d, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4( 63.9f, 63.9f, 0.0f, 0.0f), false, 2.0f, 2.0f, false, IVec3(0), tex2DTexelFetchInt, evalTexelFetch2D, BOTH), + CASE_SPEC(usampler2d, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4( 15.9f, 15.9f, 0.0f, 0.0f), false, 4.0f, 4.0f, false, IVec3(0), tex2DTexelFetchUint, evalTexelFetch2D, BOTH), + + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(127.9f, 127.9f, 3.9f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex2DArrayTexelFetchFixed, evalTexelFetch2DArray, BOTH), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4( 63.9f, 63.9f, 3.9f, 0.0f), false, 1.0f, 1.0f, false, IVec3(0), tex2DArrayTexelFetchFloat, evalTexelFetch2DArray, BOTH), + CASE_SPEC(isampler2darray, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4( 31.9f, 31.9f, 3.9f, 0.0f), false, 2.0f, 2.0f, false, IVec3(0), tex2DArrayTexelFetchInt, evalTexelFetch2DArray, BOTH), + CASE_SPEC(usampler2darray, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4( 15.9f, 15.9f, 3.9f, 0.0f), false, 3.0f, 3.0f, false, IVec3(0), tex2DArrayTexelFetchUint, evalTexelFetch2DArray, BOTH), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(63.9f, 31.9f, 31.9f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DTexelFetchFixed, evalTexelFetch3D, BOTH), + CASE_SPEC(sampler3d_float, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(31.9f, 15.9f, 15.9f, 0.0f), false, 1.0f, 1.0f, false, IVec3(0), tex3DTexelFetchFloat, evalTexelFetch3D, BOTH), + CASE_SPEC(isampler3d, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(15.9f, 7.9f, 7.9f, 0.0f), false, 2.0f, 2.0f, false, IVec3(0), tex3DTexelFetchInt, evalTexelFetch3D, BOTH), + CASE_SPEC(usampler3d, FUNCTION_TEXELFETCH, Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(63.9f, 31.9f, 31.9f, 0.0f), false, 0.0f, 0.0f, false, IVec3(0), tex3DTexelFetchUint, evalTexelFetch3D, BOTH) + }; + createCaseGroup(this, "texelfetch", "texelFetch() Tests", texelFetchCases, DE_LENGTH_OF_ARRAY(texelFetchCases)); + + // texelFetchOffset() cases + static const TexFuncCaseSpec texelFetchOffsetCases[] = + { + // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Offset? Offset Format EvalFunc Flags + CASE_SPEC(sampler2d_fixed, FUNCTION_TEXELFETCH, Vec4( 8.0f, -7.0f, 0.0f, 0.0f), Vec4(263.9f, 248.9f, 0.0f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DTexelFetchFixed, evalTexelFetch2D, BOTH), + CASE_SPEC(sampler2d_float, FUNCTION_TEXELFETCH, Vec4(-7.0f, 8.0f, 0.0f, 0.0f), Vec4(120.9f, 135.9f, 0.0f, 0.0f), false, 1.0f, 1.0f, true, IVec3(7, -8, 0), tex2DTexelFetchFloat, evalTexelFetch2D, BOTH), + CASE_SPEC(isampler2d, FUNCTION_TEXELFETCH, Vec4( 8.0f, -7.0f, 0.0f, 0.0f), Vec4( 71.9f, 56.9f, 0.0f, 0.0f), false, 2.0f, 2.0f, true, IVec3(-8, 7, 0), tex2DTexelFetchInt, evalTexelFetch2D, BOTH), + CASE_SPEC(usampler2d, FUNCTION_TEXELFETCH, Vec4(-7.0f, 8.0f, 0.0f, 0.0f), Vec4( 8.9f, 23.9f, 0.0f, 0.0f), false, 4.0f, 4.0f, true, IVec3(7, -8, 0), tex2DTexelFetchUint, evalTexelFetch2D, BOTH), + + CASE_SPEC(sampler2darray_fixed, FUNCTION_TEXELFETCH, Vec4( 8.0f, -7.0f, 0.0f, 0.0f), Vec4(135.9f, 120.9f, 3.9f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 0), tex2DArrayTexelFetchFixed, evalTexelFetch2DArray, BOTH), + CASE_SPEC(sampler2darray_float, FUNCTION_TEXELFETCH, Vec4(-7.0f, 8.0f, 0.0f, 0.0f), Vec4( 56.9f, 71.9f, 3.9f, 0.0f), false, 1.0f, 1.0f, true, IVec3(7, -8, 0), tex2DArrayTexelFetchFloat, evalTexelFetch2DArray, BOTH), + CASE_SPEC(isampler2darray, FUNCTION_TEXELFETCH, Vec4( 8.0f, -7.0f, 0.0f, 0.0f), Vec4( 39.9f, 24.9f, 3.9f, 0.0f), false, 2.0f, 2.0f, true, IVec3(-8, 7, 0), tex2DArrayTexelFetchInt, evalTexelFetch2DArray, BOTH), + CASE_SPEC(usampler2darray, FUNCTION_TEXELFETCH, Vec4(-7.0f, 8.0f, 0.0f, 0.0f), Vec4( 8.9f, 23.9f, 3.9f, 0.0f), false, 3.0f, 3.0f, true, IVec3(7, -8, 0), tex2DArrayTexelFetchUint, evalTexelFetch2DArray, BOTH), + + CASE_SPEC(sampler3d_fixed, FUNCTION_TEXELFETCH, Vec4( 8.0f, -7.0f, -3.0f, 0.0f),Vec4(71.9f, 24.9f, 28.9f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DTexelFetchFixed, evalTexelFetch3D, BOTH), + CASE_SPEC(sampler3d_float, FUNCTION_TEXELFETCH, Vec4(-7.0f, -3.0f, 8.0f, 0.0f),Vec4(24.9f, 12.9f, 23.9f, 0.0f), false, 1.0f, 1.0f, true, IVec3(7, 3, -8), tex3DTexelFetchFloat, evalTexelFetch3D, BOTH), + CASE_SPEC(isampler3d, FUNCTION_TEXELFETCH, Vec4(-3.0f, 8.0f, -7.0f, 0.0f),Vec4(12.9f, 15.9f, 0.9f, 0.0f), false, 2.0f, 2.0f, true, IVec3(3, -8, 7), tex3DTexelFetchInt, evalTexelFetch3D, BOTH), + CASE_SPEC(usampler3d, FUNCTION_TEXELFETCH, Vec4( 8.0f, -7.0f, -3.0f, 0.0f),Vec4(71.9f, 24.9f, 28.9f, 0.0f), false, 0.0f, 0.0f, true, IVec3(-8, 7, 3), tex3DTexelFetchUint, evalTexelFetch3D, BOTH) + }; + createCaseGroup(this, "texelfetchoffset", "texelFetchOffset() Tests", texelFetchOffsetCases, DE_LENGTH_OF_ARRAY(texelFetchOffsetCases)); + + // textureSize() cases + { + struct TextureSizeCaseSpec + { + const char* name; + const char* samplerName; + TextureSpec textureSpec; + } textureSizeCases[] = + { + { "sampler2d_fixed", "sampler2D", tex2DFixed }, + { "sampler2d_float", "sampler2D", tex2DFloat }, + { "isampler2d", "isampler2D", tex2DInt }, + { "usampler2d", "usampler2D", tex2DUint }, + { "sampler2dshadow", "sampler2DShadow", tex2DShadow }, + { "sampler3d_fixed", "sampler3D", tex3DFixed }, + { "sampler3d_float", "sampler3D", tex3DFloat }, + { "isampler3d", "isampler3D", tex3DInt }, + { "usampler3d", "usampler3D", tex3DUint }, + { "samplercube_fixed", "samplerCube", texCubeFixed }, + { "samplercube_float", "samplerCube", texCubeFloat }, + { "isamplercube", "isamplerCube", texCubeInt }, + { "usamplercube", "usamplerCube", texCubeUint }, + { "samplercubeshadow", "samplerCubeShadow", texCubeShadow }, + { "sampler2darray_fixed", "sampler2DArray", tex2DArrayFixed }, + { "sampler2darray_float", "sampler2DArray", tex2DArrayFloat }, + { "isampler2darray", "isampler2DArray", tex2DArrayInt }, + { "usampler2darray", "usampler2DArray", tex2DArrayUint }, + { "sampler2darrayshadow", "sampler2DArrayShadow", tex2DArrayShadow }, + }; + + de::MovePtr group (new tcu::TestCaseGroup(m_testCtx, "texturesize", "textureSize() Tests")); + + for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureSizeCases); ++ndx) + { + const TextureSizeCaseSpec& caseSpec = textureSizeCases[ndx]; + + group->addChild(new TextureSizeCase(m_testCtx, (std::string(caseSpec.name) + "_vertex"), "", caseSpec.samplerName, caseSpec.textureSpec, true)); + group->addChild(new TextureSizeCase(m_testCtx, (std::string(caseSpec.name) + "_fragment"), "", caseSpec.samplerName, caseSpec.textureSpec, false)); + } + + addChild(group.release()); + } +} + +} // anonymous + +tcu::TestCaseGroup* createTextureFunctionTests (tcu::TestContext& testCtx) +{ + return new ShaderTextureFunctionTests(testCtx); +} + +} // sr +} // vkt diff --git a/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.hpp b/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.hpp new file mode 100644 index 0000000..13ec83d --- /dev/null +++ b/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderTextureFunctionTests.hpp @@ -0,0 +1,48 @@ +#ifndef _VKTSHADERRENDERTEXTUREFUNCTIONTESTS_HPP +#define _VKTSHADERRENDERTEXTUREFUNCTIONTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 The Android Open Source Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice(s) and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + * + *//*! + * \file + * \brief Texture access function tests. + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace vkt +{ +namespace sr +{ + +tcu::TestCaseGroup* createTextureFunctionTests (tcu::TestContext& testCtx); + +} // sr +} // vkt + +#endif // _VKTSHADERRENDERTEXTUREFUNCTIONTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/vktTestPackage.cpp b/external/vulkancts/modules/vulkan/vktTestPackage.cpp index 27f11d3..fb25cae 100644 --- a/external/vulkancts/modules/vulkan/vktTestPackage.cpp +++ b/external/vulkancts/modules/vulkan/vktTestPackage.cpp @@ -53,6 +53,7 @@ #include "vktShaderRenderReturnTests.hpp" #include "vktShaderRenderStructTests.hpp" #include "vktShaderRenderSwitchTests.hpp" +#include "vktShaderRenderTextureFunctionTests.hpp" #include "vktShaderBuiltinTests.hpp" #include "vktOpaqueTypeIndexingTests.hpp" #include "vktUniformBlockTests.hpp" @@ -330,14 +331,15 @@ void createGlslTests (tcu::TestCaseGroup* glslTests) std::string("vulkan/glsl/es310/") + s_es310Tests[ndx].name + ".test").release()); // ShaderRenderCase-based tests - glslTests->addChild(sr::createDiscardTests (testCtx)); - glslTests->addChild(sr::createIndexingTests (testCtx)); - glslTests->addChild(sr::createLoopTests (testCtx)); - glslTests->addChild(sr::createMatrixTests (testCtx)); - glslTests->addChild(sr::createOperatorTests (testCtx)); - glslTests->addChild(sr::createReturnTests (testCtx)); - glslTests->addChild(sr::createStructTests (testCtx)); - glslTests->addChild(sr::createSwitchTests (testCtx)); + glslTests->addChild(sr::createDiscardTests (testCtx)); + glslTests->addChild(sr::createIndexingTests (testCtx)); + glslTests->addChild(sr::createLoopTests (testCtx)); + glslTests->addChild(sr::createMatrixTests (testCtx)); + glslTests->addChild(sr::createOperatorTests (testCtx)); + glslTests->addChild(sr::createReturnTests (testCtx)); + glslTests->addChild(sr::createStructTests (testCtx)); + glslTests->addChild(sr::createSwitchTests (testCtx)); + glslTests->addChild(sr::createTextureFunctionTests (testCtx)); // ShaderExecutor-based tests glslTests->addChild(shaderexecutor::createBuiltinTests (testCtx)); -- 2.7.4