1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
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
8 *
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
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
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.
20 *
21 *//*!
22 * \file
23 * \brief Texture filtering tests.
24 *//*--------------------------------------------------------------------*/
25
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"
38 #include <string>
39 #include <vector>
40
41 using namespace vk;
42
43 namespace vkt
44 {
45 namespace texture
46 {
47
48 namespace
49 {
50
51 using std::vector;
52 using std::string;
53 using tcu::TestLog;
54 using tcu::Sampler;
55
56 using namespace texture::util;
57 using namespace glu::TextureTestUtil;
58
59 enum
60 {
61 TEXCUBE_VIEWPORT_SIZE = 28,
62
63 TEX2D_VIEWPORT_WIDTH = 64,
64 TEX2D_VIEWPORT_HEIGHT = 64,
65
66 TEX3D_VIEWPORT_WIDTH = 64,
67 TEX3D_VIEWPORT_HEIGHT = 64,
68 };
69
70 class Texture2DFilteringTestInstance : public TestInstance
71 {
72 public:
73 typedef Texture2DTestCaseParameters ParameterType;
74
75 Texture2DFilteringTestInstance (Context& context, const ParameterType& testParameters);
76 ~Texture2DFilteringTestInstance (void);
77
78 virtual tcu::TestStatus iterate (void);
79 private:
80 Texture2DFilteringTestInstance (const Texture2DFilteringTestInstance& other);
81 Texture2DFilteringTestInstance& operator= (const Texture2DFilteringTestInstance& other);
82
83 struct FilterCase
84 {
85 int textureIndex;
86
87 tcu::Vec2 minCoord;
88 tcu::Vec2 maxCoord;
89
FilterCasevkt::texture::__anon640f863c0111::Texture2DFilteringTestInstance::FilterCase90 FilterCase (void)
91 : textureIndex(-1)
92 {
93 }
94
FilterCasevkt::texture::__anon640f863c0111::Texture2DFilteringTestInstance::FilterCase95 FilterCase (int tex_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
96 : textureIndex (tex_)
97 , minCoord (minCoord_)
98 , maxCoord (maxCoord_)
99 {
100 }
101 };
102
103 const ParameterType m_testParameters;
104 vector<TestTexture2DSp> m_textures;
105 vector<FilterCase> m_cases;
106 TextureRenderer m_renderer;
107 int m_caseNdx;
108 };
109
Texture2DFilteringTestInstance(Context & context,const ParameterType & testParameters)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)
114 , m_caseNdx (0)
115 {
116 const bool mipmaps = m_testParameters.mipmaps;
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;
121
122 if ((testParameters.wrapS == Sampler::MIRRORED_ONCE ||
123 testParameters.wrapT == Sampler::MIRRORED_ONCE) &&
124 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_sampler_mirror_clamp_to_edge"))
125 TCU_THROW(NotSupportedError, "VK_KHR_sampler_mirror_clamp_to_edge not supported");
126
127 // Create 2 textures.
128 m_textures.reserve(2);
129 for (int ndx = 0; ndx < 2; ndx++)
130 if (mipmaps)
131 m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
132 else
133 m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, 1)));
134
135 // Fill first gradient texture.
136 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
137 {
138 const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
139 const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
140
141 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
142 }
143
144 // Fill second with grid texture.
145 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
146 {
147 const deUint32 step = 0x00ffffff / numLevels;
148 const deUint32 rgb = step*levelNdx;
149 const deUint32 colorA = 0xff000000 | rgb;
150 const deUint32 colorB = 0xff000000 | ~rgb;
151
152 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
153 }
154
155 // Upload.
156 for (vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
157 {
158 m_renderer.add2DTexture(*i);
159 }
160
161 // Compute cases.
162 {
163 const struct
164 {
165 const int texNdx;
166 const float lodX;
167 const float lodY;
168 const float oX;
169 const float oY;
170 } cases[] =
171 {
172 { 0, 1.6f, 2.9f, -1.0f, -2.7f },
173 { 0, -2.0f, -1.35f, -0.2f, 0.7f },
174 { 1, 0.14f, 0.275f, -1.5f, -1.1f },
175 { 1, -0.92f, -2.64f, 0.4f, -0.1f },
176 };
177
178 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
179 {
180 const int texNdx = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
181 const float lodX = cases[caseNdx].lodX;
182 const float lodY = cases[caseNdx].lodY;
183 const float oX = cases[caseNdx].oX;
184 const float oY = cases[caseNdx].oY;
185 const float sX = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
186 const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[texNdx]->getTexture().getHeight());
187
188 m_cases.push_back(FilterCase(texNdx, tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY)));
189 }
190 }
191 }
192
~Texture2DFilteringTestInstance(void)193 Texture2DFilteringTestInstance::~Texture2DFilteringTestInstance (void)
194 {
195 }
196
iterate(void)197 tcu::TestStatus Texture2DFilteringTestInstance::iterate (void)
198 {
199 tcu::TestLog& log = m_context.getTestContext().getLog();
200
201 const pipeline::TestTexture2D& texture = m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
202 const tcu::TextureFormat texFmt = texture.getTextureFormat();
203 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
204 const FilterCase& curCase = m_cases[m_caseNdx];
205 ReferenceParams refParams (TEXTURETYPE_2D);
206 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
207 vector<float> texCoord;
208
209 // Setup params for reference.
210
211 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter, !m_testParameters.unnormal);
212 refParams.samplerType = getSamplerType(texFmt);
213 refParams.lodMode = LODMODE_EXACT;
214 refParams.colorBias = fmtInfo.lookupBias;
215 refParams.colorScale = fmtInfo.lookupScale;
216 refParams.unnormal = m_testParameters.unnormal;
217
218 // Compute texture coordinates.
219 log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
220 computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
221
222 m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
223
224 {
225 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
226 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
227 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
228 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
229 tcu::LodPrecision lodPrecision;
230 tcu::LookupPrecision lookupPrecision;
231
232 lodPrecision.derivateBits = 18;
233 lodPrecision.lodBits = 6;
234 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
235 lookupPrecision.coordBits = tcu::IVec3(20,20,0);
236 lookupPrecision.uvwBits = tcu::IVec3(7,7,0);
237 lookupPrecision.colorMask = getCompareMask(pixelFormat);
238
239 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DView)texture.getTexture(),
240 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
241
242 if (!isHighQuality)
243 {
244 // Evaluate against lower precision requirements.
245 lodPrecision.lodBits = 4;
246 lookupPrecision.uvwBits = tcu::IVec3(4,4,0);
247
248 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
249
250 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DView)texture.getTexture(),
251 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
252
253 if (!isOk)
254 {
255 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
256 return tcu::TestStatus::fail("Image verification failed");
257 }
258 }
259 }
260
261 m_caseNdx += 1;
262 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
263 }
264
265 struct TextureCubeFilteringTestCaseParameters : public TextureCubeTestCaseParameters
266 {
267 bool onlySampleFaceInterior;
268 };
269
270 class TextureCubeFilteringTestInstance : public TestInstance
271 {
272 public:
273 typedef TextureCubeFilteringTestCaseParameters ParameterType;
274
275 TextureCubeFilteringTestInstance (Context& context, const ParameterType& testParameters);
276 ~TextureCubeFilteringTestInstance (void);
277
278 virtual tcu::TestStatus iterate (void);
279
280 private:
281 TextureCubeFilteringTestInstance (const TextureCubeFilteringTestInstance& other);
282 TextureCubeFilteringTestInstance& operator= (const TextureCubeFilteringTestInstance& other);
283
284 struct FilterCase
285 {
286 int textureIndex;
287 tcu::Vec2 bottomLeft;
288 tcu::Vec2 topRight;
289
FilterCasevkt::texture::__anon640f863c0111::TextureCubeFilteringTestInstance::FilterCase290 FilterCase (void)
291 : textureIndex(-1)
292 {
293 }
294
FilterCasevkt::texture::__anon640f863c0111::TextureCubeFilteringTestInstance::FilterCase295 FilterCase (int tex_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
296 : textureIndex (tex_)
297 , bottomLeft (bottomLeft_)
298 , topRight (topRight_)
299 {
300 }
301 };
302
303 const ParameterType m_testParameters;
304 vector<TestTextureCubeSp> m_textures;
305 vector<FilterCase> m_cases;
306 TextureRenderer m_renderer;
307 int m_caseNdx;
308 };
309
TextureCubeFilteringTestInstance(Context & context,const ParameterType & testParameters)310 TextureCubeFilteringTestInstance::TextureCubeFilteringTestInstance (Context& context, const ParameterType& testParameters)
311 : TestInstance (context)
312 , m_testParameters (testParameters)
313 , m_renderer (context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
314 , m_caseNdx (0)
315 {
316 const int numLevels = deLog2Floor32(m_testParameters.size)+1;
317 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
318 const tcu::Vec4 cBias = fmtInfo.valueMin;
319 const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
320
321 if ((testParameters.wrapS == Sampler::MIRRORED_ONCE ||
322 testParameters.wrapT == Sampler::MIRRORED_ONCE) &&
323 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_sampler_mirror_clamp_to_edge"))
324 TCU_THROW(NotSupportedError, "VK_KHR_sampler_mirror_clamp_to_edge not supported");
325
326 m_textures.reserve(2);
327 for (int ndx = 0; ndx < 2; ndx++)
328 m_textures.push_back(TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
329
330 // Fill first with gradient texture.
331 static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
332 {
333 { tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
334 { tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
335 { tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
336 { tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
337 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
338 { tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z
339 };
340
341 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
342 {
343 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
344 {
345 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
346 }
347 }
348
349 // Fill second with grid texture.
350 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
351 {
352 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
353 {
354 const deUint32 step = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
355 const deUint32 rgb = step*levelNdx*face;
356 const deUint32 colorA = 0xff000000 | rgb;
357 const deUint32 colorB = 0xff000000 | ~rgb;
358
359 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
360 }
361 }
362
363 // Upload.
364 for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
365 {
366 m_renderer.addCubeTexture(*i);
367 }
368
369 // Compute cases
370 {
371 const int tex0 = 0;
372 const int tex1 = m_textures.size() > 1 ? 1 : 0;
373
374 if (m_testParameters.onlySampleFaceInterior)
375 {
376 m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
377 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f))); // magnification
378 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
379 m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f), tcu::Vec2(0.6f, 0.5f))); // magnification
380 }
381 else
382 {
383 m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f))); // minification
384
385 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.8f, 0.8f), tcu::Vec2(1.25f, 1.20f))); // magnification
386 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f))); // minification
387 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.2f, -1.1f), tcu::Vec2(-0.8f, -0.8f))); // magnification
388 }
389 }
390 }
391
~TextureCubeFilteringTestInstance(void)392 TextureCubeFilteringTestInstance::~TextureCubeFilteringTestInstance (void)
393 {
394 }
395
getFaceDesc(const tcu::CubeFace face)396 const char* getFaceDesc (const tcu::CubeFace face)
397 {
398 switch (face)
399 {
400 case tcu::CUBEFACE_NEGATIVE_X: return "-X";
401 case tcu::CUBEFACE_POSITIVE_X: return "+X";
402 case tcu::CUBEFACE_NEGATIVE_Y: return "-Y";
403 case tcu::CUBEFACE_POSITIVE_Y: return "+Y";
404 case tcu::CUBEFACE_NEGATIVE_Z: return "-Z";
405 case tcu::CUBEFACE_POSITIVE_Z: return "+Z";
406 default:
407 DE_ASSERT(false);
408 return DE_NULL;
409 }
410 }
411
iterate(void)412 tcu::TestStatus TextureCubeFilteringTestInstance::iterate (void)
413 {
414 tcu::TestLog& log = m_context.getTestContext().getLog();
415
416 const pipeline::TestTextureCube& texture = m_renderer.getCubeTexture(m_cases[m_caseNdx].textureIndex);
417 const tcu::TextureFormat texFmt = texture.getTextureFormat();
418 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
419 const FilterCase& curCase = m_cases[m_caseNdx];
420 ReferenceParams refParams (TEXTURETYPE_CUBE);
421
422 // Params for reference computation.
423 refParams.sampler = util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
424 refParams.sampler.seamlessCubeMap = true;
425 refParams.samplerType = getSamplerType(texFmt);
426 refParams.lodMode = LODMODE_EXACT;
427 refParams.colorBias = fmtInfo.lookupBias;
428 refParams.colorScale = fmtInfo.lookupScale;
429
430 log << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight << TestLog::EndMessage;
431
432 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
433 {
434 const tcu::CubeFace face = tcu::CubeFace(faceNdx);
435 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
436 vector<float> texCoord;
437
438 computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
439
440 log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
441
442 // \todo Log texture coordinates.
443
444 m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
445
446 {
447 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
448 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
449 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
450 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
451 tcu::LodPrecision lodPrecision;
452 tcu::LookupPrecision lookupPrecision;
453
454 lodPrecision.derivateBits = 10;
455 lodPrecision.lodBits = 5;
456 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
457 lookupPrecision.coordBits = tcu::IVec3(10,10,10);
458 lookupPrecision.uvwBits = tcu::IVec3(6,6,0);
459 lookupPrecision.colorMask = getCompareMask(pixelFormat);
460
461 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::TextureCubeView)texture.getTexture(),
462 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
463
464 if (!isHighQuality)
465 {
466 // Evaluate against lower precision requirements.
467 lodPrecision.lodBits = 4;
468 lookupPrecision.uvwBits = tcu::IVec3(4,4,0);
469
470 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
471
472 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::TextureCubeView)texture.getTexture(),
473 &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
474
475 if (!isOk)
476 {
477 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
478 return tcu::TestStatus::fail("Image verification failed");
479 }
480 }
481 }
482 }
483
484 m_caseNdx += 1;
485 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
486 }
487
488 // 2D array filtering
489
490 class Texture2DArrayFilteringTestInstance : public TestInstance
491 {
492 public:
493 typedef Texture2DArrayTestCaseParameters ParameterType;
494
495 Texture2DArrayFilteringTestInstance (Context& context, const ParameterType& testParameters);
496 ~Texture2DArrayFilteringTestInstance (void);
497
498 virtual tcu::TestStatus iterate (void);
499
500 private:
501 Texture2DArrayFilteringTestInstance (const Texture2DArrayFilteringTestInstance&);
502 Texture2DArrayFilteringTestInstance& operator= (const Texture2DArrayFilteringTestInstance&);
503
504 struct FilterCase
505 {
506 int textureIndex;
507 tcu::Vec2 lod;
508 tcu::Vec2 offset;
509 tcu::Vec2 layerRange;
510
FilterCasevkt::texture::__anon640f863c0111::Texture2DArrayFilteringTestInstance::FilterCase511 FilterCase (void)
512 : textureIndex(-1)
513 {
514 }
515
FilterCasevkt::texture::__anon640f863c0111::Texture2DArrayFilteringTestInstance::FilterCase516 FilterCase (const int tex_, const tcu::Vec2& lod_, const tcu::Vec2& offset_, const tcu::Vec2& layerRange_)
517 : textureIndex (tex_)
518 , lod (lod_)
519 , offset (offset_)
520 , layerRange (layerRange_)
521 {
522 }
523 };
524
525 const ParameterType m_testParameters;
526 vector<TestTexture2DArraySp> m_textures;
527 vector<FilterCase> m_cases;
528 TextureRenderer m_renderer;
529 int m_caseNdx;
530 };
531
Texture2DArrayFilteringTestInstance(Context & context,const ParameterType & testParameters)532 Texture2DArrayFilteringTestInstance::Texture2DArrayFilteringTestInstance (Context& context, const ParameterType& testParameters)
533 : TestInstance (context)
534 , m_testParameters (testParameters)
535 , m_renderer (context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
536 , m_caseNdx (0)
537 {
538 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
539 const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
540 const tcu::Vec4 cBias = fmtInfo.valueMin;
541 const int numLevels = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1;
542
543 if ((testParameters.wrapS == Sampler::MIRRORED_ONCE ||
544 testParameters.wrapT == Sampler::MIRRORED_ONCE) &&
545 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_sampler_mirror_clamp_to_edge"))
546 TCU_THROW(NotSupportedError, "VK_KHR_sampler_mirror_clamp_to_edge not supported");
547
548 // Create textures.
549 m_textures.reserve(2);
550 for (int ndx = 0; ndx < 2; ndx++)
551 m_textures.push_back(TestTexture2DArraySp(new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.numLayers)));
552
553 const tcu::IVec4 levelSwz[] =
554 {
555 tcu::IVec4(0,1,2,3),
556 tcu::IVec4(2,1,3,0),
557 tcu::IVec4(3,0,1,2),
558 tcu::IVec4(1,3,2,0),
559 };
560
561 // Fill first gradient texture (gradient direction varies between layers).
562 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
563 {
564 for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
565 {
566 const tcu::PixelBufferAccess levelBuf = m_textures[0]->getLevel(levelNdx, layerNdx);
567
568 const tcu::IVec4 swz = levelSwz[layerNdx%DE_LENGTH_OF_ARRAY(levelSwz)];
569 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;
570 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;
571
572 tcu::fillWithComponentGradients(levelBuf, gMin, gMax);
573 }
574 }
575
576 // Fill second with grid texture (each layer has unique colors).
577 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
578 {
579 for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
580 {
581 const tcu::PixelBufferAccess levelBuf = m_textures[1]->getLevel(levelNdx, layerNdx);
582
583 const deUint32 step = 0x00ffffff / (numLevels*m_testParameters.numLayers - 1);
584 const deUint32 rgb = step * (levelNdx + layerNdx*numLevels);
585 const deUint32 colorA = 0xff000000 | rgb;
586 const deUint32 colorB = 0xff000000 | ~rgb;
587
588 tcu::fillWithGrid(levelBuf, 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
589 }
590 }
591
592 // Upload.
593 for (vector<TestTexture2DArraySp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
594 {
595 m_renderer.add2DArrayTexture(*i);
596 }
597
598 // Test cases
599 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)));
600 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)));
601 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)));
602 m_cases.push_back(FilterCase(0, tcu::Vec2(-2.0f, -1.5f ), tcu::Vec2(-0.1f, 0.9f), tcu::Vec2(1.50001f, 1.49999f)));
603 }
604
~Texture2DArrayFilteringTestInstance(void)605 Texture2DArrayFilteringTestInstance::~Texture2DArrayFilteringTestInstance (void)
606 {
607 }
608
iterate(void)609 tcu::TestStatus Texture2DArrayFilteringTestInstance::iterate (void)
610 {
611 tcu::TestLog& log = m_context.getTestContext().getLog();
612
613 const FilterCase& curCase = m_cases[m_caseNdx];
614 const pipeline::TestTexture2DArray& texture = m_renderer.get2DArrayTexture(curCase.textureIndex);
615 const tcu::TextureFormat texFmt = texture.getTextureFormat();
616 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
617 ReferenceParams refParams (TEXTURETYPE_2D_ARRAY);
618 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
619 tcu::Vec3 texCoord[4];
620 const float* const texCoordPtr = (const float*)&texCoord[0];
621
622 // Params for reference computation.
623
624 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
625 refParams.samplerType = getSamplerType(texFmt);
626 refParams.lodMode = LODMODE_EXACT;
627 refParams.colorBias = fmtInfo.lookupBias;
628 refParams.colorScale = fmtInfo.lookupScale;
629
630 // Compute texture coordinates.
631 log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset << TestLog::EndMessage;
632
633 {
634 const float lodX = curCase.lod.x();
635 const float lodY = curCase.lod.y();
636 const float oX = curCase.offset.x();
637 const float oY = curCase.offset.y();
638 const float sX = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
639 const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
640 const float l0 = curCase.layerRange.x();
641 const float l1 = curCase.layerRange.y();
642
643 texCoord[0] = tcu::Vec3(oX, oY, l0);
644 texCoord[1] = tcu::Vec3(oX, oY+sY, l0*0.5f + l1*0.5f);
645 texCoord[2] = tcu::Vec3(oX+sX, oY, l0*0.5f + l1*0.5f);
646 texCoord[3] = tcu::Vec3(oX+sX, oY+sY, l1);
647 }
648
649 m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
650
651 {
652
653 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
654 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
655 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
656 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
657 tcu::LodPrecision lodPrecision;
658 tcu::LookupPrecision lookupPrecision;
659
660 lodPrecision.derivateBits = 18;
661 lodPrecision.lodBits = 6;
662 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
663 lookupPrecision.coordBits = tcu::IVec3(20,20,20);
664 lookupPrecision.uvwBits = tcu::IVec3(7,7,0);
665 lookupPrecision.colorMask = getCompareMask(pixelFormat);
666
667 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DArrayView)texture.getTexture(),
668 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
669
670 if (!isHighQuality)
671 {
672 // Evaluate against lower precision requirements.
673 lodPrecision.lodBits = 4;
674 lookupPrecision.uvwBits = tcu::IVec3(4,4,0);
675
676 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
677
678 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DArrayView)texture.getTexture(),
679 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
680
681 if (!isOk)
682 {
683 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
684 return tcu::TestStatus::fail("Image verification failed");
685 }
686 }
687 }
688
689 m_caseNdx += 1;
690 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
691 }
692
693 // 3D filtering
694
695 class Texture3DFilteringTestInstance : public TestInstance
696 {
697 public:
698 typedef Texture3DTestCaseParameters ParameterType;
699
700 Texture3DFilteringTestInstance (Context& context, const ParameterType& testParameters);
701 ~Texture3DFilteringTestInstance (void);
702
703 virtual tcu::TestStatus iterate (void);
704
705 private:
706 Texture3DFilteringTestInstance (const Texture3DFilteringTestInstance& other);
707 Texture3DFilteringTestInstance& operator= (const Texture3DFilteringTestInstance& other);
708
709 struct FilterCase
710 {
711 int textureIndex;
712 tcu::Vec3 lod;
713 tcu::Vec3 offset;
714
FilterCasevkt::texture::__anon640f863c0111::Texture3DFilteringTestInstance::FilterCase715 FilterCase (void)
716 : textureIndex(-1)
717 {
718 }
719
FilterCasevkt::texture::__anon640f863c0111::Texture3DFilteringTestInstance::FilterCase720 FilterCase (const int tex_, const tcu::Vec3& lod_, const tcu::Vec3& offset_)
721 : textureIndex (tex_)
722 , lod (lod_)
723 , offset (offset_)
724 {
725 }
726 };
727
728 const ParameterType m_testParameters;
729 vector<TestTexture3DSp> m_textures;
730 vector<FilterCase> m_cases;
731 TextureRenderer m_renderer;
732 int m_caseNdx;
733 };
734
Texture3DFilteringTestInstance(Context & context,const ParameterType & testParameters)735 Texture3DFilteringTestInstance::Texture3DFilteringTestInstance (Context& context, const ParameterType& testParameters)
736 : TestInstance (context)
737 , m_testParameters (testParameters)
738 , m_renderer (context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
739 , m_caseNdx (0)
740 {
741 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
742 const tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
743 const tcu::Vec4 cBias = fmtInfo.valueMin;
744 const int numLevels = deLog2Floor32(de::max(de::max(m_testParameters.width, m_testParameters.height), m_testParameters.depth)) + 1;
745
746 if ((testParameters.wrapS == Sampler::MIRRORED_ONCE ||
747 testParameters.wrapT == Sampler::MIRRORED_ONCE ||
748 testParameters.wrapR == Sampler::MIRRORED_ONCE) &&
749 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_sampler_mirror_clamp_to_edge"))
750 TCU_THROW(NotSupportedError, "VK_KHR_sampler_mirror_clamp_to_edge not supported");
751
752 // Create textures.
753 m_textures.reserve(2);
754 for (int ndx = 0; ndx < 2; ndx++)
755 m_textures.push_back(TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.depth)));
756
757 // Fill first gradient texture.
758 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
759 {
760 const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
761 const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
762
763 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
764 }
765
766 // Fill second with grid texture.
767 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
768 {
769 const deUint32 step = 0x00ffffff / numLevels;
770 const deUint32 rgb = step*levelNdx;
771 const deUint32 colorA = 0xff000000 | rgb;
772 const deUint32 colorB = 0xff000000 | ~rgb;
773
774 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
775 }
776
777 // Upload.
778 for (vector<TestTexture3DSp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
779 {
780 m_renderer.add3DTexture(*i);
781 }
782
783 // Test cases
784 m_cases.push_back(FilterCase(0, tcu::Vec3(1.5f, 2.8f, 1.0f), tcu::Vec3(-1.0f, -2.7f, -2.275f)));
785 m_cases.push_back(FilterCase(0, tcu::Vec3(-2.0f, -1.5f, -1.8f), tcu::Vec3(-0.1f, 0.9f, -0.25f)));
786 m_cases.push_back(FilterCase(1, tcu::Vec3(0.2f, 0.175f, 0.3f), tcu::Vec3(-2.0f, -3.7f, -1.825f)));
787 m_cases.push_back(FilterCase(1, tcu::Vec3(-0.8f, -2.3f, -2.5f), tcu::Vec3(0.2f, -0.1f, 1.325f)));
788 }
789
~Texture3DFilteringTestInstance(void)790 Texture3DFilteringTestInstance::~Texture3DFilteringTestInstance (void)
791 {
792 }
793
iterate(void)794 tcu::TestStatus Texture3DFilteringTestInstance::iterate (void)
795 {
796 tcu::TestLog& log = m_context.getTestContext().getLog();
797
798 const pipeline::TestTexture3D& texture = m_renderer.get3DTexture(m_cases[m_caseNdx].textureIndex);
799 const tcu::TextureFormat texFmt = texture.getTextureFormat();
800 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
801 const FilterCase& curCase = m_cases[m_caseNdx];
802 ReferenceParams refParams (TEXTURETYPE_3D);
803 tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
804 tcu::Vec3 texCoord[4];
805 const float* const texCoordPtr = (const float*)&texCoord[0];
806
807 // Params for reference computation.
808 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.wrapR, m_testParameters.minFilter, m_testParameters.magFilter);
809 refParams.samplerType = getSamplerType(texFmt);
810 refParams.lodMode = LODMODE_EXACT;
811 refParams.colorBias = fmtInfo.lookupBias;
812 refParams.colorScale = fmtInfo.lookupScale;
813
814 // Compute texture coordinates.
815 log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset << TestLog::EndMessage;
816
817 {
818 const float lodX = curCase.lod.x();
819 const float lodY = curCase.lod.y();
820 const float lodZ = curCase.lod.z();
821 const float oX = curCase.offset.x();
822 const float oY = curCase.offset.y();
823 const float oZ = curCase.offset.z();
824 const float sX = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
825 const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
826 const float sZ = deFloatExp2(lodZ) * float(de::max(m_renderer.getRenderWidth(), m_renderer.getRenderHeight())) / float(m_textures[0]->getTexture().getDepth());
827
828 texCoord[0] = tcu::Vec3(oX, oY, oZ);
829 texCoord[1] = tcu::Vec3(oX, oY+sY, oZ + sZ*0.5f);
830 texCoord[2] = tcu::Vec3(oX+sX, oY, oZ + sZ*0.5f);
831 texCoord[3] = tcu::Vec3(oX+sX, oY+sY, oZ + sZ);
832 }
833
834 m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
835
836 {
837 const bool isNearestOnly = m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
838 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
839 const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
840 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
841 tcu::LodPrecision lodPrecision;
842 tcu::LookupPrecision lookupPrecision;
843
844 lodPrecision.derivateBits = 18;
845 lodPrecision.lodBits = 6;
846 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
847 lookupPrecision.coordBits = tcu::IVec3(20,20,20);
848 lookupPrecision.uvwBits = tcu::IVec3(7,7,7);
849 lookupPrecision.colorMask = getCompareMask(pixelFormat);
850
851 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture3DView)texture.getTexture(),
852 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
853
854 if (!isHighQuality)
855 {
856 // Evaluate against lower precision requirements.
857 lodPrecision.lodBits = 4;
858 lookupPrecision.uvwBits = tcu::IVec3(4,4,4);
859
860 log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
861
862 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture3DView)texture.getTexture(),
863 texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
864
865 if (!isOk)
866 {
867 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
868 return tcu::TestStatus::fail("Image verification failed");
869 }
870 }
871 }
872
873 m_caseNdx += 1;
874 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
875 }
876
verifierCanBeUsed(const VkFormat format,const Sampler::FilterMode minFilter,const Sampler::FilterMode magFilter)877 bool verifierCanBeUsed (const VkFormat format, const Sampler::FilterMode minFilter, const Sampler::FilterMode magFilter)
878 {
879 const tcu::TextureFormat textureFormat = mapVkFormat(format);
880 const tcu::TextureChannelClass textureChannelClass = tcu::getTextureChannelClass(textureFormat.type);
881
882 return !(!(textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
883 textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
884 textureChannelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) &&
885 (tcu::TexVerifierUtil::isLinearFilter(minFilter) || tcu::TexVerifierUtil::isLinearFilter(magFilter)));
886 }
887
populateTextureFilteringTests(tcu::TestCaseGroup * textureFilteringTests)888 void populateTextureFilteringTests (tcu::TestCaseGroup* textureFilteringTests)
889 {
890 tcu::TestContext& testCtx = textureFilteringTests->getTestContext();
891
892 static const struct
893 {
894 const char* const name;
895 const Sampler::WrapMode mode;
896 } wrapModes[] =
897 {
898 { "repeat", Sampler::REPEAT_GL },
899 { "mirrored_repeat", Sampler::MIRRORED_REPEAT_GL },
900 { "clamp_to_edge", Sampler::CLAMP_TO_EDGE },
901 { "clamp_to_border", Sampler::CLAMP_TO_BORDER },
902 { "mirror_clamp_to_edge", Sampler::MIRRORED_ONCE }
903 };
904
905 static const struct
906 {
907 const char* const name;
908 const Sampler::FilterMode mode;
909 } minFilterModes[] =
910 {
911 { "nearest", Sampler::NEAREST },
912 { "linear", Sampler::LINEAR },
913 { "nearest_mipmap_nearest", Sampler::NEAREST_MIPMAP_NEAREST },
914 { "linear_mipmap_nearest", Sampler::LINEAR_MIPMAP_NEAREST },
915 { "nearest_mipmap_linear", Sampler::NEAREST_MIPMAP_LINEAR },
916 { "linear_mipmap_linear", Sampler::LINEAR_MIPMAP_LINEAR }
917 };
918
919 static const struct
920 {
921 const char* const name;
922 const Sampler::FilterMode mode;
923 } magFilterModes[] =
924 {
925 { "nearest", Sampler::NEAREST },
926 { "linear", Sampler::LINEAR }
927 };
928
929 static const struct
930 {
931 const int width;
932 const int height;
933 } sizes2D[] =
934 {
935 { 4, 8 },
936 { 32, 64 },
937 { 128, 128 },
938 { 3, 7 },
939 { 31, 55 },
940 { 127, 99 }
941 };
942
943 static const struct
944 {
945 const int size;
946 } sizesCube[] =
947 {
948 { 8 },
949 { 64 },
950 { 128 },
951 { 7 },
952 { 63 }
953 };
954
955 static const struct
956 {
957 const int width;
958 const int height;
959 const int numLayers;
960 } sizes2DArray[] =
961 {
962 { 4, 8, 8 },
963 { 32, 64, 16 },
964 { 128, 32, 64 },
965 { 3, 7, 5 },
966 { 63, 63, 63 }
967 };
968
969 static const struct
970 {
971 const int width;
972 const int height;
973 const int depth;
974 } sizes3D[] =
975 {
976 { 4, 8, 8 },
977 { 32, 64, 16 },
978 { 128, 32, 64 },
979 { 3, 7, 5 },
980 { 63, 63, 63 }
981 };
982
983 static const struct
984 {
985 const char* const name;
986 const VkFormat format;
987 } filterableFormatsByType[] =
988 {
989 { "r16g16b16a16_sfloat", VK_FORMAT_R16G16B16A16_SFLOAT },
990 { "b10g11r11_ufloat", VK_FORMAT_B10G11R11_UFLOAT_PACK32 },
991 { "e5b9g9r9_ufloat", VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 },
992 { "r8g8b8a8_unorm", VK_FORMAT_R8G8B8A8_UNORM },
993 { "r8g8b8a8_snorm", VK_FORMAT_R8G8B8A8_SNORM },
994 { "r5g6b5_unorm", VK_FORMAT_R5G6B5_UNORM_PACK16 },
995 { "r4g4b4a4_unorm", VK_FORMAT_R4G4B4A4_UNORM_PACK16 },
996 { "r5g5b5a1_unorm", VK_FORMAT_R5G5B5A1_UNORM_PACK16 },
997 { "a8b8g8r8_srgb", VK_FORMAT_A8B8G8R8_SRGB_PACK32 },
998 { "a1r5g5b5_unorm", VK_FORMAT_A1R5G5B5_UNORM_PACK16 }
999 };
1000
1001 // 2D texture filtering.
1002 {
1003 de::MovePtr<tcu::TestCaseGroup> group2D (new tcu::TestCaseGroup(testCtx, "2d", "2D Texture Filtering"));
1004
1005 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1006 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1007 de::MovePtr<tcu::TestCaseGroup> combinationsGroup (new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1008
1009 // Formats.
1010 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1011 {
1012 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1013 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1014
1015 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1016 {
1017 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1018 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1019 const string name = minFilterModes[filterNdx].name;
1020 Texture2DTestCaseParameters testParameters;
1021
1022 testParameters.format = filterableFormatsByType[fmtNdx].format;
1023 testParameters.minFilter = minFilter;
1024 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1025 testParameters.mipmaps = true;
1026
1027 testParameters.wrapS = Sampler::REPEAT_GL;
1028 testParameters.wrapT = Sampler::REPEAT_GL;
1029 testParameters.width = 64;
1030 testParameters.height = 64;
1031
1032 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1033 testParameters.programs.push_back(PROGRAM_2D_UINT);
1034
1035 // Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1036 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1037 {
1038 filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1039 }
1040 }
1041 formatsGroup->addChild(filterGroup.release());
1042 }
1043
1044 // Sizes.
1045 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1046 {
1047 const string filterGroupName = de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1048 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1049
1050 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1051 {
1052 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1053 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1054 const string name = minFilterModes[filterNdx].name;
1055 Texture2DTestCaseParameters testParameters;
1056
1057 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1058 testParameters.minFilter = minFilter;
1059 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1060 testParameters.mipmaps = true;
1061
1062 testParameters.wrapS = Sampler::REPEAT_GL;
1063 testParameters.wrapT = Sampler::REPEAT_GL;
1064 testParameters.width = sizes2D[sizeNdx].width;
1065 testParameters.height = sizes2D[sizeNdx].height;
1066
1067 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1068
1069 filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1070 }
1071 sizesGroup->addChild(filterGroup.release());
1072 }
1073
1074 // Wrap modes.
1075 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1076 {
1077 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1078
1079 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1080 {
1081 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1082
1083 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1084 {
1085 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1086
1087 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1088 {
1089 const string name = wrapModes[wrapTNdx].name;
1090 Texture2DTestCaseParameters testParameters;
1091
1092 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1093 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1094 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1095 testParameters.mipmaps = true;
1096
1097 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1098 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1099 testParameters.width = 63;
1100 testParameters.height = 57;
1101
1102 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1103
1104 wrapSGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1105 }
1106 magFilterGroup->addChild(wrapSGroup.release());
1107 }
1108 minFilterGroup->addChild(magFilterGroup.release());
1109 }
1110 combinationsGroup->addChild(minFilterGroup.release());
1111 }
1112
1113 group2D->addChild(formatsGroup.release());
1114 group2D->addChild(sizesGroup.release());
1115 group2D->addChild(combinationsGroup.release());
1116
1117 textureFilteringTests->addChild(group2D.release());
1118 }
1119
1120 // Unnormalized texture filtering.
1121 {
1122 de::MovePtr<tcu::TestCaseGroup> groupUnnormal (new tcu::TestCaseGroup(testCtx, "unnormal", "Unnormalized Texture Filtering"));
1123
1124 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1125 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1126
1127 // Formats.
1128 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1129 {
1130 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1131 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1132
1133 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); filterNdx++)
1134 {
1135 const Sampler::FilterMode magFilter = magFilterModes[filterNdx].mode;
1136 const string name = magFilterModes[filterNdx].name;
1137 Texture2DTestCaseParameters testParameters;
1138
1139 testParameters.unnormal = true;
1140
1141 testParameters.format = filterableFormatsByType[fmtNdx].format;
1142 testParameters.minFilter = magFilter;
1143 testParameters.magFilter = magFilter;
1144 testParameters.mipmaps = false;
1145
1146 testParameters.wrapS = ((fmtNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1147 testParameters.wrapT = ((fmtNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1148 testParameters.width = 64;
1149 testParameters.height = 64;
1150
1151 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1152 testParameters.programs.push_back(PROGRAM_2D_UINT);
1153
1154 // Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1155 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1156 {
1157 filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1158 }
1159 }
1160 formatsGroup->addChild(filterGroup.release());
1161 }
1162
1163 // Sizes.
1164 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1165 {
1166 const string filterGroupName = de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1167 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1168
1169 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); filterNdx++)
1170 {
1171 const Sampler::FilterMode magFilter = magFilterModes[filterNdx].mode;
1172 const string name = magFilterModes[filterNdx].name;
1173 Texture2DTestCaseParameters testParameters;
1174
1175 testParameters.unnormal = true;
1176 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1177 testParameters.minFilter = magFilter;
1178 testParameters.magFilter = magFilter;
1179 testParameters.mipmaps = false;
1180
1181 testParameters.wrapS = ((sizeNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1182 testParameters.wrapT = ((sizeNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1183 testParameters.width = sizes2D[sizeNdx].width;
1184 testParameters.height = sizes2D[sizeNdx].height;
1185
1186 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1187
1188 filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1189 }
1190 sizesGroup->addChild(filterGroup.release());
1191 }
1192
1193 groupUnnormal->addChild(formatsGroup.release());
1194 groupUnnormal->addChild(sizesGroup.release());
1195
1196 textureFilteringTests->addChild(groupUnnormal.release());
1197 }
1198
1199 // Cube map texture filtering.
1200 {
1201 de::MovePtr<tcu::TestCaseGroup> groupCube (new tcu::TestCaseGroup(testCtx, "cube", "Cube Map Texture Filtering"));
1202
1203 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "2D 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"));
1206 de::MovePtr<tcu::TestCaseGroup> onlyFaceInteriorGroup (new tcu::TestCaseGroup(testCtx, "no_edges_visible", "Don't sample anywhere near a face's edges"));
1207
1208 // Formats.
1209 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1210 {
1211 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1212 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1213
1214 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1215 {
1216 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1217 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1218 const string name = minFilterModes[filterNdx].name;
1219 TextureCubeFilteringTestCaseParameters testParameters;
1220
1221 testParameters.format = filterableFormatsByType[fmtNdx].format;
1222 testParameters.minFilter = minFilter;
1223 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1224
1225 testParameters.wrapS = Sampler::REPEAT_GL;
1226 testParameters.wrapT = Sampler::REPEAT_GL;
1227 testParameters.onlySampleFaceInterior = false;
1228 testParameters.size = 64;
1229
1230 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1231 testParameters.programs.push_back(PROGRAM_CUBE_UINT);
1232
1233 // Some tests have to be skipped due to the restrictions of the verifiers.
1234 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1235 {
1236 filterGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1237 }
1238 }
1239 formatsGroup->addChild(filterGroup.release());
1240 }
1241
1242 // Sizes.
1243 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
1244 {
1245 const string filterGroupName = de::toString(sizesCube[sizeNdx].size) + "x" + de::toString(sizesCube[sizeNdx].size);
1246 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1247
1248 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1249 {
1250 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1251 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1252 const string name = minFilterModes[filterNdx].name;
1253 TextureCubeFilteringTestCaseParameters testParameters;
1254
1255 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1256 testParameters.minFilter = minFilter;
1257 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1258 testParameters.wrapS = Sampler::REPEAT_GL;
1259 testParameters.wrapT = Sampler::REPEAT_GL;
1260 testParameters.onlySampleFaceInterior = false;
1261 testParameters.size = sizesCube[sizeNdx].size;
1262
1263 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1264
1265 filterGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1266
1267 }
1268 sizesGroup->addChild(filterGroup.release());
1269 }
1270
1271 // Filter/wrap mode combinations.
1272 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1273 {
1274 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1275
1276 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1277 {
1278 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1279
1280 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1281 {
1282 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1283
1284 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1285 {
1286 const string name = wrapModes[wrapTNdx].name;
1287 TextureCubeFilteringTestCaseParameters testParameters;
1288
1289 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1290 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1291 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1292 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1293 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1294 testParameters.onlySampleFaceInterior = false;
1295 testParameters.size = 63;
1296
1297 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1298
1299 wrapSGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1300 }
1301 magFilterGroup->addChild(wrapSGroup.release());
1302 }
1303 minFilterGroup->addChild(magFilterGroup.release());
1304 }
1305 combinationsGroup->addChild(minFilterGroup.release());
1306 }
1307
1308 // Cases with no visible cube edges.
1309 for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
1310 {
1311 const bool isLinear = isLinearI != 0;
1312 const string name = isLinear ? "linear" : "nearest";
1313 TextureCubeFilteringTestCaseParameters testParameters;
1314
1315 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1316 testParameters.minFilter = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1317 testParameters.magFilter = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1318 testParameters.wrapS = Sampler::REPEAT_GL;
1319 testParameters.wrapT = Sampler::REPEAT_GL;
1320 testParameters.onlySampleFaceInterior = true;
1321 testParameters.size = 63;
1322
1323 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1324
1325 onlyFaceInteriorGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1326 }
1327
1328 groupCube->addChild(formatsGroup.release());
1329 groupCube->addChild(sizesGroup.release());
1330 groupCube->addChild(combinationsGroup.release());
1331 groupCube->addChild(onlyFaceInteriorGroup.release());
1332
1333 textureFilteringTests->addChild(groupCube.release());
1334 }
1335
1336 // 2D array texture filtering.
1337 {
1338 de::MovePtr<tcu::TestCaseGroup> group2DArray (new tcu::TestCaseGroup(testCtx, "2d_array", "2D Array Texture Filtering"));
1339
1340 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "2D Array Texture Formats"));
1341 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1342 de::MovePtr<tcu::TestCaseGroup> combinationsGroup (new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1343
1344 // Formats.
1345 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1346 {
1347 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1348 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1349
1350 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1351 {
1352 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1353 const char* const filterName = minFilterModes[filterNdx].name;
1354 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1355 const char* const formatName = filterableFormatsByType[fmtNdx].name;
1356 const string name = string(formatName) + "_" + filterName;
1357 Texture2DArrayTestCaseParameters testParameters;
1358
1359 testParameters.format = filterableFormatsByType[fmtNdx].format;
1360 testParameters.minFilter = minFilter;
1361 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1362
1363 testParameters.wrapS = Sampler::REPEAT_GL;
1364 testParameters.wrapT = Sampler::REPEAT_GL;
1365 testParameters.width = 128;
1366 testParameters.height = 128;
1367 testParameters.numLayers = 8;
1368
1369 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1370 testParameters.programs.push_back(PROGRAM_2D_ARRAY_UINT);
1371
1372 // Some tests have to be skipped due to the restrictions of the verifiers.
1373 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1374 {
1375 filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1376 }
1377 }
1378 formatsGroup->addChild(filterGroup.release());
1379 }
1380
1381 // Sizes.
1382 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2DArray); sizeNdx++)
1383 {
1384 const string filterGroupName = de::toString(sizes2DArray[sizeNdx].width) + "x" + de::toString(sizes2DArray[sizeNdx].height) + "x" + de::toString(sizes2DArray[sizeNdx].numLayers);
1385 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1386
1387 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1388 {
1389 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1390 const char* const filterName = minFilterModes[filterNdx].name;
1391 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1392 const string name = filterName;
1393 Texture2DArrayTestCaseParameters testParameters;
1394
1395 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1396 testParameters.minFilter = minFilter;
1397 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1398 testParameters.wrapS = Sampler::REPEAT_GL;
1399 testParameters.wrapT = Sampler::REPEAT_GL;
1400 testParameters.width = sizes2DArray[sizeNdx].width;
1401 testParameters.height = sizes2DArray[sizeNdx].height;
1402 testParameters.numLayers = sizes2DArray[sizeNdx].numLayers;
1403
1404 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1405
1406 filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1407 }
1408 sizesGroup->addChild(filterGroup.release());
1409 }
1410
1411 // Wrap modes.
1412 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1413 {
1414 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1415
1416 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1417 {
1418 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1419
1420 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1421 {
1422 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1423
1424 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1425 {
1426 const string name = wrapModes[wrapTNdx].name;
1427 Texture2DArrayTestCaseParameters testParameters;
1428
1429 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1430 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1431 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1432 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1433 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1434 testParameters.width = 123;
1435 testParameters.height = 107;
1436 testParameters.numLayers = 7;
1437
1438 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1439
1440 wrapSGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1441 }
1442 magFilterGroup->addChild(wrapSGroup.release());
1443 }
1444 minFilterGroup->addChild(magFilterGroup.release());
1445 }
1446 combinationsGroup->addChild(minFilterGroup.release());
1447 }
1448
1449 group2DArray->addChild(formatsGroup.release());
1450 group2DArray->addChild(sizesGroup.release());
1451 group2DArray->addChild(combinationsGroup.release());
1452
1453 textureFilteringTests->addChild(group2DArray.release());
1454 }
1455
1456 // 3D texture filtering.
1457 {
1458 de::MovePtr<tcu::TestCaseGroup> group3D (new tcu::TestCaseGroup(testCtx, "3d", "3D Texture Filtering"));
1459
1460 de::MovePtr<tcu::TestCaseGroup> formatsGroup (new tcu::TestCaseGroup(testCtx, "formats", "3D Texture Formats"));
1461 de::MovePtr<tcu::TestCaseGroup> sizesGroup (new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1462 de::MovePtr<tcu::TestCaseGroup> combinationsGroup (new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1463
1464 // Formats.
1465 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1466 {
1467 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1468 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1469
1470 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1471 {
1472 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1473 const char* const filterName = minFilterModes[filterNdx].name;
1474 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1475 const char* const formatName = filterableFormatsByType[fmtNdx].name;
1476 const string name = string(formatName) + "_" + filterName;
1477 Texture3DTestCaseParameters testParameters;
1478
1479 testParameters.format = filterableFormatsByType[fmtNdx].format;
1480 testParameters.minFilter = minFilter;
1481 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1482
1483 testParameters.wrapS = Sampler::REPEAT_GL;
1484 testParameters.wrapT = Sampler::REPEAT_GL;
1485 testParameters.wrapR = Sampler::REPEAT_GL;
1486 testParameters.width = 64;
1487 testParameters.height = 64;
1488 testParameters.depth = 64;
1489
1490 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1491 testParameters.programs.push_back(PROGRAM_3D_UINT);
1492
1493 // Some tests have to be skipped due to the restrictions of the verifiers.
1494 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1495 {
1496 filterGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1497 }
1498 }
1499 formatsGroup->addChild(filterGroup.release());
1500 }
1501
1502 // Sizes.
1503 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes3D); sizeNdx++)
1504 {
1505 const string filterGroupName = de::toString(sizes3D[sizeNdx].width) + "x" + de::toString(sizes3D[sizeNdx].height) + "x" + de::toString(sizes3D[sizeNdx].depth);
1506 de::MovePtr<tcu::TestCaseGroup> filterGroup (new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1507
1508 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1509 {
1510 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1511 const char* const filterName = minFilterModes[filterNdx].name;
1512 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1513 const string name = filterName;
1514 Texture3DTestCaseParameters testParameters;
1515
1516 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1517 testParameters.minFilter = minFilter;
1518 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1519 testParameters.wrapS = Sampler::REPEAT_GL;
1520 testParameters.wrapT = Sampler::REPEAT_GL;
1521 testParameters.wrapR = Sampler::REPEAT_GL;
1522 testParameters.width = sizes3D[sizeNdx].width;
1523 testParameters.height = sizes3D[sizeNdx].height;
1524 testParameters.depth = sizes3D[sizeNdx].depth;
1525
1526 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1527
1528 filterGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1529 }
1530 sizesGroup->addChild(filterGroup.release());
1531 }
1532
1533 // Wrap modes.
1534 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1535 {
1536 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1537
1538 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1539 {
1540 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1541
1542 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1543 {
1544 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1545
1546 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1547 {
1548 de::MovePtr<tcu::TestCaseGroup> wrapTGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapTNdx].name, ""));
1549
1550 for (int wrapRNdx = 0; wrapRNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapRNdx++)
1551 {
1552 const string name = wrapModes[wrapRNdx].name;
1553 Texture3DTestCaseParameters testParameters;
1554
1555 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1556 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1557 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1558 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1559 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1560 testParameters.wrapR = wrapModes[wrapRNdx].mode;
1561 testParameters.width = 63;
1562 testParameters.height = 57;
1563 testParameters.depth = 67;
1564
1565 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1566
1567 wrapTGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1568 }
1569 wrapSGroup->addChild(wrapTGroup.release());
1570 }
1571 magFilterGroup->addChild(wrapSGroup.release());
1572 }
1573 minFilterGroup->addChild(magFilterGroup.release());
1574 }
1575 combinationsGroup->addChild(minFilterGroup.release());
1576 }
1577
1578 group3D->addChild(formatsGroup.release());
1579 group3D->addChild(sizesGroup.release());
1580 group3D->addChild(combinationsGroup.release());
1581
1582 textureFilteringTests->addChild(group3D.release());
1583 }
1584 }
1585
1586 } // anonymous
1587
createTextureFilteringTests(tcu::TestContext & testCtx)1588 tcu::TestCaseGroup* createTextureFilteringTests (tcu::TestContext& testCtx)
1589 {
1590 return createTestGroup(testCtx, "filtering", "Texture filtering tests.", populateTextureFilteringTests);
1591 }
1592
1593 } // texture
1594 } // vkt
1595