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 namespace util
48 {
49
50 template <>
checkTextureSupport(Context & context,const Texture2DTestCaseParameters & testParameters)51 void checkTextureSupport(Context &context, const Texture2DTestCaseParameters &testParameters)
52 {
53 if (testParameters.minFilter == tcu::Sampler::Sampler::CUBIC ||
54 testParameters.minFilter == tcu::Sampler::Sampler::CUBIC_MIPMAP_NEAREST ||
55 testParameters.minFilter == tcu::Sampler::Sampler::CUBIC_MIPMAP_LINEAR ||
56 testParameters.magFilter == tcu::Sampler::Sampler::CUBIC)
57 {
58 context.requireDeviceFunctionality("VK_EXT_filter_cubic");
59
60 // check if image format supports cubic filtering
61 const vk::VkPhysicalDeviceImageViewImageFormatInfoEXT imageViewImageFormatInfo = {
62 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT, // VkStructureType sType;
63 DE_NULL, // void* pNext;
64 VK_IMAGE_VIEW_TYPE_2D // VkImageViewType imageViewType;
65 };
66
67 const vk::VkPhysicalDeviceImageFormatInfo2 formatInfo = {
68 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType;
69 &imageViewImageFormatInfo, // const void* pNext;
70 testParameters.format, // VkFormat format;
71 VK_IMAGE_TYPE_2D, // VkImageType type;
72 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
73 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
74 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
75 0u // VkImageCreateFlags flags;
76 };
77
78 vk::VkFilterCubicImageViewImageFormatPropertiesEXT cubicImageViewProperties = {
79 VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT, // VkStructureType sType;
80 DE_NULL, // void* pNext;
81 false, // VkBool32 filterCubic;
82 false // VkBool32 filterCubicMinmax;
83 };
84
85 vk::VkImageFormatProperties2 formatProperties = {
86 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, // VkStructureType sType;
87 &cubicImageViewProperties, // void* pNext;
88 vk::VkImageFormatProperties() // VkImageFormatProperties imageFormatProperties;
89 };
90
91 const vk::VkResult res = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(
92 context.getPhysicalDevice(), &formatInfo, &formatProperties);
93 if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
94 TCU_THROW(NotSupportedError, "Image format not supported");
95 VK_CHECK(res);
96
97 if (!cubicImageViewProperties.filterCubic)
98 TCU_THROW(NotSupportedError, "Image format does not support cubic filtering");
99
100 VkFormatProperties formatProps;
101 context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(),
102 testParameters.format, &formatProps);
103 if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT) == 0)
104 TCU_THROW(NotSupportedError, "Format properties do not support cubic filtering feature");
105 }
106
107 if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
108 testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
109 context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
110
111 #ifndef CTS_USES_VULKANSC
112 if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 &&
113 context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
114 TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
115 #endif
116 }
117
118 template <>
checkTextureSupport(Context & context,const TextureCubeTestCaseParameters & testParameters)119 void checkTextureSupport(Context &context, const TextureCubeTestCaseParameters &testParameters)
120 {
121 if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
122 testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
123 context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
124 }
125
126 template <>
checkTextureSupport(Context & context,const Texture2DArrayTestCaseParameters & testParameters)127 void checkTextureSupport(Context &context, const Texture2DArrayTestCaseParameters &testParameters)
128 {
129 if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
130 testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
131 context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
132
133 #ifndef CTS_USES_VULKANSC
134 bool mipmaps =
135 (deLog2Floor32(de::max(testParameters.width, testParameters.height)) + 1) > 1 || testParameters.mipmaps;
136 if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 && mipmaps &&
137 context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
138 TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
139 #endif
140 }
141
142 template <>
checkTextureSupport(Context & context,const Texture3DTestCaseParameters & testParameters)143 void checkTextureSupport(Context &context, const Texture3DTestCaseParameters &testParameters)
144 {
145 if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
146 testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE ||
147 testParameters.wrapR == tcu::Sampler::Sampler::MIRRORED_ONCE)
148 context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
149
150 #ifndef CTS_USES_VULKANSC
151 if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 &&
152 context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
153 TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
154 #endif
155 }
156
157 template <>
checkTextureSupport(Context & context,const TextureCubeFilteringTestCaseParameters & testParameters)158 void checkTextureSupport(Context &context, const TextureCubeFilteringTestCaseParameters &testParameters)
159 {
160 #ifndef CTS_USES_VULKANSC
161 if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 &&
162 context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
163 TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
164 #else
165 DE_UNREF(context);
166 DE_UNREF(testParameters);
167 #endif
168 }
169
170 } // namespace util
171
172 namespace
173 {
174
175 using std::string;
176 using std::vector;
177 using tcu::Sampler;
178 using tcu::TestLog;
179
180 using namespace texture::util;
181 using namespace glu::TextureTestUtil;
182
183 enum
184 {
185 TEXCUBE_VIEWPORT_SIZE = 28,
186
187 TEX2D_VIEWPORT_WIDTH = 64,
188 TEX2D_VIEWPORT_HEIGHT = 64,
189
190 TEX3D_VIEWPORT_WIDTH = 64,
191 TEX3D_VIEWPORT_HEIGHT = 64,
192 };
193
194 class Texture2DFilteringTestInstance : public TestInstance
195 {
196 public:
197 typedef Texture2DTestCaseParameters ParameterType;
198
199 Texture2DFilteringTestInstance(Context &context, const ParameterType &testParameters);
200 ~Texture2DFilteringTestInstance(void);
201
202 virtual tcu::TestStatus iterate(void);
203
204 private:
205 Texture2DFilteringTestInstance(const Texture2DFilteringTestInstance &other);
206 Texture2DFilteringTestInstance &operator=(const Texture2DFilteringTestInstance &other);
207
208 struct FilterCase
209 {
210 int textureIndex;
211
212 tcu::Vec2 minCoord;
213 tcu::Vec2 maxCoord;
214
FilterCasevkt::texture::__anon12a368720111::Texture2DFilteringTestInstance::FilterCase215 FilterCase(void) : textureIndex(-1)
216 {
217 }
218
FilterCasevkt::texture::__anon12a368720111::Texture2DFilteringTestInstance::FilterCase219 FilterCase(int tex_, const tcu::Vec2 &minCoord_, const tcu::Vec2 &maxCoord_)
220 : textureIndex(tex_)
221 , minCoord(minCoord_)
222 , maxCoord(maxCoord_)
223 {
224 }
225 };
226
227 const ParameterType m_testParameters;
228 vector<TestTexture2DSp> m_textures;
229 vector<FilterCase> m_cases;
230 TextureRenderer m_renderer;
231 int m_caseNdx;
232 };
233
Texture2DFilteringTestInstance(Context & context,const ParameterType & testParameters)234 Texture2DFilteringTestInstance::Texture2DFilteringTestInstance(Context &context, const ParameterType &testParameters)
235 : TestInstance(context)
236 , m_testParameters(testParameters)
237 , m_renderer(context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
238 , m_caseNdx(0)
239 {
240 const bool mipmaps = m_testParameters.mipmaps;
241 const int numLevels = mipmaps ? deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1 : 1;
242 const tcu::TextureFormat texFormat = vk::mapVkFormat(m_testParameters.format);
243 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
244 tcu::Vec4 cBias, cScale;
245 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
246 {
247 const tcu::TextureFormat texFormatStencil = vk::mapVkFormat(VK_FORMAT_S8_UINT);
248 const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
249 cBias = fmtInfoStencil.valueMin;
250 cScale = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
251 }
252 else
253 {
254 cBias = fmtInfo.valueMin;
255 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
256 }
257
258 // Create 2 textures.
259 m_textures.reserve(2);
260 for (int ndx = 0; ndx < 2; ndx++)
261 if (mipmaps)
262 m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(
263 vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
264 else
265 m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(
266 vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, 1)));
267
268 // Fill first gradient texture.
269 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
270 {
271 const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
272 const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
273
274 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
275 tcu::fillWithComponentGradients(
276 getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), gMin,
277 gMax);
278 else
279 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
280 }
281
282 // Fill second with grid texture.
283 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
284 {
285 const uint32_t step = 0x00ffffff / numLevels;
286 const uint32_t rgb = step * levelNdx;
287 const uint32_t colorA = 0xff000000 | rgb;
288 const uint32_t colorB = 0xff000000 | ~rgb;
289
290 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
291 tcu::fillWithGrid(
292 getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), 4,
293 tcu::RGBA(colorA).toVec() * cScale + cBias, tcu::RGBA(colorB).toVec() * cScale + cBias);
294 else
295 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
296 tcu::RGBA(colorB).toVec() * cScale + cBias);
297 }
298
299 // Upload.
300 for (vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
301 {
302 m_renderer.add2DTexture(*i, testParameters.aspectMask);
303 }
304
305 // Compute cases.
306 {
307 const struct
308 {
309 const int texNdx;
310 const float lodX;
311 const float lodY;
312 const float oX;
313 const float oY;
314 } cases[] = {
315 {0, 1.6f, 2.9f, -1.0f, -2.7f},
316 {0, -2.0f, -1.35f, -0.2f, 0.7f},
317 {1, 0.14f, 0.275f, -1.5f, -1.1f},
318 {1, -0.92f, -2.64f, 0.4f, -0.1f},
319 };
320
321 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
322 {
323 const int texNdx = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size() - 1);
324 const float lodX = cases[caseNdx].lodX;
325 const float lodY = cases[caseNdx].lodY;
326 const float oX = cases[caseNdx].oX;
327 const float oY = cases[caseNdx].oY;
328 const float sX = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) /
329 float(m_textures[texNdx]->getTexture().getWidth());
330 const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) /
331 float(m_textures[texNdx]->getTexture().getHeight());
332
333 m_cases.push_back(FilterCase(texNdx, tcu::Vec2(oX, oY), tcu::Vec2(oX + sX, oY + sY)));
334 }
335 }
336 }
337
~Texture2DFilteringTestInstance(void)338 Texture2DFilteringTestInstance::~Texture2DFilteringTestInstance(void)
339 {
340 }
341
iterate(void)342 tcu::TestStatus Texture2DFilteringTestInstance::iterate(void)
343 {
344 tcu::TestLog &log = m_context.getTestContext().getLog();
345 const pipeline::TestTexture2D &texture = m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
346 const tcu::TextureFormat texFmt = texture.getTextureFormat();
347 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
348 const FilterCase &curCase = m_cases[m_caseNdx];
349 ReferenceParams refParams(TEXTURETYPE_2D);
350 tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
351 vector<float> texCoord;
352
353 // Setup params for reference.
354
355 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter,
356 m_testParameters.magFilter, !m_testParameters.unnormal);
357 if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
358 {
359 refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
360 refParams.samplerType = SAMPLERTYPE_UINT;
361 }
362 else
363 refParams.samplerType = getSamplerType(texFmt);
364 refParams.colorBias = fmtInfo.lookupBias;
365 refParams.colorScale = fmtInfo.lookupScale;
366 refParams.unnormal = m_testParameters.unnormal;
367
368 // Compute texture coordinates.
369 log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord
370 << TestLog::EndMessage;
371 computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
372
373 m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
374
375 {
376 const bool isNearestOnly =
377 m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
378 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
379 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
380 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
381 tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
382 tcu::LodPrecision lodPrecision;
383 tcu::LookupPrecision lookupPrecision;
384
385 lodPrecision.derivateBits = 18;
386 lodPrecision.lodBits = 6;
387 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
388 lookupPrecision.coordBits = tcu::IVec3(20, 20, 0);
389 lookupPrecision.uvwBits = tcu::IVec3(7, 7, 0);
390 lookupPrecision.colorMask = getCompareMask(pixelFormat);
391
392 #ifdef CTS_USES_VULKANSC
393 if (m_context.getTestContext().getCommandLine().isSubProcess())
394 #endif // CTS_USES_VULKANSC
395 {
396 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
397 (tcu::Texture2DView)texture.getTexture(), &texCoord[0],
398 refParams, lookupPrecision, lodPrecision, pixelFormat);
399
400 if (!isHighQuality)
401 {
402 // Evaluate against lower precision requirements.
403 lodPrecision.lodBits = 4;
404 lookupPrecision.uvwBits = tcu::IVec3(4, 4, 0);
405
406 log << TestLog::Message
407 << "Warning: Verification against high precision requirements failed, trying with lower "
408 "requirements."
409 << TestLog::EndMessage;
410
411 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
412 (tcu::Texture2DView)texture.getTexture(), &texCoord[0], refParams,
413 lookupPrecision, lodPrecision, pixelFormat);
414
415 if (!isOk)
416 {
417 log << TestLog::Message
418 << "ERROR: Verification against low precision requirements failed, failing test case."
419 << TestLog::EndMessage;
420 return tcu::TestStatus::fail("Image verification failed");
421 }
422 }
423 }
424 }
425
426 m_caseNdx += 1;
427 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
428 }
429
430 class TextureCubeFilteringTestInstance : public TestInstance
431 {
432 public:
433 typedef TextureCubeFilteringTestCaseParameters ParameterType;
434
435 TextureCubeFilteringTestInstance(Context &context, const ParameterType &testParameters);
436 ~TextureCubeFilteringTestInstance(void);
437
438 virtual tcu::TestStatus iterate(void);
439
440 private:
441 TextureCubeFilteringTestInstance(const TextureCubeFilteringTestInstance &other);
442 TextureCubeFilteringTestInstance &operator=(const TextureCubeFilteringTestInstance &other);
443
444 struct FilterCase
445 {
446 int textureIndex;
447 tcu::Vec2 bottomLeft;
448 tcu::Vec2 topRight;
449
FilterCasevkt::texture::__anon12a368720111::TextureCubeFilteringTestInstance::FilterCase450 FilterCase(void) : textureIndex(-1)
451 {
452 }
453
FilterCasevkt::texture::__anon12a368720111::TextureCubeFilteringTestInstance::FilterCase454 FilterCase(int tex_, const tcu::Vec2 &bottomLeft_, const tcu::Vec2 &topRight_)
455 : textureIndex(tex_)
456 , bottomLeft(bottomLeft_)
457 , topRight(topRight_)
458 {
459 }
460 };
461
462 const ParameterType m_testParameters;
463 vector<TestTextureCubeSp> m_textures;
464 vector<FilterCase> m_cases;
465 TextureRenderer m_renderer;
466 int m_caseNdx;
467 };
468
TextureCubeFilteringTestInstance(Context & context,const ParameterType & testParameters)469 TextureCubeFilteringTestInstance::TextureCubeFilteringTestInstance(Context &context,
470 const ParameterType &testParameters)
471 : TestInstance(context)
472 , m_testParameters(testParameters)
473 , m_renderer(context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
474 , m_caseNdx(0)
475 {
476 const int numLevels = deLog2Floor32(m_testParameters.size) + 1;
477 const tcu::TextureFormat texFormat = vk::mapVkFormat(m_testParameters.format);
478 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
479 tcu::Vec4 cBias, cScale;
480 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
481 {
482 const tcu::TextureFormat texFormatStencil = vk::mapVkFormat(VK_FORMAT_S8_UINT);
483 const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
484 cBias = fmtInfoStencil.valueMin;
485 cScale = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
486 }
487 else
488 {
489 cBias = fmtInfo.valueMin;
490 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
491 }
492
493 m_textures.reserve(2);
494 for (int ndx = 0; ndx < 2; ndx++)
495 m_textures.push_back(TestTextureCubeSp(
496 new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
497
498 // Fill first with gradient texture.
499 static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] = {
500 {tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // negative x
501 {tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // positive x
502 {tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // negative y
503 {tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // positive y
504 {tcu::Vec4(0.0f, 0.0f, 0.0f, 0.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)}, // negative z
505 {tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)} // positive z
506 };
507
508 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
509 {
510 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
511 {
512 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
513 tcu::fillWithComponentGradients(
514 getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, face), tcu::Sampler::MODE_STENCIL),
515 gradients[face][0] * cScale + cBias, gradients[face][1] * cScale + cBias);
516 else
517 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face),
518 gradients[face][0] * cScale + cBias,
519 gradients[face][1] * cScale + cBias);
520 }
521 }
522
523 // Fill second with grid texture.
524 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
525 {
526 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
527 {
528 const uint32_t step = 0x00ffffff / (numLevels * tcu::CUBEFACE_LAST);
529 const uint32_t rgb = step * levelNdx * face;
530 const uint32_t colorA = 0xff000000 | rgb;
531 const uint32_t colorB = 0xff000000 | ~rgb;
532
533 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
534 tcu::RGBA(colorB).toVec() * cScale + cBias);
535
536 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
537 tcu::fillWithGrid(
538 getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, face), tcu::Sampler::MODE_STENCIL),
539 4, tcu::RGBA(colorA).toVec() * cScale + cBias, tcu::RGBA(colorB).toVec() * cScale + cBias);
540 else
541 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4,
542 tcu::RGBA(colorA).toVec() * cScale + cBias,
543 tcu::RGBA(colorB).toVec() * cScale + cBias);
544 }
545 }
546
547 // Upload.
548 for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
549 {
550 m_renderer.addCubeTexture(*i, testParameters.aspectMask);
551 }
552
553 // Compute cases
554 {
555 const int tex0 = 0;
556 const int tex1 = m_textures.size() > 1 ? 1 : 0;
557
558 if (m_testParameters.onlySampleFaceInterior)
559 {
560 m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
561 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f))); // magnification
562 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
563 m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f), tcu::Vec2(0.6f, 0.5f))); // magnification
564 }
565 else
566 {
567 m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f))); // minification
568
569 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.8f, 0.8f), tcu::Vec2(1.25f, 1.20f))); // magnification
570 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f))); // minification
571 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.2f, -1.1f), tcu::Vec2(-0.8f, -0.8f))); // magnification
572 }
573 }
574 }
575
~TextureCubeFilteringTestInstance(void)576 TextureCubeFilteringTestInstance::~TextureCubeFilteringTestInstance(void)
577 {
578 }
579
getFaceDesc(const tcu::CubeFace face)580 const char *getFaceDesc(const tcu::CubeFace face)
581 {
582 switch (face)
583 {
584 case tcu::CUBEFACE_NEGATIVE_X:
585 return "-X";
586 case tcu::CUBEFACE_POSITIVE_X:
587 return "+X";
588 case tcu::CUBEFACE_NEGATIVE_Y:
589 return "-Y";
590 case tcu::CUBEFACE_POSITIVE_Y:
591 return "+Y";
592 case tcu::CUBEFACE_NEGATIVE_Z:
593 return "-Z";
594 case tcu::CUBEFACE_POSITIVE_Z:
595 return "+Z";
596 default:
597 DE_ASSERT(false);
598 return DE_NULL;
599 }
600 }
601
iterate(void)602 tcu::TestStatus TextureCubeFilteringTestInstance::iterate(void)
603 {
604 tcu::TestLog &log = m_context.getTestContext().getLog();
605
606 const pipeline::TestTextureCube &texture = m_renderer.getCubeTexture(m_cases[m_caseNdx].textureIndex);
607 const tcu::TextureFormat texFmt = texture.getTextureFormat();
608 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
609 const FilterCase &curCase = m_cases[m_caseNdx];
610 ReferenceParams refParams(TEXTURETYPE_CUBE);
611
612 // Params for reference computation.
613 refParams.sampler = util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter,
614 m_testParameters.magFilter);
615 if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
616 {
617 refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
618 refParams.samplerType = SAMPLERTYPE_UINT;
619 }
620 else
621 refParams.samplerType = getSamplerType(texFmt);
622 refParams.sampler.seamlessCubeMap = true;
623 refParams.lodMode = LODMODE_EXACT;
624 refParams.colorBias = fmtInfo.lookupBias;
625 refParams.colorScale = fmtInfo.lookupScale;
626
627 log << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight
628 << TestLog::EndMessage;
629
630 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
631 {
632 const tcu::CubeFace face = tcu::CubeFace(faceNdx);
633 tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
634 vector<float> texCoord;
635
636 computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
637
638 log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
639
640 // \todo Log texture coordinates.
641
642 m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
643
644 {
645 const bool isNearestOnly =
646 m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
647 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
648 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2],
649 formatBitDepth[3]);
650 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
651 tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
652 tcu::LodPrecision lodPrecision;
653 tcu::LookupPrecision lookupPrecision;
654
655 lodPrecision.derivateBits = 10;
656 lodPrecision.lodBits = 5;
657 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
658 lookupPrecision.coordBits = tcu::IVec3(10, 10, 10);
659 lookupPrecision.uvwBits = tcu::IVec3(6, 6, 0);
660 lookupPrecision.colorMask = getCompareMask(pixelFormat);
661
662 #ifdef CTS_USES_VULKANSC
663 if (m_context.getTestContext().getCommandLine().isSubProcess())
664 #endif // CTS_USES_VULKANSC
665 {
666 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
667 (tcu::TextureCubeView)texture.getTexture(), &texCoord[0],
668 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
677 << "Warning: Verification against high precision requirements failed, trying with lower "
678 "requirements."
679 << TestLog::EndMessage;
680
681 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
682 (tcu::TextureCubeView)texture.getTexture(), &texCoord[0],
683 refParams, lookupPrecision, lodPrecision, pixelFormat);
684
685 if (!isOk)
686 {
687 log << TestLog::Message
688 << "ERROR: Verification against low precision requirements failed, failing test case."
689 << TestLog::EndMessage;
690 return tcu::TestStatus::fail("Image verification failed");
691 }
692 }
693 }
694 }
695 }
696
697 m_caseNdx += 1;
698 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
699 }
700
701 // 2D array filtering
702
703 class Texture2DArrayFilteringTestInstance : public TestInstance
704 {
705 public:
706 typedef Texture2DArrayTestCaseParameters ParameterType;
707
708 Texture2DArrayFilteringTestInstance(Context &context, const ParameterType &testParameters);
709 ~Texture2DArrayFilteringTestInstance(void);
710
711 virtual tcu::TestStatus iterate(void);
712
713 private:
714 Texture2DArrayFilteringTestInstance(const Texture2DArrayFilteringTestInstance &);
715 Texture2DArrayFilteringTestInstance &operator=(const Texture2DArrayFilteringTestInstance &);
716
717 struct FilterCase
718 {
719 int textureIndex;
720 tcu::Vec2 lod;
721 tcu::Vec2 offset;
722 tcu::Vec2 layerRange;
723
FilterCasevkt::texture::__anon12a368720111::Texture2DArrayFilteringTestInstance::FilterCase724 FilterCase(void) : textureIndex(-1)
725 {
726 }
727
FilterCasevkt::texture::__anon12a368720111::Texture2DArrayFilteringTestInstance::FilterCase728 FilterCase(const int tex_, const tcu::Vec2 &lod_, const tcu::Vec2 &offset_, const tcu::Vec2 &layerRange_)
729 : textureIndex(tex_)
730 , lod(lod_)
731 , offset(offset_)
732 , layerRange(layerRange_)
733 {
734 }
735 };
736
737 const ParameterType m_testParameters;
738 vector<TestTexture2DArraySp> m_textures;
739 vector<FilterCase> m_cases;
740 TextureRenderer m_renderer;
741 int m_caseNdx;
742 };
743
Texture2DArrayFilteringTestInstance(Context & context,const ParameterType & testParameters)744 Texture2DArrayFilteringTestInstance::Texture2DArrayFilteringTestInstance(Context &context,
745 const ParameterType &testParameters)
746 : TestInstance(context)
747 , m_testParameters(testParameters)
748 , m_renderer(context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
749 , m_caseNdx(0)
750 {
751 const int numLevels = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1;
752 const tcu::TextureFormat texFormat = vk::mapVkFormat(m_testParameters.format);
753 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
754 tcu::Vec4 cBias, cScale;
755 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
756 {
757 const tcu::TextureFormat texFormatStencil = vk::mapVkFormat(VK_FORMAT_S8_UINT);
758 const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
759 cBias = fmtInfoStencil.valueMin;
760 cScale = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
761 }
762 else
763 {
764 cBias = fmtInfo.valueMin;
765 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
766 }
767
768 // Create textures.
769 m_textures.reserve(2);
770 for (int ndx = 0; ndx < 2; ndx++)
771 m_textures.push_back(TestTexture2DArraySp(
772 new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width,
773 m_testParameters.height, m_testParameters.numLayers)));
774
775 const tcu::IVec4 levelSwz[] = {
776 tcu::IVec4(0, 1, 2, 3),
777 tcu::IVec4(2, 1, 3, 0),
778 tcu::IVec4(3, 0, 1, 2),
779 tcu::IVec4(1, 3, 2, 0),
780 };
781
782 // Fill first gradient texture (gradient direction varies between layers).
783 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
784 {
785 for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
786 {
787 const tcu::IVec4 swz = levelSwz[layerNdx % DE_LENGTH_OF_ARRAY(levelSwz)];
788 const tcu::Vec4 gMin =
789 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f).swizzle(swz[0], swz[1], swz[2], swz[3]) * cScale + cBias;
790 const tcu::Vec4 gMax =
791 tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f).swizzle(swz[0], swz[1], swz[2], swz[3]) * cScale + cBias;
792
793 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
794 tcu::fillWithComponentGradients(
795 getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, layerNdx),
796 tcu::Sampler::MODE_STENCIL),
797 gMin, gMax);
798 else
799 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, layerNdx), gMin, gMax);
800 }
801 }
802
803 // Fill second with grid texture (each layer has unique colors).
804 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
805 {
806 for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
807 {
808 const uint32_t step = 0x00ffffff / (numLevels * m_testParameters.numLayers - 1);
809 const uint32_t rgb = step * (levelNdx + layerNdx * numLevels);
810 const uint32_t colorA = 0xff000000 | rgb;
811 const uint32_t colorB = 0xff000000 | ~rgb;
812
813 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
814 tcu::fillWithGrid(getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, layerNdx),
815 tcu::Sampler::MODE_STENCIL),
816 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
817 tcu::RGBA(colorB).toVec() * cScale + cBias);
818 else
819 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, layerNdx), 4,
820 tcu::RGBA(colorA).toVec() * cScale + cBias,
821 tcu::RGBA(colorB).toVec() * cScale + cBias);
822 }
823 }
824
825 // Upload.
826 for (vector<TestTexture2DArraySp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
827 {
828 m_renderer.add2DArrayTexture(*i, testParameters.aspectMask);
829 }
830
831 // Test cases
832 m_cases.push_back(FilterCase(0, tcu::Vec2(1.5f, 2.8f), tcu::Vec2(-1.0f, -2.7f),
833 tcu::Vec2(-0.5f, float(m_testParameters.numLayers) + 0.5f)));
834 m_cases.push_back(FilterCase(1, tcu::Vec2(0.2f, 0.175f), tcu::Vec2(-2.0f, -3.7f),
835 tcu::Vec2(-0.5f, float(m_testParameters.numLayers) + 0.5f)));
836 m_cases.push_back(FilterCase(1, tcu::Vec2(-0.8f, -2.3f), tcu::Vec2(0.2f, -0.1f),
837 tcu::Vec2(float(m_testParameters.numLayers) + 0.5f, -0.5f)));
838 m_cases.push_back(FilterCase(0, tcu::Vec2(-2.0f, -1.5f), tcu::Vec2(-0.1f, 0.9f), tcu::Vec2(1.50001f, 1.49999f)));
839 }
840
~Texture2DArrayFilteringTestInstance(void)841 Texture2DArrayFilteringTestInstance::~Texture2DArrayFilteringTestInstance(void)
842 {
843 }
844
iterate(void)845 tcu::TestStatus Texture2DArrayFilteringTestInstance::iterate(void)
846 {
847 tcu::TestLog &log = m_context.getTestContext().getLog();
848
849 const FilterCase &curCase = m_cases[m_caseNdx];
850 const pipeline::TestTexture2DArray &texture = m_renderer.get2DArrayTexture(curCase.textureIndex);
851 const tcu::TextureFormat texFmt = texture.getTextureFormat();
852 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
853 ReferenceParams refParams(TEXTURETYPE_2D_ARRAY);
854 tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
855 tcu::Vec3 texCoord[4];
856 const float *const texCoordPtr = (const float *)&texCoord[0];
857
858 // Params for reference computation.
859
860 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter,
861 m_testParameters.magFilter);
862 if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
863 {
864 refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
865 refParams.samplerType = SAMPLERTYPE_UINT;
866 }
867 else
868 refParams.samplerType = getSamplerType(texFmt);
869 refParams.lodMode = LODMODE_EXACT;
870 refParams.colorBias = fmtInfo.lookupBias;
871 refParams.colorScale = fmtInfo.lookupScale;
872
873 // Compute texture coordinates.
874 log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset
875 << TestLog::EndMessage;
876
877 {
878 const float lodX = curCase.lod.x();
879 const float lodY = curCase.lod.y();
880 const float oX = curCase.offset.x();
881 const float oY = curCase.offset.y();
882 const float sX =
883 deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
884 const float sY =
885 deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
886 const float l0 = curCase.layerRange.x();
887 const float l1 = curCase.layerRange.y();
888
889 texCoord[0] = tcu::Vec3(oX, oY, l0);
890 texCoord[1] = tcu::Vec3(oX, oY + sY, l0 * 0.5f + l1 * 0.5f);
891 texCoord[2] = tcu::Vec3(oX + sX, oY, l0 * 0.5f + l1 * 0.5f);
892 texCoord[3] = tcu::Vec3(oX + sX, oY + sY, l1);
893 }
894
895 m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
896
897 {
898
899 const bool isNearestOnly =
900 m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
901 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
902 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
903 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
904 tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
905 tcu::LodPrecision lodPrecision;
906 tcu::LookupPrecision lookupPrecision;
907
908 lodPrecision.derivateBits = 18;
909 lodPrecision.lodBits = 6;
910 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
911 lookupPrecision.coordBits = tcu::IVec3(20, 20, 20);
912 lookupPrecision.uvwBits = tcu::IVec3(7, 7, 0);
913 lookupPrecision.colorMask = getCompareMask(pixelFormat);
914
915 #ifdef CTS_USES_VULKANSC
916 if (m_context.getTestContext().getCommandLine().isSubProcess())
917 #endif // CTS_USES_VULKANSC
918 {
919 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
920 (tcu::Texture2DArrayView)texture.getTexture(), texCoordPtr,
921 refParams, lookupPrecision, lodPrecision, pixelFormat);
922
923 if (!isHighQuality)
924 {
925 // Evaluate against lower precision requirements.
926 lodPrecision.lodBits = 4;
927 lookupPrecision.uvwBits = tcu::IVec3(4, 4, 0);
928
929 log << TestLog::Message
930 << "Warning: Verification against high precision requirements failed, trying with lower "
931 "requirements."
932 << TestLog::EndMessage;
933
934 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
935 (tcu::Texture2DArrayView)texture.getTexture(), texCoordPtr,
936 refParams, lookupPrecision, lodPrecision, pixelFormat);
937
938 if (!isOk)
939 {
940 log << TestLog::Message
941 << "ERROR: Verification against low precision requirements failed, failing test case."
942 << TestLog::EndMessage;
943 return tcu::TestStatus::fail("Image verification failed");
944 }
945 }
946 }
947 }
948
949 m_caseNdx += 1;
950 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
951 }
952
953 // 3D filtering
954
955 class Texture3DFilteringTestInstance : public TestInstance
956 {
957 public:
958 typedef Texture3DTestCaseParameters ParameterType;
959
960 Texture3DFilteringTestInstance(Context &context, const ParameterType &testParameters);
961 ~Texture3DFilteringTestInstance(void);
962
963 virtual tcu::TestStatus iterate(void);
964
965 private:
966 Texture3DFilteringTestInstance(const Texture3DFilteringTestInstance &other);
967 Texture3DFilteringTestInstance &operator=(const Texture3DFilteringTestInstance &other);
968
969 struct FilterCase
970 {
971 int textureIndex;
972 tcu::Vec3 lod;
973 tcu::Vec3 offset;
974
FilterCasevkt::texture::__anon12a368720111::Texture3DFilteringTestInstance::FilterCase975 FilterCase(void) : textureIndex(-1)
976 {
977 }
978
FilterCasevkt::texture::__anon12a368720111::Texture3DFilteringTestInstance::FilterCase979 FilterCase(const int tex_, const tcu::Vec3 &lod_, const tcu::Vec3 &offset_)
980 : textureIndex(tex_)
981 , lod(lod_)
982 , offset(offset_)
983 {
984 }
985 };
986
987 const ParameterType m_testParameters;
988 vector<TestTexture3DSp> m_textures;
989 vector<FilterCase> m_cases;
990 TextureRenderer m_renderer;
991 int m_caseNdx;
992 };
993
Texture3DFilteringTestInstance(Context & context,const ParameterType & testParameters)994 Texture3DFilteringTestInstance::Texture3DFilteringTestInstance(Context &context, const ParameterType &testParameters)
995 : TestInstance(context)
996 , m_testParameters(testParameters)
997 , m_renderer(context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
998 , m_caseNdx(0)
999 {
1000 const int numLevels =
1001 deLog2Floor32(de::max(de::max(m_testParameters.width, m_testParameters.height), m_testParameters.depth)) + 1;
1002 const tcu::TextureFormat texFormat = vk::mapVkFormat(m_testParameters.format);
1003 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
1004 tcu::Vec4 cBias, cScale;
1005 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1006 {
1007 const tcu::TextureFormat texFormatStencil = vk::mapVkFormat(VK_FORMAT_S8_UINT);
1008 const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
1009 cBias = fmtInfoStencil.valueMin;
1010 cScale = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
1011 }
1012 else
1013 {
1014 cBias = fmtInfo.valueMin;
1015 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1016 }
1017
1018 // Create textures.
1019 m_textures.reserve(2);
1020 for (int ndx = 0; ndx < 2; ndx++)
1021 m_textures.push_back(TestTexture3DSp(
1022 new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width,
1023 m_testParameters.height, m_testParameters.depth)));
1024
1025 // Fill first gradient texture.
1026 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1027 {
1028 const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1029 const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1030
1031 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1032 tcu::fillWithComponentGradients(
1033 getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), gMin,
1034 gMax);
1035 else
1036 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
1037 }
1038
1039 // Fill second with grid texture.
1040 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1041 {
1042 const uint32_t step = 0x00ffffff / numLevels;
1043 const uint32_t rgb = step * levelNdx;
1044 const uint32_t colorA = 0xff000000 | rgb;
1045 const uint32_t colorB = 0xff000000 | ~rgb;
1046
1047 if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1048 tcu::fillWithGrid(
1049 getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), 4,
1050 tcu::RGBA(colorA).toVec() * cScale + cBias, tcu::RGBA(colorB).toVec() * cScale + cBias);
1051 else
1052 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
1053 tcu::RGBA(colorB).toVec() * cScale + cBias);
1054 }
1055
1056 // Upload.
1057 for (vector<TestTexture3DSp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
1058 {
1059 m_renderer.add3DTexture(*i, testParameters.aspectMask);
1060 }
1061
1062 // Test cases
1063 m_cases.push_back(FilterCase(0, tcu::Vec3(1.5f, 2.8f, 1.0f), tcu::Vec3(-1.0f, -2.7f, -2.275f)));
1064 m_cases.push_back(FilterCase(0, tcu::Vec3(-2.0f, -1.5f, -1.8f), tcu::Vec3(-0.1f, 0.9f, -0.25f)));
1065 m_cases.push_back(FilterCase(1, tcu::Vec3(0.2f, 0.175f, 0.3f), tcu::Vec3(-2.0f, -3.7f, -1.825f)));
1066 m_cases.push_back(FilterCase(1, tcu::Vec3(-0.8f, -2.3f, -2.5f), tcu::Vec3(0.2f, -0.1f, 1.325f)));
1067 }
1068
~Texture3DFilteringTestInstance(void)1069 Texture3DFilteringTestInstance::~Texture3DFilteringTestInstance(void)
1070 {
1071 }
1072
iterate(void)1073 tcu::TestStatus Texture3DFilteringTestInstance::iterate(void)
1074 {
1075 tcu::TestLog &log = m_context.getTestContext().getLog();
1076
1077 const pipeline::TestTexture3D &texture = m_renderer.get3DTexture(m_cases[m_caseNdx].textureIndex);
1078 const tcu::TextureFormat texFmt = texture.getTextureFormat();
1079 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
1080 const FilterCase &curCase = m_cases[m_caseNdx];
1081 ReferenceParams refParams(TEXTURETYPE_3D);
1082 tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
1083 tcu::Vec3 texCoord[4];
1084 const float *const texCoordPtr = (const float *)&texCoord[0];
1085
1086 // Params for reference computation.
1087 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.wrapR,
1088 m_testParameters.minFilter, m_testParameters.magFilter);
1089 if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1090 {
1091 refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
1092 refParams.samplerType = SAMPLERTYPE_UINT;
1093 }
1094 else
1095 refParams.samplerType = getSamplerType(texFmt);
1096 refParams.lodMode = LODMODE_EXACT;
1097 refParams.colorBias = fmtInfo.lookupBias;
1098 refParams.colorScale = fmtInfo.lookupScale;
1099
1100 // Compute texture coordinates.
1101 log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset
1102 << TestLog::EndMessage;
1103
1104 {
1105 const float lodX = curCase.lod.x();
1106 const float lodY = curCase.lod.y();
1107 const float lodZ = curCase.lod.z();
1108 const float oX = curCase.offset.x();
1109 const float oY = curCase.offset.y();
1110 const float oZ = curCase.offset.z();
1111 const float sX =
1112 deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
1113 const float sY =
1114 deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
1115 const float sZ = deFloatExp2(lodZ) * float(de::max(m_renderer.getRenderWidth(), m_renderer.getRenderHeight())) /
1116 float(m_textures[0]->getTexture().getDepth());
1117
1118 texCoord[0] = tcu::Vec3(oX, oY, oZ);
1119 texCoord[1] = tcu::Vec3(oX, oY + sY, oZ + sZ * 0.5f);
1120 texCoord[2] = tcu::Vec3(oX + sX, oY, oZ + sZ * 0.5f);
1121 texCoord[3] = tcu::Vec3(oX + sX, oY + sY, oZ + sZ);
1122 }
1123
1124 m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
1125
1126 {
1127 const bool isNearestOnly =
1128 m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
1129 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1130 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1131 const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
1132 tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
1133 tcu::LodPrecision lodPrecision;
1134 tcu::LookupPrecision lookupPrecision;
1135
1136 lodPrecision.derivateBits = 18;
1137 lodPrecision.lodBits = 6;
1138 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
1139 lookupPrecision.coordBits = tcu::IVec3(20, 20, 20);
1140 lookupPrecision.uvwBits = tcu::IVec3(7, 7, 7);
1141 lookupPrecision.colorMask = getCompareMask(pixelFormat);
1142
1143 #ifdef CTS_USES_VULKANSC
1144 if (m_context.getTestContext().getCommandLine().isSubProcess())
1145 #endif // CTS_USES_VULKANSC
1146 {
1147 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
1148 (tcu::Texture3DView)texture.getTexture(), texCoordPtr,
1149 refParams, lookupPrecision, lodPrecision, pixelFormat);
1150
1151 if (!isHighQuality)
1152 {
1153 // Evaluate against lower precision requirements.
1154 lodPrecision.lodBits = 4;
1155 lookupPrecision.uvwBits = tcu::IVec3(4, 4, 4);
1156
1157 log << TestLog::Message
1158 << "Warning: Verification against high precision requirements failed, trying with lower "
1159 "requirements."
1160 << TestLog::EndMessage;
1161
1162 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
1163 (tcu::Texture3DView)texture.getTexture(), texCoordPtr, refParams,
1164 lookupPrecision, lodPrecision, pixelFormat);
1165
1166 if (!isOk)
1167 {
1168 log << TestLog::Message
1169 << "ERROR: Verification against low precision requirements failed, failing test case."
1170 << TestLog::EndMessage;
1171 return tcu::TestStatus::fail("Image verification failed");
1172 }
1173 }
1174 }
1175 }
1176
1177 m_caseNdx += 1;
1178 return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1179 }
1180
verifierCanBeUsed(const VkFormat format,const Sampler::FilterMode minFilter,const Sampler::FilterMode magFilter)1181 bool verifierCanBeUsed(const VkFormat format, const Sampler::FilterMode minFilter, const Sampler::FilterMode magFilter)
1182 {
1183 const tcu::TextureFormat textureFormat = mapVkFormat(format);
1184 const tcu::TextureChannelClass textureChannelClass = tcu::getTextureChannelClass(textureFormat.type);
1185
1186 return !(!(textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1187 textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1188 textureChannelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) &&
1189 (tcu::TexVerifierUtil::isLinearFilter(minFilter) || tcu::TexVerifierUtil::isLinearFilter(magFilter) ||
1190 tcu::TexVerifierUtil::isCubicFilter(minFilter) || tcu::TexVerifierUtil::isCubicFilter(magFilter)));
1191 }
1192
1193 } // namespace
1194
populateTextureFilteringTests(tcu::TestCaseGroup * textureFilteringTests)1195 void populateTextureFilteringTests(tcu::TestCaseGroup *textureFilteringTests)
1196 {
1197 tcu::TestContext &testCtx = textureFilteringTests->getTestContext();
1198
1199 static const struct
1200 {
1201 const char *const name;
1202 const Sampler::WrapMode mode;
1203 } wrapModes[] = {{"repeat", Sampler::REPEAT_GL},
1204 {"mirrored_repeat", Sampler::MIRRORED_REPEAT_GL},
1205 {"clamp_to_edge", Sampler::CLAMP_TO_EDGE},
1206 {"clamp_to_border", Sampler::CLAMP_TO_BORDER},
1207 {"mirror_clamp_to_edge", Sampler::MIRRORED_ONCE}};
1208
1209 struct FilterModes
1210 {
1211 const char *const name;
1212 const Sampler::FilterMode mode;
1213 };
1214
1215 static const FilterModes minFilterModes[] = {{"nearest", Sampler::NEAREST},
1216 {"linear", Sampler::LINEAR},
1217 {"nearest_mipmap_nearest", Sampler::NEAREST_MIPMAP_NEAREST},
1218 {"linear_mipmap_nearest", Sampler::LINEAR_MIPMAP_NEAREST},
1219 {"nearest_mipmap_linear", Sampler::NEAREST_MIPMAP_LINEAR},
1220 {"linear_mipmap_linear", Sampler::LINEAR_MIPMAP_LINEAR}};
1221
1222 static const FilterModes magFilterModes[] = {{"nearest", Sampler::NEAREST}, {"linear", Sampler::LINEAR}};
1223
1224 static const FilterModes minFilterModes2D[] = {{"nearest", Sampler::NEAREST},
1225 {"linear", Sampler::LINEAR},
1226 {"cubic", Sampler::CUBIC},
1227 {"nearest_mipmap_nearest", Sampler::NEAREST_MIPMAP_NEAREST},
1228 {"linear_mipmap_nearest", Sampler::LINEAR_MIPMAP_NEAREST},
1229 {"nearest_mipmap_linear", Sampler::NEAREST_MIPMAP_LINEAR},
1230 {"linear_mipmap_linear", Sampler::LINEAR_MIPMAP_LINEAR},
1231 {"cubic_mipmap_nearest", Sampler::CUBIC_MIPMAP_NEAREST},
1232 {"cubic_mipmap_linear", Sampler::CUBIC_MIPMAP_LINEAR}};
1233
1234 static const FilterModes magFilterModes2D[] = {
1235 {"nearest", Sampler::NEAREST}, {"linear", Sampler::LINEAR}, {"cubic", Sampler::CUBIC}};
1236
1237 static const struct
1238 {
1239 const int width;
1240 const int height;
1241 } sizes2D[] = {{4, 8}, {32, 64}, {128, 128}, {3, 7}, {31, 55}, {127, 99}};
1242
1243 static const struct
1244 {
1245 const int size;
1246 } sizesCube[] = {{8}, {64}, {128}, {7}, {63}};
1247
1248 static const struct
1249 {
1250 const int width;
1251 const int height;
1252 const int numLayers;
1253 } sizes2DArray[] = {{4, 8, 8}, {32, 64, 16}, {128, 32, 64}, {3, 7, 5}, {63, 63, 63}};
1254
1255 static const struct
1256 {
1257 const int width;
1258 const int height;
1259 const int depth;
1260 } sizes3D[] = {{4, 8, 8}, {32, 64, 16}, {128, 32, 64}, {3, 7, 5}, {63, 63, 63}};
1261
1262 static const struct
1263 {
1264 const char *const name;
1265 const VkFormat format;
1266 const VkImageAspectFlags aspectMask;
1267 const Program program2D;
1268 const Program programCube;
1269 const Program program2DArray;
1270 const Program program3D;
1271 } filterableFormatsByType[] = {
1272 {"r16g16b16a16_sfloat", VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1273 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1274 {"b10g11r11_ufloat", VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1275 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1276 {"e5b9g9r9_ufloat", VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1277 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1278 {"r8g8b8a8_unorm", VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT,
1279 PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1280 {"r8g8b8a8_snorm", VK_FORMAT_R8G8B8A8_SNORM, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT,
1281 PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1282 {"r5g6b5_unorm", VK_FORMAT_R5G6B5_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT,
1283 PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1284 {"r10x6g10x6b10x6a10x6_unorm", VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, VK_IMAGE_ASPECT_COLOR_BIT,
1285 PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1286 {"r4g4b4a4_unorm", VK_FORMAT_R4G4B4A4_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1287 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1288 {"a4r4g4b4_unorm", VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1289 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1290 {"a4b4g4r4_unorm", VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1291 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1292 {"r5g5b5a1_unorm", VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1293 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1294 {"a8b8g8r8_srgb", VK_FORMAT_A8B8G8R8_SRGB_PACK32, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1295 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1296 {"a1r5g5b5_unorm", VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1297 PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1298 {"s8_uint", VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT, PROGRAM_2D_UINT, PROGRAM_CUBE_UINT,
1299 PROGRAM_2D_ARRAY_UINT, PROGRAM_3D_UINT},
1300 {"d24_unorm_s8_uint_stencil", VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT, PROGRAM_2D_UINT,
1301 PROGRAM_CUBE_UINT, PROGRAM_2D_ARRAY_UINT, PROGRAM_3D_UINT},
1302 {"d32_sfloat_s8_uint_stencil", VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT, PROGRAM_2D_UINT,
1303 PROGRAM_CUBE_UINT, PROGRAM_2D_ARRAY_UINT, PROGRAM_3D_UINT}};
1304
1305 // 2D texture filtering.
1306 {
1307 // 2D Texture Filtering
1308 de::MovePtr<tcu::TestCaseGroup> group2D(new tcu::TestCaseGroup(testCtx, "2d"));
1309
1310 // 2D Texture Formats
1311 de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1312 de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1313 de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1314
1315 // Formats.
1316 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1317 {
1318 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1319 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1320
1321 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1322 {
1323 const Sampler::FilterMode minFilter = minFilterModes2D[filterNdx].mode;
1324 const bool isMipmap =
1325 minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1326 const string name = minFilterModes2D[filterNdx].name;
1327 Texture2DTestCaseParameters testParameters;
1328
1329 testParameters.format = filterableFormatsByType[fmtNdx].format;
1330 testParameters.minFilter = minFilter;
1331 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1332 testParameters.mipmaps = true;
1333
1334 testParameters.wrapS = Sampler::REPEAT_GL;
1335 testParameters.wrapT = Sampler::REPEAT_GL;
1336 testParameters.width = 64;
1337 testParameters.height = 64;
1338
1339 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1340 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1341
1342 // Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1343 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1344 {
1345 filterGroup->addChild(
1346 new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1347 }
1348 }
1349 formatsGroup->addChild(filterGroup.release());
1350 }
1351
1352 // Sizes.
1353 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1354 {
1355 const string filterGroupName =
1356 de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1357 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1358
1359 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1360 {
1361 const Sampler::FilterMode minFilter = minFilterModes2D[filterNdx].mode;
1362 const bool isMipmap =
1363 minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1364 const string name = minFilterModes2D[filterNdx].name;
1365 Texture2DTestCaseParameters testParameters;
1366
1367 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1368 testParameters.minFilter = minFilter;
1369 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1370 testParameters.mipmaps = true;
1371
1372 testParameters.wrapS = Sampler::REPEAT_GL;
1373 testParameters.wrapT = Sampler::REPEAT_GL;
1374 testParameters.width = sizes2D[sizeNdx].width;
1375 testParameters.height = sizes2D[sizeNdx].height;
1376
1377 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1378 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1379
1380 filterGroup->addChild(
1381 new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1382 }
1383 sizesGroup->addChild(filterGroup.release());
1384 }
1385
1386 // Wrap modes.
1387 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); minFilterNdx++)
1388 {
1389 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1390 new tcu::TestCaseGroup(testCtx, minFilterModes2D[minFilterNdx].name));
1391
1392 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); magFilterNdx++)
1393 {
1394 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1395 new tcu::TestCaseGroup(testCtx, magFilterModes2D[magFilterNdx].name));
1396
1397 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1398 {
1399 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1400 new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1401
1402 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1403 {
1404 const string name = wrapModes[wrapTNdx].name;
1405 Texture2DTestCaseParameters testParameters;
1406
1407 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1408 testParameters.minFilter = minFilterModes2D[minFilterNdx].mode;
1409 testParameters.magFilter = magFilterModes2D[magFilterNdx].mode;
1410 testParameters.mipmaps = true;
1411
1412 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1413 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1414 testParameters.width = 63;
1415 testParameters.height = 57;
1416
1417 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1418 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1419
1420 wrapSGroup->addChild(
1421 new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1422 }
1423 magFilterGroup->addChild(wrapSGroup.release());
1424 }
1425 minFilterGroup->addChild(magFilterGroup.release());
1426 }
1427 combinationsGroup->addChild(minFilterGroup.release());
1428 }
1429
1430 group2D->addChild(formatsGroup.release());
1431 group2D->addChild(sizesGroup.release());
1432 group2D->addChild(combinationsGroup.release());
1433
1434 textureFilteringTests->addChild(group2D.release());
1435 }
1436
1437 // Unnormalized texture filtering.
1438 {
1439 de::MovePtr<tcu::TestCaseGroup> groupUnnormal(new tcu::TestCaseGroup(testCtx, "unnormal"));
1440
1441 de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1442 de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1443
1444 // Formats.
1445 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1446 {
1447 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1448 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1449
1450 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1451 {
1452 const Sampler::FilterMode magFilter = magFilterModes2D[filterNdx].mode;
1453 const string name = magFilterModes2D[filterNdx].name;
1454 Texture2DTestCaseParameters testParameters;
1455
1456 testParameters.unnormal = true;
1457
1458 testParameters.format = filterableFormatsByType[fmtNdx].format;
1459 testParameters.minFilter = magFilter;
1460 testParameters.magFilter = magFilter;
1461 testParameters.mipmaps = false;
1462
1463 testParameters.wrapS = ((fmtNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1464 testParameters.wrapT = ((fmtNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1465 testParameters.width = 64;
1466 testParameters.height = 64;
1467
1468 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1469 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1470
1471 // Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1472 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1473 {
1474 filterGroup->addChild(
1475 new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1476 }
1477 }
1478 formatsGroup->addChild(filterGroup.release());
1479 }
1480
1481 // Sizes.
1482 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1483 {
1484 const string filterGroupName =
1485 de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1486 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1487
1488 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1489 {
1490 const Sampler::FilterMode magFilter = magFilterModes2D[filterNdx].mode;
1491 const string name = magFilterModes2D[filterNdx].name;
1492 Texture2DTestCaseParameters testParameters;
1493
1494 testParameters.unnormal = true;
1495 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1496 testParameters.minFilter = magFilter;
1497 testParameters.magFilter = magFilter;
1498 testParameters.mipmaps = false;
1499
1500 testParameters.wrapS = ((sizeNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1501 testParameters.wrapT = ((sizeNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1502 testParameters.width = sizes2D[sizeNdx].width;
1503 testParameters.height = sizes2D[sizeNdx].height;
1504
1505 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1506 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1507
1508 filterGroup->addChild(
1509 new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1510 }
1511 sizesGroup->addChild(filterGroup.release());
1512 }
1513
1514 groupUnnormal->addChild(formatsGroup.release());
1515 groupUnnormal->addChild(sizesGroup.release());
1516
1517 textureFilteringTests->addChild(groupUnnormal.release());
1518 }
1519
1520 // Cube map texture filtering.
1521 {
1522 de::MovePtr<tcu::TestCaseGroup> groupCube(new tcu::TestCaseGroup(testCtx, "cube"));
1523
1524 de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1525 de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1526 de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1527 de::MovePtr<tcu::TestCaseGroup> onlyFaceInteriorGroup(new tcu::TestCaseGroup(testCtx, "no_edges_visible"));
1528
1529 // Formats.
1530 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1531 {
1532 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1533 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1534
1535 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1536 {
1537 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1538 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1539 const string name = minFilterModes[filterNdx].name;
1540 TextureCubeFilteringTestCaseParameters testParameters;
1541
1542 testParameters.format = filterableFormatsByType[fmtNdx].format;
1543 testParameters.minFilter = minFilter;
1544 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1545
1546 testParameters.wrapS = Sampler::REPEAT_GL;
1547 testParameters.wrapT = Sampler::REPEAT_GL;
1548 testParameters.onlySampleFaceInterior = false;
1549 testParameters.size = 64;
1550
1551 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1552 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].programCube);
1553
1554 // Some tests have to be skipped due to the restrictions of the verifiers.
1555 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1556 {
1557 filterGroup->addChild(
1558 new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1559 }
1560 }
1561 formatsGroup->addChild(filterGroup.release());
1562 }
1563
1564 // Sizes.
1565 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
1566 {
1567 const string filterGroupName =
1568 de::toString(sizesCube[sizeNdx].size) + "x" + de::toString(sizesCube[sizeNdx].size);
1569 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1570
1571 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1572 {
1573 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1574 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1575 const string name = minFilterModes[filterNdx].name;
1576 TextureCubeFilteringTestCaseParameters testParameters;
1577
1578 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1579 testParameters.minFilter = minFilter;
1580 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1581 testParameters.wrapS = Sampler::REPEAT_GL;
1582 testParameters.wrapT = Sampler::REPEAT_GL;
1583 testParameters.onlySampleFaceInterior = false;
1584 testParameters.size = sizesCube[sizeNdx].size;
1585
1586 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1587 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1588
1589 filterGroup->addChild(
1590 new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1591 }
1592 sizesGroup->addChild(filterGroup.release());
1593 }
1594
1595 // Filter/wrap mode combinations.
1596 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1597 {
1598 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1599 new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name));
1600
1601 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1602 {
1603 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1604 new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name));
1605
1606 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1607 {
1608 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1609 new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1610
1611 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1612 {
1613 const string name = wrapModes[wrapTNdx].name;
1614 TextureCubeFilteringTestCaseParameters testParameters;
1615
1616 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1617 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1618 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1619 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1620 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1621 testParameters.onlySampleFaceInterior = false;
1622 testParameters.size = 63;
1623
1624 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1625 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1626
1627 wrapSGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(
1628 testCtx, name.c_str(), testParameters));
1629 }
1630 magFilterGroup->addChild(wrapSGroup.release());
1631 }
1632 minFilterGroup->addChild(magFilterGroup.release());
1633 }
1634 combinationsGroup->addChild(minFilterGroup.release());
1635 }
1636
1637 // Cases with no visible cube edges.
1638 for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
1639 {
1640 const bool isLinear = isLinearI != 0;
1641 const string name = isLinear ? "linear" : "nearest";
1642 TextureCubeFilteringTestCaseParameters testParameters;
1643
1644 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1645 testParameters.minFilter = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1646 testParameters.magFilter = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1647 testParameters.wrapS = Sampler::REPEAT_GL;
1648 testParameters.wrapT = Sampler::REPEAT_GL;
1649 testParameters.onlySampleFaceInterior = true;
1650 testParameters.size = 63;
1651
1652 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1653 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1654
1655 onlyFaceInteriorGroup->addChild(
1656 new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1657 }
1658
1659 groupCube->addChild(formatsGroup.release());
1660 groupCube->addChild(sizesGroup.release());
1661 groupCube->addChild(combinationsGroup.release());
1662 groupCube->addChild(onlyFaceInteriorGroup.release());
1663
1664 textureFilteringTests->addChild(groupCube.release());
1665 }
1666
1667 // 2D array texture filtering.
1668 {
1669 de::MovePtr<tcu::TestCaseGroup> group2DArray(new tcu::TestCaseGroup(testCtx, "2d_array"));
1670
1671 de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1672 de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1673 de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1674
1675 // Formats.
1676 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1677 {
1678 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1679 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1680
1681 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1682 {
1683 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1684 const char *const filterName = minFilterModes[filterNdx].name;
1685 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1686 const char *const formatName = filterableFormatsByType[fmtNdx].name;
1687 const string name = string(formatName) + "_" + filterName;
1688 Texture2DArrayTestCaseParameters testParameters;
1689
1690 testParameters.format = filterableFormatsByType[fmtNdx].format;
1691 testParameters.minFilter = minFilter;
1692 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1693
1694 testParameters.wrapS = Sampler::REPEAT_GL;
1695 testParameters.wrapT = Sampler::REPEAT_GL;
1696 testParameters.width = 128;
1697 testParameters.height = 128;
1698 testParameters.numLayers = 8;
1699
1700 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1701 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2DArray);
1702
1703 // Some tests have to be skipped due to the restrictions of the verifiers.
1704 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1705 {
1706 filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(
1707 testCtx, name.c_str(), testParameters));
1708 }
1709 }
1710 formatsGroup->addChild(filterGroup.release());
1711 }
1712
1713 // Sizes.
1714 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2DArray); sizeNdx++)
1715 {
1716 const string filterGroupName = de::toString(sizes2DArray[sizeNdx].width) + "x" +
1717 de::toString(sizes2DArray[sizeNdx].height) + "x" +
1718 de::toString(sizes2DArray[sizeNdx].numLayers);
1719 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1720
1721 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1722 {
1723 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1724 const char *const filterName = minFilterModes[filterNdx].name;
1725 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1726 const string name = filterName;
1727 Texture2DArrayTestCaseParameters testParameters;
1728
1729 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1730 testParameters.minFilter = minFilter;
1731 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1732 testParameters.wrapS = Sampler::REPEAT_GL;
1733 testParameters.wrapT = Sampler::REPEAT_GL;
1734 testParameters.width = sizes2DArray[sizeNdx].width;
1735 testParameters.height = sizes2DArray[sizeNdx].height;
1736 testParameters.numLayers = sizes2DArray[sizeNdx].numLayers;
1737
1738 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1739 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1740
1741 filterGroup->addChild(
1742 new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1743 }
1744 sizesGroup->addChild(filterGroup.release());
1745 }
1746
1747 // Wrap modes.
1748 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1749 {
1750 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1751 new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name));
1752
1753 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1754 {
1755 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1756 new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name));
1757
1758 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1759 {
1760 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1761 new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1762
1763 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1764 {
1765 const string name = wrapModes[wrapTNdx].name;
1766 Texture2DArrayTestCaseParameters testParameters;
1767
1768 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1769 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1770 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1771 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1772 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1773 testParameters.width = 123;
1774 testParameters.height = 107;
1775 testParameters.numLayers = 7;
1776
1777 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1778 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1779
1780 wrapSGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(
1781 testCtx, name.c_str(), testParameters));
1782 }
1783 magFilterGroup->addChild(wrapSGroup.release());
1784 }
1785 minFilterGroup->addChild(magFilterGroup.release());
1786 }
1787 combinationsGroup->addChild(minFilterGroup.release());
1788 }
1789
1790 group2DArray->addChild(formatsGroup.release());
1791 group2DArray->addChild(sizesGroup.release());
1792 group2DArray->addChild(combinationsGroup.release());
1793
1794 textureFilteringTests->addChild(group2DArray.release());
1795 }
1796
1797 // 3D texture filtering.
1798 {
1799 de::MovePtr<tcu::TestCaseGroup> group3D(new tcu::TestCaseGroup(testCtx, "3d"));
1800
1801 de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1802 de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1803 de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1804
1805 // Formats.
1806 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1807 {
1808 const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1809 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1810
1811 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1812 {
1813 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1814 const char *const filterName = minFilterModes[filterNdx].name;
1815 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1816 const char *const formatName = filterableFormatsByType[fmtNdx].name;
1817 const string name = string(formatName) + "_" + filterName;
1818 Texture3DTestCaseParameters testParameters;
1819
1820 testParameters.format = filterableFormatsByType[fmtNdx].format;
1821 testParameters.minFilter = minFilter;
1822 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1823
1824 testParameters.wrapS = Sampler::REPEAT_GL;
1825 testParameters.wrapT = Sampler::REPEAT_GL;
1826 testParameters.wrapR = Sampler::REPEAT_GL;
1827 testParameters.width = 64;
1828 testParameters.height = 64;
1829 testParameters.depth = 64;
1830
1831 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1832 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program3D);
1833
1834 // Some tests have to be skipped due to the restrictions of the verifiers.
1835 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1836 {
1837 filterGroup->addChild(
1838 new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1839 }
1840 }
1841 formatsGroup->addChild(filterGroup.release());
1842 }
1843
1844 // Sizes.
1845 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes3D); sizeNdx++)
1846 {
1847 const string filterGroupName = de::toString(sizes3D[sizeNdx].width) + "x" +
1848 de::toString(sizes3D[sizeNdx].height) + "x" +
1849 de::toString(sizes3D[sizeNdx].depth);
1850 de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1851
1852 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1853 {
1854 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1855 const char *const filterName = minFilterModes[filterNdx].name;
1856 const bool isMipmap = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1857 const string name = filterName;
1858 Texture3DTestCaseParameters testParameters;
1859
1860 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1861 testParameters.minFilter = minFilter;
1862 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1863 testParameters.wrapS = Sampler::REPEAT_GL;
1864 testParameters.wrapT = Sampler::REPEAT_GL;
1865 testParameters.wrapR = Sampler::REPEAT_GL;
1866 testParameters.width = sizes3D[sizeNdx].width;
1867 testParameters.height = sizes3D[sizeNdx].height;
1868 testParameters.depth = sizes3D[sizeNdx].depth;
1869
1870 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1871 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1872
1873 filterGroup->addChild(
1874 new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1875 }
1876 sizesGroup->addChild(filterGroup.release());
1877 }
1878
1879 // Wrap modes.
1880 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1881 {
1882 de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1883 new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name));
1884
1885 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1886 {
1887 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1888 new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name));
1889
1890 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1891 {
1892 de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1893 new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1894
1895 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1896 {
1897 de::MovePtr<tcu::TestCaseGroup> wrapTGroup(
1898 new tcu::TestCaseGroup(testCtx, wrapModes[wrapTNdx].name));
1899
1900 for (int wrapRNdx = 0; wrapRNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapRNdx++)
1901 {
1902 const string name = wrapModes[wrapRNdx].name;
1903 Texture3DTestCaseParameters testParameters;
1904
1905 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
1906 testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1907 testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1908 testParameters.wrapS = wrapModes[wrapSNdx].mode;
1909 testParameters.wrapT = wrapModes[wrapTNdx].mode;
1910 testParameters.wrapR = wrapModes[wrapRNdx].mode;
1911 testParameters.width = 63;
1912 testParameters.height = 57;
1913 testParameters.depth = 67;
1914
1915 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1916 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1917
1918 wrapTGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(
1919 testCtx, name.c_str(), testParameters));
1920 }
1921 wrapSGroup->addChild(wrapTGroup.release());
1922 }
1923 magFilterGroup->addChild(wrapSGroup.release());
1924 }
1925 minFilterGroup->addChild(magFilterGroup.release());
1926 }
1927 combinationsGroup->addChild(minFilterGroup.release());
1928 }
1929
1930 group3D->addChild(formatsGroup.release());
1931 group3D->addChild(sizesGroup.release());
1932 group3D->addChild(combinationsGroup.release());
1933
1934 textureFilteringTests->addChild(group3D.release());
1935 }
1936 }
1937
createTextureFilteringTests(tcu::TestContext & testCtx)1938 tcu::TestCaseGroup *createTextureFilteringTests(tcu::TestContext &testCtx)
1939 {
1940 return createTestGroup(testCtx, "filtering", populateTextureFilteringTests);
1941 }
1942
1943 } // namespace texture
1944 } // namespace vkt
1945