1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2014 The Android Open Source Project
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * \brief Texture filtering tests.
24 *//*--------------------------------------------------------------------*/
26 #include "tcuVectorUtil.hpp"
27 #include "tcuTexVerifierUtil.hpp"
28 #include "vkImageUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestCaseUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36 #include "vktTextureFilteringTests.hpp"
37 #include "vktTextureTestUtil.hpp"
56 using namespace texture::util;
57 using namespace glu::TextureTestUtil;
61 TEXCUBE_VIEWPORT_SIZE = 28,
63 TEX2D_VIEWPORT_WIDTH = 64,
64 TEX2D_VIEWPORT_HEIGHT = 64,
66 TEX3D_VIEWPORT_WIDTH = 64,
67 TEX3D_VIEWPORT_HEIGHT = 64,
70 class Texture2DFilteringTestInstance : public TestInstance
73 typedef Texture2DTestCaseParameters ParameterType;
75 Texture2DFilteringTestInstance (Context& context, const ParameterType& testParameters);
76 ~Texture2DFilteringTestInstance (void);
78 virtual tcu::TestStatus iterate (void);
80 Texture2DFilteringTestInstance (const Texture2DFilteringTestInstance& other);
81 Texture2DFilteringTestInstance& operator= (const Texture2DFilteringTestInstance& other);
95 FilterCase (int tex_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
97 , minCoord (minCoord_)
98 , maxCoord (maxCoord_)
103 const ParameterType m_testParameters;
104 vector<TestTexture2DSp> m_textures;
105 vector<FilterCase> m_cases;
106 TextureRenderer m_renderer;
110 Texture2DFilteringTestInstance::Texture2DFilteringTestInstance (Context& context, const ParameterType& testParameters)
111 : TestInstance (context)
112 , m_testParameters (testParameters)
113 , m_renderer (context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
116 const bool mipmaps = true;
117 const int numLevels = mipmaps ? deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height))+1 : 1;
118 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
119 const tcu::Vec4 cBias = fmtInfo.valueMin;
120 const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
122 // Create 2 textures.
123 m_textures.reserve(2);
124 for (int ndx = 0; ndx < 2; ndx++)
125 m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
127 // Fill first gradient texture.
128 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
130 const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
131 const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
133 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
136 // Fill second with grid texture.
137 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
139 const deUint32 step = 0x00ffffff / numLevels;
140 const deUint32 rgb = step*levelNdx;
141 const deUint32 colorA = 0xff000000 | rgb;
142 const deUint32 colorB = 0xff000000 | ~rgb;
144 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
148 for (vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
150 m_renderer.add2DTexture(*i);
164 { 0, 1.6f, 2.9f, -1.0f, -2.7f },
165 { 0, -2.0f, -1.35f, -0.2f, 0.7f },
166 { 1, 0.14f, 0.275f, -1.5f, -1.1f },
167 { 1, -0.92f, -2.64f, 0.4f, -0.1f },
170 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
172 const int texNdx = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
173 const float lodX = cases[caseNdx].lodX;
174 const float lodY = cases[caseNdx].lodY;
175 const float oX = cases[caseNdx].oX;
176 const float oY = cases[caseNdx].oY;
177 const float sX = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
178 const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[texNdx]->getTexture().getHeight());
180 m_cases.push_back(FilterCase(texNdx, tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY)));
185 Texture2DFilteringTestInstance::~Texture2DFilteringTestInstance (void)
189 tcu::TestStatus Texture2DFilteringTestInstance::iterate (void)
191 tcu::TestLog& log = m_context.getTestContext().getLog();
193 const pipeline::TestTexture2D& texture = m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
194 const tcu::TextureFormat texFmt = texture.getTextureFormat();
195 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
196 const FilterCase& curCase = m_cases[m_caseNdx];
197 ReferenceParams refParams (TEXTURETYPE_2D);
198 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
199 vector<float> texCoord;
201 // Setup params for reference.
203 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
204 refParams.samplerType = getSamplerType(texFmt);
205 refParams.lodMode = LODMODE_EXACT;
206 refParams.colorBias = fmtInfo.lookupBias;
207 refParams.colorScale = fmtInfo.lookupScale;
209 // Compute texture coordinates.
210 log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
211 computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
213 m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
216 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
217 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
218 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
219 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
220 tcu::LodPrecision lodPrecision (tcu::LodPrecision::RULE_VULKAN);
221 tcu::LookupPrecision lookupPrecision;
223 lodPrecision.derivateBits = 18;
224 lodPrecision.lodBits = 6;
225 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
226 lookupPrecision.coordBits = tcu::IVec3(20,20,0);
227 lookupPrecision.uvwBits = tcu::IVec3(7,7,0);
228 lookupPrecision.colorMask = getCompareMask(pixelFormat);
230 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DView)texture.getTexture(),
231 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
235 // Evaluate against lower precision requirements.
236 lodPrecision.lodBits = 4;
237 lookupPrecision.uvwBits = tcu::IVec3(4,4,0);
239 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
241 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DView)texture.getTexture(),
242 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
246 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
247 return tcu::TestStatus::fail("Image verification failed");
253 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
256 struct TextureCubeFilteringTestCaseParameters : public TextureCubeTestCaseParameters
258 bool onlySampleFaceInterior;
261 class TextureCubeFilteringTestInstance : public TestInstance
264 typedef TextureCubeFilteringTestCaseParameters ParameterType;
266 TextureCubeFilteringTestInstance (Context& context, const ParameterType& testParameters);
267 ~TextureCubeFilteringTestInstance (void);
269 virtual tcu::TestStatus iterate (void);
272 TextureCubeFilteringTestInstance (const TextureCubeFilteringTestInstance& other);
273 TextureCubeFilteringTestInstance& operator= (const TextureCubeFilteringTestInstance& other);
278 tcu::Vec2 bottomLeft;
286 FilterCase (int tex_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
287 : textureIndex (tex_)
288 , bottomLeft (bottomLeft_)
289 , topRight (topRight_)
294 const ParameterType m_testParameters;
295 vector<TestTextureCubeSp> m_textures;
296 vector<FilterCase> m_cases;
297 TextureRenderer m_renderer;
301 TextureCubeFilteringTestInstance::TextureCubeFilteringTestInstance (Context& context, const ParameterType& testParameters)
302 : TestInstance (context)
303 , m_testParameters (testParameters)
304 , m_renderer (context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
307 const int numLevels = deLog2Floor32(m_testParameters.size)+1;
308 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
309 const tcu::Vec4 cBias = fmtInfo.valueMin;
310 const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
312 m_textures.reserve(2);
313 for (int ndx = 0; ndx < 2; ndx++)
314 m_textures.push_back(TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
316 // Fill first with gradient texture.
317 static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
319 { tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
320 { tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
321 { tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
322 { tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
323 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
324 { tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z
327 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
329 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
331 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
335 // Fill second with grid texture.
336 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
338 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
340 const deUint32 step = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
341 const deUint32 rgb = step*levelNdx*face;
342 const deUint32 colorA = 0xff000000 | rgb;
343 const deUint32 colorB = 0xff000000 | ~rgb;
345 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
350 for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
352 m_renderer.addCubeTexture(*i);
358 const int tex1 = m_textures.size() > 1 ? 1 : 0;
360 if (m_testParameters.onlySampleFaceInterior)
362 m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
363 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f))); // magnification
364 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
365 m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f), tcu::Vec2(0.6f, 0.5f))); // magnification
369 m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f))); // minification
371 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.8f, 0.8f), tcu::Vec2(1.25f, 1.20f))); // magnification
372 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f))); // minification
373 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.2f, -1.1f), tcu::Vec2(-0.8f, -0.8f))); // magnification
378 TextureCubeFilteringTestInstance::~TextureCubeFilteringTestInstance (void)
382 const char* getFaceDesc (const tcu::CubeFace face)
386 case tcu::CUBEFACE_NEGATIVE_X: return "-X";
387 case tcu::CUBEFACE_POSITIVE_X: return "+X";
388 case tcu::CUBEFACE_NEGATIVE_Y: return "-Y";
389 case tcu::CUBEFACE_POSITIVE_Y: return "+Y";
390 case tcu::CUBEFACE_NEGATIVE_Z: return "-Z";
391 case tcu::CUBEFACE_POSITIVE_Z: return "+Z";
398 tcu::TestStatus TextureCubeFilteringTestInstance::iterate (void)
400 tcu::TestLog& log = m_context.getTestContext().getLog();
402 const pipeline::TestTextureCube& texture = m_renderer.getCubeTexture(m_cases[m_caseNdx].textureIndex);
403 const tcu::TextureFormat texFmt = texture.getTextureFormat();
404 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
405 const FilterCase& curCase = m_cases[m_caseNdx];
406 ReferenceParams refParams (TEXTURETYPE_CUBE);
408 // Params for reference computation.
409 refParams.sampler = util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
410 refParams.sampler.seamlessCubeMap = true;
411 refParams.samplerType = getSamplerType(texFmt);
412 refParams.lodMode = LODMODE_EXACT;
413 refParams.colorBias = fmtInfo.lookupBias;
414 refParams.colorScale = fmtInfo.lookupScale;
416 log << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight << TestLog::EndMessage;
418 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
420 const tcu::CubeFace face = tcu::CubeFace(faceNdx);
421 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
422 vector<float> texCoord;
424 computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
426 log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
428 // \todo Log texture coordinates.
430 m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
433 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
434 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
435 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
436 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
437 tcu::LodPrecision lodPrecision (tcu::LodPrecision::RULE_VULKAN);
438 tcu::LookupPrecision lookupPrecision;
440 lodPrecision.derivateBits = 10;
441 lodPrecision.lodBits = 5;
442 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
443 lookupPrecision.coordBits = tcu::IVec3(10,10,10);
444 lookupPrecision.uvwBits = tcu::IVec3(6,6,0);
445 lookupPrecision.colorMask = getCompareMask(pixelFormat);
447 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::TextureCubeView)texture.getTexture(),
448 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
452 // Evaluate against lower precision requirements.
453 lodPrecision.lodBits = 4;
454 lookupPrecision.uvwBits = tcu::IVec3(4,4,0);
456 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
458 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::TextureCubeView)texture.getTexture(),
459 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
463 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
464 return tcu::TestStatus::fail("Image verification failed");
471 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
474 // 2D array filtering
476 class Texture2DArrayFilteringTestInstance : public TestInstance
479 typedef Texture2DArrayTestCaseParameters ParameterType;
481 Texture2DArrayFilteringTestInstance (Context& context, const ParameterType& testParameters);
482 ~Texture2DArrayFilteringTestInstance (void);
484 virtual tcu::TestStatus iterate (void);
487 Texture2DArrayFilteringTestInstance (const Texture2DArrayFilteringTestInstance&);
488 Texture2DArrayFilteringTestInstance& operator= (const Texture2DArrayFilteringTestInstance&);
495 tcu::Vec2 layerRange;
502 FilterCase (const int tex_, const tcu::Vec2& lod_, const tcu::Vec2& offset_, const tcu::Vec2& layerRange_)
503 : textureIndex (tex_)
506 , layerRange (layerRange_)
511 const ParameterType m_testParameters;
512 vector<TestTexture2DArraySp> m_textures;
513 vector<FilterCase> m_cases;
514 TextureRenderer m_renderer;
518 Texture2DArrayFilteringTestInstance::Texture2DArrayFilteringTestInstance (Context& context, const ParameterType& testParameters)
519 : TestInstance (context)
520 , m_testParameters (testParameters)
521 , m_renderer (context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
524 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
525 const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
526 const tcu::Vec4 cBias = fmtInfo.valueMin;
527 const int numLevels = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1;
530 m_textures.reserve(2);
531 for (int ndx = 0; ndx < 2; ndx++)
532 m_textures.push_back(TestTexture2DArraySp(new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.numLayers)));
534 const tcu::IVec4 levelSwz[] =
542 // Fill first gradient texture (gradient direction varies between layers).
543 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
545 for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
547 const tcu::PixelBufferAccess levelBuf = m_textures[0]->getLevel(levelNdx, layerNdx);
549 const tcu::IVec4 swz = levelSwz[layerNdx%DE_LENGTH_OF_ARRAY(levelSwz)];
550 const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;
551 const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;
553 tcu::fillWithComponentGradients(levelBuf, gMin, gMax);
557 // Fill second with grid texture (each layer has unique colors).
558 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
560 for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
562 const tcu::PixelBufferAccess levelBuf = m_textures[1]->getLevel(levelNdx, layerNdx);
564 const deUint32 step = 0x00ffffff / (numLevels*m_testParameters.numLayers - 1);
565 const deUint32 rgb = step * (levelNdx + layerNdx*numLevels);
566 const deUint32 colorA = 0xff000000 | rgb;
567 const deUint32 colorB = 0xff000000 | ~rgb;
569 tcu::fillWithGrid(levelBuf, 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
574 for (vector<TestTexture2DArraySp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
576 m_renderer.add2DArrayTexture(*i);
580 m_cases.push_back(FilterCase(0, tcu::Vec2( 1.5f, 2.8f ), tcu::Vec2(-1.0f, -2.7f), tcu::Vec2(-0.5f, float(m_testParameters.numLayers)+0.5f)));
581 m_cases.push_back(FilterCase(1, tcu::Vec2( 0.2f, 0.175f), tcu::Vec2(-2.0f, -3.7f), tcu::Vec2(-0.5f, float(m_testParameters.numLayers)+0.5f)));
582 m_cases.push_back(FilterCase(1, tcu::Vec2(-0.8f, -2.3f ), tcu::Vec2( 0.2f, -0.1f), tcu::Vec2(float(m_testParameters.numLayers)+0.5f, -0.5f)));
583 m_cases.push_back(FilterCase(0, tcu::Vec2(-2.0f, -1.5f ), tcu::Vec2(-0.1f, 0.9f), tcu::Vec2(1.50001f, 1.49999f)));
586 Texture2DArrayFilteringTestInstance::~Texture2DArrayFilteringTestInstance (void)
590 tcu::TestStatus Texture2DArrayFilteringTestInstance::iterate (void)
592 tcu::TestLog& log = m_context.getTestContext().getLog();
594 const FilterCase& curCase = m_cases[m_caseNdx];
595 const pipeline::TestTexture2DArray& texture = m_renderer.get2DArrayTexture(curCase.textureIndex);
596 const tcu::TextureFormat texFmt = texture.getTextureFormat();
597 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
598 ReferenceParams refParams (TEXTURETYPE_2D_ARRAY);
599 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
600 tcu::Vec3 texCoord[4];
601 const float* const texCoordPtr = (const float*)&texCoord[0];
603 // Params for reference computation.
605 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
606 refParams.samplerType = getSamplerType(texFmt);
607 refParams.lodMode = LODMODE_EXACT;
608 refParams.colorBias = fmtInfo.lookupBias;
609 refParams.colorScale = fmtInfo.lookupScale;
611 // Compute texture coordinates.
612 log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset << TestLog::EndMessage;
615 const float lodX = curCase.lod.x();
616 const float lodY = curCase.lod.y();
617 const float oX = curCase.offset.x();
618 const float oY = curCase.offset.y();
619 const float sX = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
620 const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
621 const float l0 = curCase.layerRange.x();
622 const float l1 = curCase.layerRange.y();
624 texCoord[0] = tcu::Vec3(oX, oY, l0);
625 texCoord[1] = tcu::Vec3(oX, oY+sY, l0*0.5f + l1*0.5f);
626 texCoord[2] = tcu::Vec3(oX+sX, oY, l0*0.5f + l1*0.5f);
627 texCoord[3] = tcu::Vec3(oX+sX, oY+sY, l1);
630 m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
634 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
635 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
636 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
637 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
638 tcu::LodPrecision lodPrecision (tcu::LodPrecision::RULE_VULKAN);
639 tcu::LookupPrecision lookupPrecision;
641 lodPrecision.derivateBits = 18;
642 lodPrecision.lodBits = 6;
643 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
644 lookupPrecision.coordBits = tcu::IVec3(20,20,20);
645 lookupPrecision.uvwBits = tcu::IVec3(7,7,0);
646 lookupPrecision.colorMask = getCompareMask(pixelFormat);
648 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DArrayView)texture.getTexture(),
649 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
653 // Evaluate against lower precision requirements.
654 lodPrecision.lodBits = 4;
655 lookupPrecision.uvwBits = tcu::IVec3(4,4,0);
657 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
659 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DArrayView)texture.getTexture(),
660 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
664 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
665 return tcu::TestStatus::fail("Image verification failed");
671 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
676 class Texture3DFilteringTestInstance : public TestInstance
679 typedef Texture3DTestCaseParameters ParameterType;
681 Texture3DFilteringTestInstance (Context& context, const ParameterType& testParameters);
682 ~Texture3DFilteringTestInstance (void);
684 virtual tcu::TestStatus iterate (void);
687 Texture3DFilteringTestInstance (const Texture3DFilteringTestInstance& other);
688 Texture3DFilteringTestInstance& operator= (const Texture3DFilteringTestInstance& other);
701 FilterCase (const int tex_, const tcu::Vec3& lod_, const tcu::Vec3& offset_)
702 : textureIndex (tex_)
709 const ParameterType m_testParameters;
710 vector<TestTexture3DSp> m_textures;
711 vector<FilterCase> m_cases;
712 TextureRenderer m_renderer;
716 Texture3DFilteringTestInstance::Texture3DFilteringTestInstance (Context& context, const ParameterType& testParameters)
717 : TestInstance (context)
718 , m_testParameters (testParameters)
719 , m_renderer (context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
722 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
723 const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
724 const tcu::Vec4 cBias = fmtInfo.valueMin;
725 const int numLevels = deLog2Floor32(de::max(de::max(m_testParameters.width, m_testParameters.height), m_testParameters.depth)) + 1;
728 m_textures.reserve(2);
729 for (int ndx = 0; ndx < 2; ndx++)
730 m_textures.push_back(TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.depth)));
732 // Fill first gradient texture.
733 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
735 const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
736 const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
738 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
741 // Fill second with grid texture.
742 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
744 const deUint32 step = 0x00ffffff / numLevels;
745 const deUint32 rgb = step*levelNdx;
746 const deUint32 colorA = 0xff000000 | rgb;
747 const deUint32 colorB = 0xff000000 | ~rgb;
749 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
753 for (vector<TestTexture3DSp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
755 m_renderer.add3DTexture(*i);
759 m_cases.push_back(FilterCase(0, tcu::Vec3(1.5f, 2.8f, 1.0f), tcu::Vec3(-1.0f, -2.7f, -2.275f)));
760 m_cases.push_back(FilterCase(0, tcu::Vec3(-2.0f, -1.5f, -1.8f), tcu::Vec3(-0.1f, 0.9f, -0.25f)));
761 m_cases.push_back(FilterCase(1, tcu::Vec3(0.2f, 0.175f, 0.3f), tcu::Vec3(-2.0f, -3.7f, -1.825f)));
762 m_cases.push_back(FilterCase(1, tcu::Vec3(-0.8f, -2.3f, -2.5f), tcu::Vec3(0.2f, -0.1f, 1.325f)));
765 Texture3DFilteringTestInstance::~Texture3DFilteringTestInstance (void)
769 tcu::TestStatus Texture3DFilteringTestInstance::iterate (void)
771 tcu::TestLog& log = m_context.getTestContext().getLog();
773 const pipeline::TestTexture3D& texture = m_renderer.get3DTexture(m_cases[m_caseNdx].textureIndex);
774 const tcu::TextureFormat texFmt = texture.getTextureFormat();
775 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
776 const FilterCase& curCase = m_cases[m_caseNdx];
777 ReferenceParams refParams (TEXTURETYPE_3D);
778 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
779 tcu::Vec3 texCoord[4];
780 const float* const texCoordPtr = (const float*)&texCoord[0];
782 // Params for reference computation.
783 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.wrapR, m_testParameters.minFilter, m_testParameters.magFilter);
784 refParams.samplerType = getSamplerType(texFmt);
785 refParams.lodMode = LODMODE_EXACT;
786 refParams.colorBias = fmtInfo.lookupBias;
787 refParams.colorScale = fmtInfo.lookupScale;
789 // Compute texture coordinates.
790 log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset << TestLog::EndMessage;
793 const float lodX = curCase.lod.x();
794 const float lodY = curCase.lod.y();
795 const float lodZ = curCase.lod.z();
796 const float oX = curCase.offset.x();
797 const float oY = curCase.offset.y();
798 const float oZ = curCase.offset.z();
799 const float sX = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
800 const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
801 const float sZ = deFloatExp2(lodZ) * float(de::max(m_renderer.getRenderWidth(), m_renderer.getRenderHeight())) / float(m_textures[0]->getTexture().getDepth());
803 texCoord[0] = tcu::Vec3(oX, oY, oZ);
804 texCoord[1] = tcu::Vec3(oX, oY+sY, oZ + sZ*0.5f);
805 texCoord[2] = tcu::Vec3(oX+sX, oY, oZ + sZ*0.5f);
806 texCoord[3] = tcu::Vec3(oX+sX, oY+sY, oZ + sZ);
809 m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
812 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
813 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
814 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
815 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
816 tcu::LodPrecision lodPrecision (tcu::LodPrecision::RULE_VULKAN);
817 tcu::LookupPrecision lookupPrecision;
819 lodPrecision.derivateBits = 18;
820 lodPrecision.lodBits = 6;
821 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
822 lookupPrecision.coordBits = tcu::IVec3(20,20,20);
823 lookupPrecision.uvwBits = tcu::IVec3(7,7,7);
824 lookupPrecision.colorMask = getCompareMask(pixelFormat);
826 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture3DView)texture.getTexture(),
827 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
831 // Evaluate against lower precision requirements.
832 lodPrecision.lodBits = 4;
833 lookupPrecision.uvwBits = tcu::IVec3(4,4,4);
835 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
837 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture3DView)texture.getTexture(),
838 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
842 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
843 return tcu::TestStatus::fail("Image verification failed");
849 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
852 bool verifierCanBeUsed(const VkFormat format, const Sampler::FilterMode minFilter, const Sampler::FilterMode magFilter)
854 const tcu::TextureFormat textureFormat = mapVkFormat(format);
855 const tcu::TextureChannelClass textureChannelClass = tcu::getTextureChannelClass(textureFormat.type);
857 return !(!(textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
858 textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
859 textureChannelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) &&
860 (tcu::TexVerifierUtil::isLinearFilter(minFilter) || tcu::TexVerifierUtil::isLinearFilter(magFilter)));
863 void populateTextureFilteringTests (tcu::TestCaseGroup* textureFilteringTests)
865 tcu::TestContext& testCtx = textureFilteringTests->getTestContext();
869 const char* const name;
870 const Sampler::WrapMode mode;
873 { "repeat", Sampler::REPEAT_GL },
874 { "mirrored_repeat", Sampler::MIRRORED_REPEAT_GL },
875 { "clamp_to_edge", Sampler::CLAMP_TO_EDGE },
876 { "clamp_to_border", Sampler::CLAMP_TO_BORDER },
877 { "mirror_clamp_to_edge", Sampler::MIRRORED_ONCE }
882 const char* const name;
883 const Sampler::FilterMode mode;
886 { "nearest", Sampler::NEAREST },
887 { "linear", Sampler::LINEAR },
888 { "nearest_mipmap_nearest", Sampler::NEAREST_MIPMAP_NEAREST },
889 { "linear_mipmap_nearest", Sampler::LINEAR_MIPMAP_NEAREST },
890 { "nearest_mipmap_linear", Sampler::NEAREST_MIPMAP_LINEAR },
891 { "linear_mipmap_linear", Sampler::LINEAR_MIPMAP_LINEAR }
896 const char* const name;
897 const Sampler::FilterMode mode;
900 { "nearest", Sampler::NEAREST },
901 { "linear", Sampler::LINEAR }
960 const char* const name;
961 const VkFormat format;
962 } filterableFormatsByType[] =
964 { "r16g16b16a16_sfloat", VK_FORMAT_R16G16B16A16_SFLOAT },
965 { "b10g11r11_ufloat", VK_FORMAT_B10G11R11_UFLOAT_PACK32 },
966 { "e5b9g9r9_ufloat", VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 },
967 { "r8g8b8a8_unorm", VK_FORMAT_R8G8B8A8_UNORM },
968 { "r8g8b8a8_snorm", VK_FORMAT_R8G8B8A8_SNORM },
969 { "r5g6b5_unorm", VK_FORMAT_R5G6B5_UNORM_PACK16 },
970 { "r4g4b4a4_unorm", VK_FORMAT_R4G4B4A4_UNORM_PACK16 },
971 { "r5g5b5a1_unorm", VK_FORMAT_R5G5B5A1_UNORM_PACK16 },
972 { "a8b8g8r8_srgb", VK_FORMAT_A8B8G8R8_SRGB_PACK32 },
973 { "a1r5g5b5_unorm", VK_FORMAT_A1R5G5B5_UNORM_PACK16 }
976 // 2D texture filtering.
978 de::MovePtr<tcu::TestCaseGroup> group2D (new tcu::TestCaseGroup(testCtx, "2d", "2D Texture Filtering"));
980 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
981 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
982 de::MovePtr<tcu::TestCaseGroup> combinationsGroup (new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
985 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
987 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
989 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
990 const char* const filterName = minFilterModes[filterNdx].name;
991 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
992 const char* const formatName = filterableFormatsByType[fmtNdx].name;
993 const string name = string(formatName) + "_" + filterName;
994 Texture2DTestCaseParameters testParameters;
996 testParameters.format = filterableFormatsByType[fmtNdx].format;
997 testParameters.minFilter = minFilter;
998 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1000 testParameters.wrapS = Sampler::REPEAT_GL;
1001 testParameters.wrapT = Sampler::REPEAT_GL;
1002 testParameters.width = 64;
1003 testParameters.height = 64;
1005 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1006 testParameters.programs.push_back(PROGRAM_2D_UINT);
1008 // Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1009 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1011 formatsGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1017 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1019 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1021 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1022 const char* const filterName = minFilterModes[filterNdx].name;
1023 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1024 const string name = de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height) + "_" + filterName;
1025 Texture2DTestCaseParameters testParameters;
1027 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1028 testParameters.minFilter = minFilter;
1029 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1030 testParameters.wrapS = Sampler::REPEAT_GL;
1031 testParameters.wrapT = Sampler::REPEAT_GL;
1032 testParameters.width = sizes2D[sizeNdx].width;
1033 testParameters.height = sizes2D[sizeNdx].height;
1035 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1037 sizesGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1042 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1044 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1046 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1048 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1050 const string name = string(minFilterModes[minFilterNdx].name) + "_" + magFilterModes[magFilterNdx].name + "_" + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
1051 Texture2DTestCaseParameters testParameters;
1053 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1054 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1055 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1056 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1057 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1058 testParameters.width = 63;
1059 testParameters.height = 57;
1061 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1063 combinationsGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1069 group2D->addChild(formatsGroup.release());
1070 group2D->addChild(sizesGroup.release());
1071 group2D->addChild(combinationsGroup.release());
1073 textureFilteringTests->addChild(group2D.release());
1076 // Cube map texture filtering.
1078 de::MovePtr<tcu::TestCaseGroup> groupCube (new tcu::TestCaseGroup(testCtx, "cube", "Cube Map Texture Filtering"));
1080 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1081 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1082 de::MovePtr<tcu::TestCaseGroup> combinationsGroup (new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1083 de::MovePtr<tcu::TestCaseGroup> onlyFaceInteriorGroup (new tcu::TestCaseGroup(testCtx, "no_edges_visible", "Don't sample anywhere near a face's edges"));
1086 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1088 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1090 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1091 const char* const filterName = minFilterModes[filterNdx].name;
1092 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1093 const char* const formatName = filterableFormatsByType[fmtNdx].name;
1094 const string name = string(formatName) + "_" + filterName;
1095 TextureCubeFilteringTestCaseParameters testParameters;
1097 testParameters.format = filterableFormatsByType[fmtNdx].format;
1098 testParameters.minFilter = minFilter;
1099 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1101 testParameters.wrapS = Sampler::REPEAT_GL;
1102 testParameters.wrapT = Sampler::REPEAT_GL;
1103 testParameters.onlySampleFaceInterior = false;
1104 testParameters.size = 64;
1106 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1107 testParameters.programs.push_back(PROGRAM_CUBE_UINT);
1109 // Some tests have to be skipped due to the restrictions of the verifiers.
1110 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1112 formatsGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1118 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
1120 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1122 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1123 const char* const filterName = minFilterModes[filterNdx].name;
1124 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1125 const string name = de::toString(sizesCube[sizeNdx].size) + "x" + de::toString(sizesCube[sizeNdx].size) + "_" + filterName;
1126 TextureCubeFilteringTestCaseParameters testParameters;
1128 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1129 testParameters.minFilter = minFilter;
1130 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1131 testParameters.wrapS = Sampler::REPEAT_GL;
1132 testParameters.wrapT = Sampler::REPEAT_GL;
1133 testParameters.onlySampleFaceInterior = false;
1134 testParameters.size = sizesCube[sizeNdx].size;
1136 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1138 sizesGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1143 // Filter/wrap mode combinations.
1144 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1146 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1148 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1150 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1152 const string name = string(minFilterModes[minFilterNdx].name) + "_" + magFilterModes[magFilterNdx].name + "_" + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
1153 TextureCubeFilteringTestCaseParameters testParameters;
1155 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1156 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1157 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1158 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1159 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1160 testParameters.onlySampleFaceInterior = false;
1161 testParameters.size = 63;
1163 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1165 combinationsGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1171 // Cases with no visible cube edges.
1172 for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
1174 const bool isLinear = isLinearI != 0;
1175 const string name = isLinear ? "linear" : "nearest";
1176 TextureCubeFilteringTestCaseParameters testParameters;
1178 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1179 testParameters.minFilter = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1180 testParameters.magFilter = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1181 testParameters.wrapS = Sampler::REPEAT_GL;
1182 testParameters.wrapT = Sampler::REPEAT_GL;
1183 testParameters.onlySampleFaceInterior = true;
1184 testParameters.size = 63;
1186 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1188 onlyFaceInteriorGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1191 groupCube->addChild(formatsGroup.release());
1192 groupCube->addChild(sizesGroup.release());
1193 groupCube->addChild(combinationsGroup.release());
1194 groupCube->addChild(onlyFaceInteriorGroup.release());
1196 textureFilteringTests->addChild(groupCube.release());
1199 // 2D array texture filtering.
1201 de::MovePtr<tcu::TestCaseGroup> group2DArray (new tcu::TestCaseGroup(testCtx, "2d_array", "2D Array Texture Filtering"));
1203 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "2D Array Texture Formats"));
1204 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1205 de::MovePtr<tcu::TestCaseGroup> combinationsGroup (new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1208 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1210 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1212 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1213 const char* const filterName = minFilterModes[filterNdx].name;
1214 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1215 const char* const formatName = filterableFormatsByType[fmtNdx].name;
1216 const string name = string(formatName) + "_" + filterName;
1217 Texture2DArrayTestCaseParameters testParameters;
1219 testParameters.format = filterableFormatsByType[fmtNdx].format;
1220 testParameters.minFilter = minFilter;
1221 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1223 testParameters.wrapS = Sampler::REPEAT_GL;
1224 testParameters.wrapT = Sampler::REPEAT_GL;
1225 testParameters.width = 128;
1226 testParameters.height = 128;
1227 testParameters.numLayers = 8;
1229 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1230 testParameters.programs.push_back(PROGRAM_2D_ARRAY_UINT);
1232 // Some tests have to be skipped due to the restrictions of the verifiers.
1233 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1235 formatsGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1241 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2DArray); sizeNdx++)
1243 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1245 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1246 const char* const filterName = minFilterModes[filterNdx].name;
1247 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1248 const string name = de::toString(sizes2DArray[sizeNdx].width) + "x" + de::toString(sizes2DArray[sizeNdx].height) + "x" + de::toString(sizes2DArray[sizeNdx].numLayers) + "_" + filterName;
1249 Texture2DArrayTestCaseParameters testParameters;
1251 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1252 testParameters.minFilter = minFilter;
1253 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1254 testParameters.wrapS = Sampler::REPEAT_GL;
1255 testParameters.wrapT = Sampler::REPEAT_GL;
1256 testParameters.width = sizes2DArray[sizeNdx].width;
1257 testParameters.height = sizes2DArray[sizeNdx].height;
1258 testParameters.numLayers = sizes2DArray[sizeNdx].numLayers;
1260 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1262 sizesGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1267 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1269 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1271 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1273 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1275 const string name = string(minFilterModes[minFilterNdx].name) + "_" + magFilterModes[magFilterNdx].name + "_" + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
1276 Texture2DArrayTestCaseParameters testParameters;
1278 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1279 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1280 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1281 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1282 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1283 testParameters.width = 123;
1284 testParameters.height = 107;
1285 testParameters.numLayers = 7;
1287 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1289 combinationsGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1295 group2DArray->addChild(formatsGroup.release());
1296 group2DArray->addChild(sizesGroup.release());
1297 group2DArray->addChild(combinationsGroup.release());
1299 textureFilteringTests->addChild(group2DArray.release());
1302 // 3D texture filtering.
1304 de::MovePtr<tcu::TestCaseGroup> group3D (new tcu::TestCaseGroup(testCtx, "3d", "3D Texture Filtering"));
1306 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "3D Texture Formats"));
1307 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1308 de::MovePtr<tcu::TestCaseGroup> combinationsGroup (new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1311 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1313 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1315 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1316 const char* const filterName = minFilterModes[filterNdx].name;
1317 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1318 const char* const formatName = filterableFormatsByType[fmtNdx].name;
1319 const string name = string(formatName) + "_" + filterName;
1320 Texture3DTestCaseParameters testParameters;
1322 testParameters.format = filterableFormatsByType[fmtNdx].format;
1323 testParameters.minFilter = minFilter;
1324 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1326 testParameters.wrapS = Sampler::REPEAT_GL;
1327 testParameters.wrapT = Sampler::REPEAT_GL;
1328 testParameters.wrapR = Sampler::REPEAT_GL;
1329 testParameters.width = 64;
1330 testParameters.height = 64;
1331 testParameters.depth = 64;
1333 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1334 testParameters.programs.push_back(PROGRAM_3D_UINT);
1336 // Some tests have to be skipped due to the restrictions of the verifiers.
1337 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1339 formatsGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1345 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes3D); sizeNdx++)
1347 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1349 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1350 const char* const filterName = minFilterModes[filterNdx].name;
1351 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1352 const string name = de::toString(sizes3D[sizeNdx].width) + "x" + de::toString(sizes3D[sizeNdx].height) + "x" + de::toString(sizes3D[sizeNdx].depth) + "_" + filterName;
1353 Texture3DTestCaseParameters testParameters;
1355 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1356 testParameters.minFilter = minFilter;
1357 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1358 testParameters.wrapS = Sampler::REPEAT_GL;
1359 testParameters.wrapT = Sampler::REPEAT_GL;
1360 testParameters.wrapR = Sampler::REPEAT_GL;
1361 testParameters.width = sizes3D[sizeNdx].width;
1362 testParameters.height = sizes3D[sizeNdx].height;
1363 testParameters.depth = sizes3D[sizeNdx].depth;
1365 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1367 sizesGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1372 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1374 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1376 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1378 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1380 for (int wrapRNdx = 0; wrapRNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapRNdx++)
1382 const string name = string(minFilterModes[minFilterNdx].name) + "_" + magFilterModes[magFilterNdx].name + "_" + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name + "_" + wrapModes[wrapRNdx].name;
1383 Texture3DTestCaseParameters testParameters;
1385 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1386 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1387 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1388 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1389 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1390 testParameters.wrapR = wrapModes[wrapRNdx].mode;
1391 testParameters.width = 63;
1392 testParameters.height = 57;
1393 testParameters.depth = 67;
1395 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1397 combinationsGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1404 group3D->addChild(formatsGroup.release());
1405 group3D->addChild(sizesGroup.release());
1406 group3D->addChild(combinationsGroup.release());
1408 textureFilteringTests->addChild(group3D.release());
1414 tcu::TestCaseGroup* createTextureFilteringTests (tcu::TestContext& testCtx)
1416 return createTestGroup(testCtx, "filtering", "Texture filtering tests.", populateTextureFilteringTests);