| /*------------------------------------------------------------------------ |
| * 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 |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Texture access and query 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" |
| #include "vkImageUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| |
| namespace vkt |
| { |
| namespace sr |
| { |
| namespace |
| { |
| |
| using tcu::Vec2; |
| using tcu::Vec3; |
| using tcu::Vec4; |
| using tcu::IVec2; |
| using tcu::IVec3; |
| using tcu::IVec4; |
| |
| using std::vector; |
| |
| enum Function |
| { |
| FUNCTION_TEXTURE = 0, //!< texture(), textureOffset(), textureClampARB, textureOffsetClampARB |
| FUNCTION_TEXTUREPROJ, //!< textureProj(), textureProjOffset() |
| FUNCTION_TEXTUREPROJ2, //!< textureProj(sampler1D, vec2) |
| FUNCTION_TEXTUREPROJ3, //!< textureProj(sampler2D, vec3) |
| FUNCTION_TEXTURELOD, // ... |
| FUNCTION_TEXTUREPROJLOD, |
| FUNCTION_TEXTUREPROJLOD2, //!< textureProjLod(sampler1D, vec2) |
| FUNCTION_TEXTUREPROJLOD3, //!< textureProjLod(sampler2D, vec3) |
| FUNCTION_TEXTUREGRAD, //!< textureGrad, textureGradOffset, textureGradClampARB, textureGradOffsetClampARB |
| FUNCTION_TEXTUREPROJGRAD, |
| FUNCTION_TEXTUREPROJGRAD2, //!< textureProjGrad(sampler1D, vec2) |
| 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_TEXTUREPROJ2 || |
| function == FUNCTION_TEXTUREPROJ3); |
| } |
| |
| inline bool functionHasProj (Function function) |
| { |
| return function == FUNCTION_TEXTUREPROJ || |
| function == FUNCTION_TEXTUREPROJ2 || |
| function == FUNCTION_TEXTUREPROJ3 || |
| function == FUNCTION_TEXTUREPROJLOD || |
| function == FUNCTION_TEXTUREPROJLOD2 || |
| function == FUNCTION_TEXTUREPROJLOD3 || |
| function == FUNCTION_TEXTUREPROJGRAD || |
| function == FUNCTION_TEXTUREPROJGRAD2|| |
| function == FUNCTION_TEXTUREPROJGRAD3; |
| } |
| |
| inline bool functionHasGrad (Function function) |
| { |
| return function == FUNCTION_TEXTUREGRAD || |
| function == FUNCTION_TEXTUREPROJGRAD || |
| function == FUNCTION_TEXTUREPROJGRAD2|| |
| function == FUNCTION_TEXTUREPROJGRAD3; |
| } |
| |
| inline bool functionHasLod (Function function) |
| { |
| return function == FUNCTION_TEXTURELOD || |
| function == FUNCTION_TEXTUREPROJLOD || |
| function == FUNCTION_TEXTUREPROJLOD2 || |
| 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; |
| |
| // Lod clamp |
| bool useClamp; |
| float lodClamp; |
| |
| 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) |
| , useClamp (false) |
| , lodClamp (0.0f) |
| { |
| } |
| |
| 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_, |
| bool useClamp_, |
| float lodClamp_) |
| : function (function_) |
| , minCoord (minCoord_) |
| , maxCoord (maxCoord_) |
| , useBias (useBias_) |
| , minLodBias (minLodBias_) |
| , maxLodBias (maxLodBias_) |
| , minDX (minDX_) |
| , maxDX (maxDX_) |
| , minDY (minDY_) |
| , maxDY (maxDY_) |
| , useOffset (useOffset_) |
| , offset (offset_) |
| , useClamp (useClamp_) |
| , lodClamp (lodClamp_) |
| { |
| } |
| }; |
| |
| enum TextureType |
| { |
| TEXTURETYPE_1D = 0, |
| TEXTURETYPE_2D, |
| TEXTURETYPE_3D, |
| TEXTURETYPE_CUBE_MAP, |
| TEXTURETYPE_1D_ARRAY, |
| TEXTURETYPE_2D_ARRAY, |
| TEXTURETYPE_CUBE_ARRAY, |
| |
| 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; |
| float lodClamp; |
| tcu::IVec3 offset; |
| tcu::Vec4 scale; |
| tcu::Vec4 bias; |
| |
| TexLookupParams (void) |
| : lod (0.0f) |
| , lodClamp (0.0f) |
| , offset (0) |
| , scale (1.0f) |
| , bias (0.0f) |
| { |
| } |
| }; |
| |
| // \note LodMode and computeLodFromDerivates functions are copied from glsTextureTestUtil |
| namespace TextureTestUtil |
| { |
| |
| 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 |
| }; |
| |
| // 1D lookup LOD computation. |
| |
| float computeLodFromDerivates (LodMode mode, float dudx, float dudy) |
| { |
| float p = 0.0f; |
| switch (mode) |
| { |
| // \note [mika] Min and max bounds equal to exact with 1D textures |
| case LODMODE_EXACT: |
| case LODMODE_MIN_BOUND: |
| case LODMODE_MAX_BOUND: |
| p = de::max(deFloatAbs(dudx), deFloatAbs(dudy)); |
| break; |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| |
| return deFloatLog2(p); |
| } |
| |
| // 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); |
| } |
| |
| } // TextureTestUtil |
| |
| using namespace TextureTestUtil; |
| |
| 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); |
| } |
| |
| inline float computeLodFromGrad1D (const ShaderEvalContext& c) |
| { |
| float w = (float)c.textures[0].tex1D->getWidth(); |
| return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[2].x()*w); |
| } |
| |
| inline float computeLodFromGrad1DArray (const ShaderEvalContext& c) |
| { |
| float w = (float)c.textures[0].tex1DArray->getWidth(); |
| return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[2].x()*w); |
| } |
| |
| inline float computeLodFromGradCubeArray (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].texCubeArray->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 Vec4 texture1D (const ShaderEvalContext& c, float s, float lod) { return c.textures[0].tex1D->sample(c.textures[0].sampler, s, lod); } |
| inline Vec4 texture1DArray (const ShaderEvalContext& c, float s, float t, float lod) { return c.textures[0].tex1DArray->sample(c.textures[0].sampler, s, t, lod); } |
| inline Vec4 textureCubeArray (const ShaderEvalContext& c, float s, float t, float r, float q, float lod) { return c.textures[0].texCubeArray->sample(c.textures[0].sampler, s, t, r, q, 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 float texture1DShadow (const ShaderEvalContext& c, float ref, float s, float lod) { return c.textures[0].tex1D->sampleCompare(c.textures[0].sampler, ref, s, lod); } |
| inline float texture1DArrayShadow (const ShaderEvalContext& c, float ref, float s, float t, float lod) { return c.textures[0].tex1DArray->sampleCompare(c.textures[0].sampler, ref, s, t, lod); } |
| inline float textureCubeArrayShadow (const ShaderEvalContext& c, float ref, float s, float t, float r, float q, float lod) { return c.textures[0].texCubeArray->sampleCompare(c.textures[0].sampler, ref, s, t, r, q, 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 Vec4 texture1DOffset (const ShaderEvalContext& c, float s, float lod, deInt32 offset) { return c.textures[0].tex1D->sampleOffset(c.textures[0].sampler, s, lod, offset); } |
| inline Vec4 texture1DArrayOffset (const ShaderEvalContext& c, float s, float t, float lod, deInt32 offset) { return c.textures[0].tex1DArray->sampleOffset(c.textures[0].sampler, s, t, 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); } |
| inline float texture1DShadowOffset (const ShaderEvalContext& c, float ref, float s, float lod, deInt32 offset) { return c.textures[0].tex1D->sampleCompareOffset(c.textures[0].sampler, ref, s, lod, offset); } |
| inline float texture1DArrayShadowOffset (const ShaderEvalContext& c, float ref, float s, float t, float lod, deInt32 offset) { return c.textures[0].tex1DArray->sampleCompareOffset(c.textures[0].sampler, ref, s, t, 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 evalTexture1D (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x(), p.lod)*p.scale + p.bias; } |
| static void evalTexture1DArray (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArray(c, c.in[0].x(), c.in[0].y(), p.lod)*p.scale + p.bias; } |
| static void evalTextureCubeArray (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCubeArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[0].w(), 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 evalTexture1DBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x(), p.lod+c.in[1].x())*p.scale + p.bias; } |
| static void evalTexture1DArrayBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArray(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x())*p.scale + p.bias; } |
| static void evalTextureCubeArrayBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCubeArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[0].w(), 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 evalTexture1DProj2 (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/c.in[0].y(), p.lod)*p.scale + p.bias; } |
| static void evalTexture1DProj2Bias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/c.in[0].y(), p.lod+c.in[1].x())*p.scale + p.bias; } |
| static void evalTexture1DProj (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/c.in[0].w(), p.lod)*p.scale + p.bias; } |
| static void evalTexture1DProjBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/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 evalTexture1DLod (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x(), c.in[1].x())*p.scale + p.bias; } |
| static void evalTexture1DArrayLod (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArray(c, c.in[0].x(), c.in[0].y(), c.in[1].x())*p.scale + p.bias; } |
| static void evalTextureCubeArrayLod (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCubeArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[0].w(), 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; } |
| static void evalTexture1DProjLod2 (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/c.in[0].y(), c.in[1].x())*p.scale + p.bias; } |
| static void evalTexture1DProjLod (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/c.in[0].w(), c.in[1].x())*p.scale + p.bias; } |
| |
| static void evalTexture2DBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp))*p.scale + p.bias; } |
| static void evalTextureCubeBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(p.lod+c.in[1].x(), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture2DArrayBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(p.lod+c.in[1].x(), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture3DBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(p.lod+c.in[1].x(), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture1DBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x(), de::max(p.lod+c.in[1].x(), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture1DArrayBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArray(c, c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp))*p.scale + p.bias; } |
| static void evalTextureCubeArrayBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCubeArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[0].w(), de::max(p.lod+c.in[1].x(), p.lodClamp))*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 evalTexture1DOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x(), p.lod, p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DArrayOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArrayOffset(c, c.in[0].x(), c.in[0].y(), p.lod, p.offset.x())*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 evalTexture1DOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x(), p.lod+c.in[1].x(), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DArrayOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArrayOffset(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x(), p.offset.x())*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 evalTexture1DLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x(), c.in[1].x(), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DArrayLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[1].x(), p.offset.x())*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 evalTexture1DProj2Offset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].y(), p.lod, p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DProj2OffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].y(), p.lod+c.in[1].x(), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DProjOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].w(), p.lod, p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DProjOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].w(), p.lod+c.in[1].x(), p.offset.x())*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; } |
| static void evalTexture1DProjLod2Offset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].y(), c.in[1].x(), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DProjLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].w(), c.in[1].x(), p.offset.x())*p.scale + p.bias; } |
| |
| static void evalTexture2DOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset.swizzle(0,1))*p.scale + p.bias; } |
| static void evalTexture2DArrayOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset.swizzle(0,1))*p.scale + p.bias; } |
| static void evalTexture3DOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset)*p.scale + p.bias; } |
| static void evalTexture1DOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DArrayOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArrayOffset(c, c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset.x())*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 evalTexture1DShadow (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadow(c, c.in[0].z(), c.in[0].x(), p.lod); } |
| static void evalTexture1DShadowBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadow(c, c.in[0].z(), c.in[0].x(), p.lod+c.in[1].x()); } |
| static void evalTexture1DArrayShadow (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod); } |
| static void evalTexture1DArrayShadowBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x()); } |
| static void evalTextureCubeArrayShadow (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = textureCubeArrayShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[0].w(), 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 evalTexture1DShadowLod (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture1DShadow(c, c.in[0].z(), c.in[0].x(), c.in[1].x()); } |
| static void evalTexture1DShadowLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[1].x(), p.offset.x()); } |
| static void evalTexture1DArrayShadowLod (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture1DArrayShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), c.in[1].x()); } |
| static void evalTexture1DArrayShadowLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), c.in[1].x(), p.offset.x()); } |
| |
| 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 evalTexture1DShadowProj (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), p.lod); } |
| static void evalTexture1DShadowProjBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/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 evalTexture1DShadowProjLod (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture1DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[1].x()); } |
| static void evalTexture1DShadowProjLodOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[1].x(), p.offset.x()); } |
| |
| 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 evalTexture2DArrayShadowOffset (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(), p.lod, p.offset.swizzle(0,1)); } |
| static void evalTexture1DShadowOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z(), c.in[0].x(), p.lod, p.offset.x()); } |
| static void evalTexture1DShadowOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z(), c.in[0].x(), p.lod+c.in[1].x(), p.offset.x()); } |
| static void evalTexture1DArrayShadowOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod, p.offset.x()); } |
| static void evalTexture1DArrayShadowOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x(), p.offset.x()); } |
| |
| 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)); } |
| static void evalTexture1DShadowProjOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), p.lod, p.offset.x()); } |
| static void evalTexture1DShadowProjOffsetBias (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), p.lod+c.in[1].x(), p.offset.x()); } |
| |
| static void evalTexture2DShadowBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp)); } |
| static void evalTextureCubeShadowBiasClamp (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(), de::max(p.lod+c.in[1].x(), p.lodClamp)); } |
| static void evalTexture1DShadowBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadow(c, c.in[0].z(), c.in[0].x(), de::max(p.lod+c.in[1].x(), p.lodClamp)); } |
| static void evalTexture1DArrayShadowBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp)); } |
| static void evalTexture2DShadowOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset.swizzle(0,1)); } |
| static void evalTexture1DShadowOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z(), c.in[0].x(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset.x()); } |
| static void evalTexture1DArrayShadowOffsetBiasClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(p.lod+c.in[1].x(), p.lodClamp), p.offset.x()); } |
| |
| // 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 evalTexture1DGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x(), computeLodFromGrad1D(c))*p.scale + p.bias; } |
| static void evalTexture1DArrayGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArray(c, c.in[0].x(), c.in[0].y(), computeLodFromGrad1DArray(c))*p.scale + p.bias; } |
| static void evalTextureCubeArrayGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCubeArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[0].w(), computeLodFromGradCubeArray(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 evalTexture1DShadowGrad (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture1DShadow(c, c.in[0].z(), c.in[0].x(), computeLodFromGrad1D(c)); } |
| static void evalTexture1DArrayShadowGrad (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture1DArrayShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), computeLodFromGrad1DArray(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 evalTexture1DGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x(), computeLodFromGrad1D(c), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DArrayGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArrayOffset(c, c.in[0].x(), c.in[0].y(), computeLodFromGrad1DArray(c), p.offset.x())*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 evalTexture1DShadowGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z(), c.in[0].x(), computeLodFromGrad1D(c), p.offset.x()); } |
| static void evalTexture1DArrayShadowGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), computeLodFromGrad1DArray(c), p.offset.x()); } |
| |
| 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 evalTexture1DShadowProjGrad (ShaderEvalContext& c, const TexLookupParams&) { c.color.x() = texture1DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), computeLodFromGrad1D(c)); } |
| static void evalTexture1DShadowProjGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), computeLodFromGrad1D(c), p.offset.x()); } |
| |
| 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 evalTexture1DProjGrad2 (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/c.in[0].y(), computeLodFromGrad1D(c))*p.scale + p.bias; } |
| static void evalTexture1DProjGrad (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x()/c.in[0].w(), computeLodFromGrad1D(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; } |
| static void evalTexture1DProjGrad2Offset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].y(), computeLodFromGrad1D(c), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DProjGradOffset (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x()/c.in[0].w(), computeLodFromGrad1D(c), p.offset.x())*p.scale + p.bias; } |
| |
| static void evalTexture2DGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad2D(c), p.lodClamp))*p.scale + p.bias; } |
| static void evalTextureCubeGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(computeLodFromGradCube(c), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture2DArrayGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(computeLodFromGrad2DArray(c), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture3DGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(computeLodFromGrad3D(c), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture1DGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1D(c, c.in[0].x(), de::max(computeLodFromGrad1D(c), p.lodClamp))*p.scale + p.bias; } |
| static void evalTexture1DArrayGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArray(c, c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad1DArray(c), p.lodClamp))*p.scale + p.bias; } |
| static void evalTextureCubeArrayGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCubeArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[0].w(), de::max(computeLodFromGradCubeArray(c), p.lodClamp))*p.scale + p.bias; } |
| |
| static void evalTexture2DShadowGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad2D(c), p.lodClamp)); } |
| static void evalTextureCubeShadowGradClamp (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(), de::max(computeLodFromGradCube(c), p.lodClamp)); } |
| static void evalTexture2DArrayShadowGradClamp (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(), de::max(computeLodFromGrad2DArray(c), p.lodClamp)); } |
| static void evalTexture1DShadowGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadow(c, c.in[0].z(), c.in[0].x(), de::max(computeLodFromGrad1D(c), p.lodClamp)); } |
| static void evalTexture1DArrayShadowGradClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad1DArray(c), p.lodClamp)); } |
| |
| static void evalTexture2DGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad2D(c), p.lodClamp), p.offset.swizzle(0,1))*p.scale + p.bias; } |
| static void evalTexture2DArrayGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(computeLodFromGrad2DArray(c), p.lodClamp), p.offset.swizzle(0,1))*p.scale + p.bias; } |
| static void evalTexture3DGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), de::max(computeLodFromGrad3D(c), p.lodClamp), p.offset)*p.scale + p.bias; } |
| static void evalTexture1DGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DOffset(c, c.in[0].x(), de::max(computeLodFromGrad1D(c), p.lodClamp), p.offset.x())*p.scale + p.bias; } |
| static void evalTexture1DArrayGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture1DArrayOffset(c, c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad1DArray(c), p.lodClamp), p.offset.x())*p.scale + p.bias; } |
| |
| static void evalTexture2DShadowGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad2D(c), p.lodClamp), p.offset.swizzle(0,1)); } |
| static void evalTexture2DArrayShadowGradOffsetClamp (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(), de::max(computeLodFromGrad2DArray(c), p.lodClamp), p.offset.swizzle(0,1)); } |
| static void evalTexture1DShadowGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DShadowOffset(c, c.in[0].z(), c.in[0].x(), de::max(computeLodFromGrad1D(c), p.lodClamp), p.offset.x()); } |
| static void evalTexture1DArrayShadowGradOffsetClamp (ShaderEvalContext& c, const TexLookupParams& p) { c.color.x() = texture1DArrayShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), de::max(computeLodFromGrad1DArray(c), p.lodClamp), p.offset.x()); } |
| |
| // 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; |
| } |
| |
| static void evalTexelFetch1D (ShaderEvalContext& c, const TexLookupParams& p) |
| { |
| int x = deChopFloatToInt32(c.in[0].x())+p.offset.x(); |
| int lod = deChopFloatToInt32(c.in[1].x()); |
| c.color = c.textures[0].tex1D->getLevel(lod).getPixel(x, 0)*p.scale + p.bias; |
| } |
| |
| static void evalTexelFetch1DArray (ShaderEvalContext& c, const TexLookupParams& p) |
| { |
| int x = deChopFloatToInt32(c.in[0].x())+p.offset.x(); |
| int l = deChopFloatToInt32(c.in[0].y()); |
| int lod = deChopFloatToInt32(c.in[1].x()); |
| c.color = c.textures[0].tex1DArray->getLevel(lod).getPixel(x, l)*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; |
| }; |
| |
| static void checkDeviceFeatures (Context& context, TextureType textureType) |
| { |
| if (textureType == TEXTURETYPE_CUBE_ARRAY) |
| { |
| const vk::VkPhysicalDeviceFeatures& deviceFeatures = context.getDeviceFeatures(); |
| |
| if (!deviceFeatures.imageCubeArray) |
| TCU_THROW(NotSupportedError, "Cube array is not supported"); |
| } |
| } |
| |
| 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, |
| const ImageBackingMode imageBackingMode = IMAGE_BACKING_MODE_REGULAR); |
| 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, |
| const ImageBackingMode imageBackingMode) |
| : ShaderRenderCaseInstance (context, isVertexCase, evaluator, uniformSetup, DE_NULL, imageBackingMode, |
| (isVertexCase ? 92 : GRID_SIZE_DEFAULT_FRAGMENT)) |
| , m_lookupSpec (lookupSpec) |
| , m_textureSpec (textureSpec) |
| , m_lookupParams (lookupParams) |
| { |
| checkDeviceFeatures(m_context, m_textureSpec.type); |
| |
| if (lookupSpec.useClamp) |
| { |
| const vk::VkPhysicalDeviceFeatures& deviceFeatures = context.getDeviceFeatures(); |
| |
| if (!deviceFeatures.shaderResourceMinLod) |
| TCU_THROW(NotSupportedError, "ShaderResourceMinLod feature not supported."); |
| } |
| |
| { |
| // Base coord scale & bias |
| Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord; |
| Vec4 b = m_lookupSpec.minCoord; |
| |
| float baseCoordTrans[] = |
| { |
| s.x(), 0.0f, 0.f, b.x(), |
| 0.f, s.y(), 0.f, b.y(), |
| s.z()/2.f, -s.z()/2.f, 0.f, s.z()/2.f + b.z(), |
| -s.w()/2.f, s.w()/2.f, 0.f, s.w()/2.f + b.w() |
| }; |
| |
| m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans)); |
| |
| 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_TEXTUREPROJ2 ? 1 : 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<tcu::Texture2D> texture2D; |
| |
| texture2D = de::MovePtr<tcu::Texture2D>(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<tcu::TextureCube> textureCube; |
| |
| DE_ASSERT(m_textureSpec.width == m_textureSpec.height); |
| textureCube = de::MovePtr<tcu::TextureCube>(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<tcu::Texture2DArray> texture2DArray; |
| |
| texture2DArray = de::MovePtr<tcu::Texture2DArray>(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<tcu::Texture3D> texture3D; |
| |
| texture3D = de::MovePtr<tcu::Texture3D>(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; |
| } |
| |
| case TEXTURETYPE_1D: |
| { |
| 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 = m_textureSpec.width/4; |
| de::MovePtr<tcu::Texture1D> texture1D; |
| |
| texture1D = de::MovePtr<tcu::Texture1D>(new tcu::Texture1D(texFmt, m_textureSpec.width)); |
| |
| 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); |
| |
| texture1D->allocLevel(level); |
| tcu::fillWithGrid(texture1D->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]; |
| lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f); |
| |
| // Append to texture list. |
| m_textures.push_back(TextureBindingSp(new TextureBinding(texture1D.release(), m_textureSpec.sampler))); |
| break; |
| } |
| |
| case TEXTURETYPE_1D_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 = m_textureSpec.width/4; |
| de::MovePtr<tcu::Texture1DArray> texture1DArray; |
| |
| texture1DArray = de::MovePtr<tcu::Texture1DArray>(new tcu::Texture1DArray(texFmt, m_textureSpec.width, m_textureSpec.depth)); |
| |
| for (int level = 0; level < m_textureSpec.numLevels; level++) |
| { |
| texture1DArray->allocLevel(level); |
| tcu::PixelBufferAccess levelAccess = texture1DArray->getLevel(level); |
| |
| for (int layer = 0; layer < levelAccess.getHeight(); 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, layer, 0, levelAccess.getWidth(), 1, 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]; |
| lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f); |
| |
| // Append to texture list. |
| m_textures.push_back(TextureBindingSp(new TextureBinding(texture1DArray.release(), m_textureSpec.sampler))); |
| break; |
| } |
| |
| case TEXTURETYPE_CUBE_ARRAY: |
| { |
| float layerStep = 1.0f / (float)(m_textureSpec.depth/6); |
| float levelStep = isAutoLod ? 0.0f : 1.0f / (float)(de::max(1, m_textureSpec.numLevels-1)*(m_textureSpec.depth/6)); |
| 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<tcu::TextureCubeArray> textureCubeArray; |
| |
| DE_ASSERT(m_textureSpec.width == m_textureSpec.height); |
| DE_ASSERT(m_textureSpec.depth % 6 == 0); |
| |
| textureCubeArray = de::MovePtr<tcu::TextureCubeArray>(new tcu::TextureCubeArray(texFmt, m_textureSpec.width, m_textureSpec.depth)); |
| |
| for (int level = 0; level < m_textureSpec.numLevels; level++) |
| { |
| float fA = float(level)*levelStep; |
| float fB = 1.0f-fA; |
| Vec2 f (fA, fB); |
| |
| textureCubeArray->allocLevel(level); |
| tcu::PixelBufferAccess levelAccess = textureCubeArray->getLevel(level); |
| |
| for (int layer = 0; layer < m_textureSpec.depth/6; layer++) |
| { |
| float layerCorr = 1.0f-(float)layer*layerStep; |
| |
| 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])*layerCorr; |
| Vec4 colorB = cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3])*layerCorr; |
| |
| { |
| const tcu::PixelBufferAccess access = tcu::getSubregion(levelAccess, 0, 0, (layer*6)+face, levelAccess.getWidth(), levelAccess.getHeight(), 1); |
| 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(textureCubeArray.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; |
| lookupParams.lodClamp = m_lookupSpec.lodClamp; |
| |
| // \todo [dirnerakos] Avoid const cast somehow |
| const_cast<TexLookupParams&>(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; |
| |
| protected: |
| const TextureLookupSpec m_lookupSpec; |
| const TextureSpec m_textureSpec; |
| const TexLookupParams m_lookupParams; |
| |
| void initShaderSources (void); |
| }; |
| |
| 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 is1DProj4 = !isShadow && m_textureSpec.type == TEXTURETYPE_1D && (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_1D ? 1 : |
| m_textureSpec.type == TEXTURETYPE_1D_ARRAY || m_textureSpec.type == TEXTURETYPE_2D ? 2 : |
| m_textureSpec.type == TEXTURETYPE_CUBE_ARRAY ? 4 : |
| 3; |
| int extraCoordComps = (isProj ? (is2DProj4 ? 2 : (is1DProj4 ? 3 : 1)) : 0) + (isShadow ? (m_textureSpec.type == TEXTURETYPE_1D ? 2 : 1) : 0); |
| const bool isCubeArrayShadow = isShadow && m_textureSpec.type == TEXTURETYPE_CUBE_ARRAY; |
| glu::DataType coordType = glu::getDataTypeFloatVec(isCubeArrayShadow ? 4 : 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_1D || m_textureSpec.type == TEXTURETYPE_1D_ARRAY ? glu::TYPE_FLOAT : |
| m_textureSpec.type == TEXTURETYPE_3D || m_textureSpec.type == TEXTURETYPE_CUBE_MAP || m_textureSpec.type == TEXTURETYPE_CUBE_ARRAY ? 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; |
| case TEXTURETYPE_1D: samplerType = isShadow ? glu::TYPE_SAMPLER_1D_SHADOW : glu::getSampler1DType(texFmt); break; |
| case TEXTURETYPE_1D_ARRAY: samplerType = isShadow ? glu::TYPE_SAMPLER_1D_ARRAY_SHADOW : glu::getSampler1DArrayType(texFmt); break; |
| case TEXTURETYPE_CUBE_ARRAY: samplerType = isShadow ? glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW : glu::getSamplerCubeArrayType(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_TEXTUREPROJ2: baseFuncName = "textureProj"; break; |
| case FUNCTION_TEXTUREPROJ3: baseFuncName = "textureProj"; break; |
| case FUNCTION_TEXTURELOD: baseFuncName = "textureLod"; break; |
| case FUNCTION_TEXTUREPROJLOD: baseFuncName = "textureProjLod"; break; |
| case FUNCTION_TEXTUREPROJLOD2: baseFuncName = "textureProjLod"; break; |
| case FUNCTION_TEXTUREPROJLOD3: baseFuncName = "textureProjLod"; break; |
| case FUNCTION_TEXTUREGRAD: baseFuncName = "textureGrad"; break; |
| case FUNCTION_TEXTUREPROJGRAD: baseFuncName = "textureProjGrad"; break; |
| case FUNCTION_TEXTUREPROJGRAD2: 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; |
| glu::GLSLVersion version = glu::GLSL_VERSION_LAST; |
| |
| switch (m_textureSpec.type) |
| { |
| case TEXTURETYPE_2D: |
| case TEXTURETYPE_3D: |
| case TEXTURETYPE_CUBE_MAP: |
| case TEXTURETYPE_2D_ARRAY: |
| version = glu::GLSL_VERSION_310_ES; |
| break; |
| |
| case TEXTURETYPE_1D: |
| case TEXTURETYPE_1D_ARRAY: |
| case TEXTURETYPE_CUBE_ARRAY: |
| version = glu::GLSL_VERSION_420; |
| break; |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| break; |
| } |
| |
| if (m_lookupSpec.useClamp) |
| version = glu::GLSL_VERSION_450; |
| |
| vert << glu::getGLSLVersionDeclaration(version) << "\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 << glu::getGLSLVersionDeclaration(version) << "\n"; |
| |
| if (m_lookupSpec.useClamp) |
| frag << "#extension GL_ARB_sparse_texture_clamp : require\n"; |
| |
| frag << "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"; |
| |
| if (version != glu::GLSL_VERSION_310_ES) |
| vert << "out gl_PerVertex {\n" |
| << "\tvec4 gl_Position;\n" |
| << "};\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"; |
| if (m_lookupSpec.useClamp) |
| op << "ClampARB"; |
| op << "(u_sampler, "; |
| |
| if (isIntCoord) |
| op << glu::getDataTypeName(glu::getDataTypeIntVec(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_1D || m_textureSpec.type == TEXTURETYPE_1D_ARRAY ? 1 : |
| m_textureSpec.type == TEXTURETYPE_3D ? 3 : 2; |
| |
| op << ", " << glu::getDataTypeName(glu::getDataTypeIntVec(offsetComps)) << "("; |
| for (int ndx = 0; ndx < offsetComps; ndx++) |
| { |
| if (ndx != 0) |
| op << ", "; |
| op << m_lookupSpec.offset[ndx]; |
| } |
| op << ")"; |
| } |
| |
| if (m_lookupSpec.useClamp) |
| op << ", float(" << m_lookupSpec.lodClamp << ")"; |
| |
| if (isCubeArrayShadow && m_lookupSpec.function == FUNCTION_TEXTURE) |
| op << ", " << texCoord << ".w"; |
| |
| 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(); |
| } |
| |
| enum QueryFunction |
| { |
| QUERYFUNCTION_TEXTURESIZE = 0, |
| QUERYFUNCTION_TEXTUREQUERYLOD, |
| QUERYFUNCTION_TEXTUREQUERYLEVELS, |
| QUERYFUNCTION_TEXTURESAMPLES, |
| |
| QUERYFUNCTION_LAST |
| }; |
| |
| class TextureQueryInstance : public ShaderRenderCaseInstance |
| { |
| public: |
| TextureQueryInstance (Context& context, |
| const bool isVertexCase, |
| const TextureSpec& textureSpec); |
| virtual ~TextureQueryInstance (void); |
| |
| protected: |
| virtual void setupDefaultInputs (void); |
| virtual void setupUniforms (const tcu::Vec4&); |
| |
| void render (void); |
| |
| protected: |
| const TextureSpec& m_textureSpec; |
| }; |
| |
| TextureQueryInstance::TextureQueryInstance (Context& context, |
| const bool isVertexCase, |
| const TextureSpec& textureSpec) |
| : ShaderRenderCaseInstance (context, isVertexCase, DE_NULL, DE_NULL, DE_NULL) |
| , m_textureSpec (textureSpec) |
| { |
| m_colorFormat = vk::VK_FORMAT_R32G32B32A32_SFLOAT; |
| |
| checkDeviceFeatures(m_context, m_textureSpec.type); |
| } |
| |
| TextureQueryInstance::~TextureQueryInstance (void) |
| { |
| } |
| |
| void TextureQueryInstance::setupDefaultInputs (void) |
| { |
| const deUint32 numVertices = 4; |
| const float positions[] = |
| { |
| -1.0f, -1.0f, 0.0f, 1.0f, |
| -1.0f, 1.0f, 0.0f, 1.0f, |
| 1.0f, -1.0f, 0.0f, 1.0f, |
| 1.0f, 1.0f, 0.0f, 1.0f |
| }; |
| |
| addAttribute(0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 4 * (deUint32)sizeof(float), numVertices, positions); |
| } |
| |
| void TextureQueryInstance::setupUniforms (const tcu::Vec4&) |
| { |
| useSampler(0u, 0u); |
| } |
| |
| void TextureQueryInstance::render (void) |
| { |
| const deUint32 numVertices = 4; |
| const deUint32 numTriangles = 2; |
| const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 }; |
| |
| ShaderRenderCaseInstance::setup(); |
| |
| ShaderRenderCaseInstance::render(numVertices, numTriangles, indices); |
| } |
| |
| static int getMaxTextureSize (TextureType type, const tcu::IVec3& textureSize) |
| { |
| int maxSize = 0; |
| |
| switch (type) |
| { |
| case TEXTURETYPE_1D: |
| case TEXTURETYPE_1D_ARRAY: |
| maxSize = textureSize.x(); |
| break; |
| |
| case TEXTURETYPE_2D: |
| case TEXTURETYPE_2D_ARRAY: |
| case TEXTURETYPE_CUBE_MAP: |
| case TEXTURETYPE_CUBE_ARRAY: |
| maxSize = de::max(textureSize.x(), textureSize.y()); |
| break; |
| |
| case TEXTURETYPE_3D: |
| maxSize = de::max(textureSize.x(), de::max(textureSize.y(), textureSize.z())); |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| |
| return maxSize; |
| } |
| |
| static std::string getTextureSizeString (TextureType type, const tcu::IVec3& textureSize) |
| { |
| std::ostringstream str; |
| |
| switch (type) |
| { |
| case TEXTURETYPE_1D: |
| str << textureSize.x() << "x1"; |
| break; |
| |
| case TEXTURETYPE_2D: |
| case TEXTURETYPE_CUBE_MAP: |
| str << textureSize.x() << "x" << textureSize.y(); |
| break; |
| |
| case TEXTURETYPE_3D: |
| str << textureSize.x() << "x" << textureSize.y() << "x" << textureSize.z(); |
| break; |
| |
| case TEXTURETYPE_1D_ARRAY: |
| str << textureSize.x() << "x1 with " << textureSize.z() << " layer(s)"; |
| break; |
| |
| case TEXTURETYPE_2D_ARRAY: |
| case TEXTURETYPE_CUBE_ARRAY: |
| str << textureSize.x() << "x" << textureSize.y() << " with " << textureSize.z() << " layers(s)"; |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| break; |
| } |
| |
| return str.str(); |
| } |
| |
| static bool isValidCase (TextureType type, const tcu::IVec3& textureSize, int lod, int lodBase) |
| { |
| const bool isSquare = textureSize.x() == textureSize.y(); |
| const bool isCubeArray = isSquare && (textureSize.z() % 6) == 0; |
| const int maxSize = getMaxTextureSize(type, textureSize); |
| const bool isLodValid = (maxSize >> (lod + lodBase)) != 0; |
| |
| if (!isLodValid) |
| return false; |
| if (type == TEXTURETYPE_CUBE_MAP && !isSquare) |
| return false; |
| if (type == TEXTURETYPE_CUBE_ARRAY && !isCubeArray) |
| return false; |
| |
| return true; |
| } |
| |
| static TextureBindingSp createEmptyTexture (deUint32 format, |
| TextureType type, |
| const tcu::IVec3& textureSize, |
| int numLevels, |
| int lodBase, |
| const tcu::Sampler& sampler) |
| { |
| const tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format); |
| const TextureBinding::Parameters params (lodBase); |
| TextureBindingSp textureBinding; |
| |
| switch (type) |
| { |
| |
| case TEXTURETYPE_1D: |
| { |
| de::MovePtr<tcu::Texture1D> texture (new tcu::Texture1D(texFmt, textureSize.x())); |
| |
| for (int level = 0; level < numLevels; level++) |
| texture->allocLevel(level); |
| |
| textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler)); |
| break; |
| } |
| |
| case TEXTURETYPE_2D: |
| { |
| de::MovePtr<tcu::Texture2D> texture (new tcu::Texture2D(texFmt, textureSize.x(), textureSize.y())); |
| |
| for (int level = 0; level < numLevels; level++) |
| texture->allocLevel(level); |
| |
| textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler)); |
| break; |
| } |
| |
| case TEXTURETYPE_3D: |
| { |
| de::MovePtr<tcu::Texture3D> texture (new tcu::Texture3D(texFmt, textureSize.x(), textureSize.y(), textureSize.z())); |
| |
| for (int level = 0; level < numLevels; level++) |
| texture->allocLevel(level); |
| |
| textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler)); |
| break; |
| } |
| |
| case TEXTURETYPE_CUBE_MAP: |
| { |
| de::MovePtr<tcu::TextureCube> texture (new tcu::TextureCube(texFmt, textureSize.x())); |
| |
| for (int level = 0; level < numLevels; level++) |
| for (int face = 0; face < tcu::CUBEFACE_LAST; face++) |
| texture->allocLevel((tcu::CubeFace)face, level); |
| |
| textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler)); |
| break; |
| } |
| |
| case TEXTURETYPE_1D_ARRAY: |
| { |
| de::MovePtr<tcu::Texture1DArray> texture (new tcu::Texture1DArray(texFmt, textureSize.x(), textureSize.z())); |
| |
| for (int level = 0; level < numLevels; level++) |
| texture->allocLevel(level); |
| |
| textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler)); |
| break; |
| } |
| |
| case TEXTURETYPE_2D_ARRAY: |
| { |
| de::MovePtr<tcu::Texture2DArray> texture (new tcu::Texture2DArray(texFmt, textureSize.x(), textureSize.y(), textureSize.z())); |
| |
| for (int level = 0; level < numLevels; level++) |
| texture->allocLevel(level); |
| |
| textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler)); |
| break; |
| } |
| |
| case TEXTURETYPE_CUBE_ARRAY: |
| { |
| de::MovePtr<tcu::TextureCubeArray> texture (new tcu::TextureCubeArray(texFmt, textureSize.x(), textureSize.z())); |
| |
| for (int level = 0; level < numLevels; level++) |
| texture->allocLevel(level); |
| |
| textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler)); |
| break; |
| } |
| |
| default: |
| DE_ASSERT(false); |
| break; |
| } |
| |
| textureBinding->setParameters(params); |
| return textureBinding; |
| } |
| |
| static inline glu::DataType getTextureSizeFuncResultType (TextureType textureType) |
| { |
| switch (textureType) |
| { |
| case TEXTURETYPE_1D: |
| return glu::TYPE_INT; |
| |
| case TEXTURETYPE_2D: |
| case TEXTURETYPE_CUBE_MAP: |
| case TEXTURETYPE_1D_ARRAY: |
| return glu::TYPE_INT_VEC2; |
| |
| case TEXTURETYPE_3D: |
| case TEXTURETYPE_2D_ARRAY: |
| case TEXTURETYPE_CUBE_ARRAY: |
| return glu::TYPE_INT_VEC3; |
| |
| default: |
| DE_ASSERT(false); |
| return glu::TYPE_LAST; |
| } |
| } |
| |
| class TextureSizeInstance : public TextureQueryInstance |
| { |
| public: |
| TextureSizeInstance (Context& context, |
| const bool isVertexCase, |
| const TextureSpec& textureSpec); |
| virtual ~TextureSizeInstance (void); |
| |
| virtual tcu::TestStatus iterate (void); |
| |
| protected: |
| virtual void setupUniforms (const tcu::Vec4& constCoords); |
| |
| private: |
| struct TestSize |
| { |
| tcu::IVec3 textureSize; |
| int lod; |
| int lodBase; |
| tcu::IVec3 expectedSize; |
| }; |
| |
| void initTexture (void); |
| bool testTextureSize (void); |
| |
| TestSize m_testSize; |
| tcu::IVec3 m_expectedSize; |
| int m_iterationCounter; |
| }; |
| |
| TextureSizeInstance:
|