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 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 Mipmapping tests.
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktTextureMipmapTests.hpp"
27
28 #include "deRandom.hpp"
29 #include "deString.h"
30 #include "gluShaderUtil.hpp"
31 #include "gluTextureTestUtil.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuMatrixUtil.hpp"
34 #include "tcuPixelFormat.hpp"
35 #include "tcuTexLookupVerifier.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuVectorUtil.hpp"
38 #include "tcuCommandLine.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkQueryUtil.hpp"
41 #include "vkImageWithMemory.hpp"
42 #include "vkBufferWithMemory.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkCmdUtil.hpp"
45 #include "vkBarrierUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vktTestGroupUtil.hpp"
48 #include "vktTextureTestUtil.hpp"
49 #include "vktCustomInstancesDevices.hpp"
50
51 #include <memory>
52
53 using namespace vk;
54
55 namespace vkt
56 {
57 namespace texture
58 {
59 namespace
60 {
61
62 using std::string;
63 using std::vector;
64 using tcu::IVec3;
65 using tcu::IVec4;
66 using tcu::Sampler;
67 using tcu::TestLog;
68 using tcu::TextureFormat;
69 using tcu::Vec2;
70 using tcu::Vec3;
71 using tcu::Vec4;
72 using namespace texture::util;
73 using namespace glu::TextureTestUtil;
74
getMinLodForCell(int cellNdx)75 float getMinLodForCell(int cellNdx)
76 {
77 static const float s_values[] = {1.0f, 3.5f, 2.0f, -2.0f, 0.0f, 3.0f, 10.0f, 4.8f,
78 5.8f, 5.7f, -1.9f, 4.0f, 6.5f, 7.1f, -1e10, 1000.f};
79 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
80 }
81
getMaxLodForCell(int cellNdx)82 float getMaxLodForCell(int cellNdx)
83 {
84 static const float s_values[] = {0.0f, 0.2f, 0.7f, 0.4f, 1.3f, 0.0f, 0.5f, 1.2f, -2.0f,
85 1.0f, 0.1f, 0.3f, 2.7f, 1.2f, 10.0f, -1000.f, 1e10f};
86 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
87 }
88
89 enum CoordType
90 {
91 COORDTYPE_BASIC, //!< texCoord = translateScale(position).
92 COORDTYPE_BASIC_BIAS, //!< Like basic, but with bias values.
93 COORDTYPE_AFFINE, //!< texCoord = translateScaleRotateShear(position).
94 COORDTYPE_PROJECTED, //!< Projected coordinates, w != 1
95
96 COORDTYPE_LAST
97 };
98
99 struct TextureMipmapCommonTestCaseParameters
100 {
101 TextureMipmapCommonTestCaseParameters(void);
102 CoordType coordType;
103 const char *minFilterName;
104 };
105
TextureMipmapCommonTestCaseParameters(void)106 TextureMipmapCommonTestCaseParameters::TextureMipmapCommonTestCaseParameters(void)
107 : coordType(COORDTYPE_BASIC)
108 , minFilterName(NULL)
109 {
110 }
111
112 struct Texture2DMipmapTestCaseParameters : public Texture2DTestCaseParameters,
113 public TextureMipmapCommonTestCaseParameters
114 {
115 };
116
117 struct TextureCubeMipmapTestCaseParameters : public TextureCubeTestCaseParameters,
118 public TextureMipmapCommonTestCaseParameters
119 {
120 };
121
122 struct Texture3DMipmapTestCaseParameters : public Texture3DTestCaseParameters,
123 public TextureMipmapCommonTestCaseParameters
124 {
125 };
126
127 // Texture2DMipmapTestInstance
128 class Texture2DMipmapTestInstance : public TestInstance
129 {
130 public:
131 typedef Texture2DMipmapTestCaseParameters ParameterType;
132
133 Texture2DMipmapTestInstance(Context &context, const ParameterType &testParameters);
134 ~Texture2DMipmapTestInstance(void);
135
136 virtual tcu::TestStatus iterate(void);
137
138 private:
139 Texture2DMipmapTestInstance(const Texture2DMipmapTestInstance &other);
140 Texture2DMipmapTestInstance &operator=(const Texture2DMipmapTestInstance &other);
141
142 const ParameterType m_testParameters;
143 TestTexture2DSp m_texture;
144 TextureRenderer m_renderer;
145 };
146
Texture2DMipmapTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)147 Texture2DMipmapTestInstance::Texture2DMipmapTestInstance(Context &context,
148 const Texture2DMipmapTestCaseParameters &testParameters)
149 : TestInstance(context)
150 , m_testParameters(testParameters)
151 , m_renderer(context, testParameters.sampleCount, testParameters.width * 4, testParameters.height * 4)
152 {
153 TCU_CHECK_INTERNAL(
154 !(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
155
156 m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format),
157 m_testParameters.width, m_testParameters.height));
158
159 const int numLevels = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1;
160
161 // Fill texture with colored grid.
162 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
163 {
164 const uint32_t step = 0xff / (numLevels - 1);
165 const uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
166 const uint32_t dec = 0xff - inc;
167 const uint32_t rgb = (inc << 16) | (dec << 8) | 0xff;
168 const uint32_t color = 0xff000000 | rgb;
169
170 tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
171 }
172
173 // Upload texture data.
174 m_renderer.add2DTexture(m_texture, testParameters.aspectMask);
175 }
176
~Texture2DMipmapTestInstance(void)177 Texture2DMipmapTestInstance::~Texture2DMipmapTestInstance(void)
178 {
179 }
180
getBasicTexCoord2D(std::vector<float> & dst,int cellNdx)181 static void getBasicTexCoord2D(std::vector<float> &dst, int cellNdx)
182 {
183 static const struct
184 {
185 const Vec2 bottomLeft;
186 const Vec2 topRight;
187 } s_basicCoords[] = {
188 {Vec2(-0.1f, 0.1f), Vec2(0.8f, 1.0f)}, {Vec2(-0.3f, -0.6f), Vec2(0.7f, 0.4f)},
189 {Vec2(-0.3f, 0.6f), Vec2(0.7f, -0.9f)}, {Vec2(-0.8f, 0.6f), Vec2(0.7f, -0.9f)},
190
191 {Vec2(-0.5f, -0.5f), Vec2(1.5f, 1.5f)}, {Vec2(1.0f, -1.0f), Vec2(-1.3f, 1.0f)},
192 {Vec2(1.2f, -1.0f), Vec2(-1.3f, 1.6f)}, {Vec2(2.2f, -1.1f), Vec2(-1.3f, 0.8f)},
193
194 {Vec2(-1.5f, 1.6f), Vec2(1.7f, -1.4f)}, {Vec2(2.0f, 1.6f), Vec2(2.3f, -1.4f)},
195 {Vec2(1.3f, -2.6f), Vec2(-2.7f, 2.9f)}, {Vec2(-0.8f, -6.6f), Vec2(6.0f, -0.9f)},
196
197 {Vec2(-8.0f, 9.0f), Vec2(8.3f, -7.0f)}, {Vec2(-16.0f, 10.0f), Vec2(18.3f, 24.0f)},
198 {Vec2(30.2f, 55.0f), Vec2(-24.3f, -1.6f)}, {Vec2(-33.2f, 64.1f), Vec2(32.1f, -64.1f)},
199 };
200
201 DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
202
203 const Vec2 &bottomLeft = s_basicCoords[cellNdx].bottomLeft;
204 const Vec2 &topRight = s_basicCoords[cellNdx].topRight;
205
206 computeQuadTexCoord2D(dst, bottomLeft, topRight);
207 }
208
getBasicTexCoord2DImageViewMinLodIntTexCoord(std::vector<float> & dst)209 static void getBasicTexCoord2DImageViewMinLodIntTexCoord(std::vector<float> &dst)
210 {
211 computeQuadTexCoord2D(dst, Vec2(0.0f), Vec2(1.0f));
212 }
213
getAffineTexCoord2D(std::vector<float> & dst,int cellNdx)214 static void getAffineTexCoord2D(std::vector<float> &dst, int cellNdx)
215 {
216 // Use basic coords as base.
217 getBasicTexCoord2D(dst, cellNdx);
218
219 // Rotate based on cell index.
220 const float angle = 2.0f * DE_PI * ((float)cellNdx / 16.0f);
221 const tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle);
222
223 // Second and third row are sheared.
224 const float shearX = de::inRange(cellNdx, 4, 11) ? (float)(15 - cellNdx) / 16.0f : 0.0f;
225 const tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
226
227 const tcu::Mat2 transform = rotMatrix * shearMatrix;
228 const Vec2 p0 = transform * Vec2(dst[0], dst[1]);
229 const Vec2 p1 = transform * Vec2(dst[2], dst[3]);
230 const Vec2 p2 = transform * Vec2(dst[4], dst[5]);
231 const Vec2 p3 = transform * Vec2(dst[6], dst[7]);
232
233 dst[0] = p0.x();
234 dst[1] = p0.y();
235 dst[2] = p1.x();
236 dst[3] = p1.y();
237 dst[4] = p2.x();
238 dst[5] = p2.y();
239 dst[6] = p3.x();
240 dst[7] = p3.y();
241 }
242
iterate(void)243 tcu::TestStatus Texture2DMipmapTestInstance::iterate(void)
244 {
245 const Sampler::FilterMode magFilter = Sampler::NEAREST;
246 const int viewportWidth = m_renderer.getRenderWidth();
247 const int viewportHeight = m_renderer.getRenderHeight();
248
249 ReferenceParams refParams(TEXTURETYPE_2D);
250 vector<float> texCoord;
251
252 const bool isProjected = m_testParameters.coordType == COORDTYPE_PROJECTED;
253 const bool useLodBias = m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
254
255 tcu::Surface renderedFrame(viewportWidth, viewportHeight);
256
257 // Viewport is divided into 4x4 grid.
258 const int gridWidth = 4;
259 const int gridHeight = 4;
260 const int cellWidth = viewportWidth / gridWidth;
261 const int cellHeight = viewportHeight / gridHeight;
262
263 // Sampling parameters.
264 refParams.sampler =
265 util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
266 refParams.samplerType = getSamplerType(vk::mapVkFormat(m_testParameters.format));
267 refParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
268 refParams.lodMode = LODMODE_EXACT; // Use ideal lod.
269
270 // Bias values.
271 static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
272
273 // Projection values.
274 static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 2.0f),
275 Vec4(0.8f, 1.0f, 1.7f, 0.6f), Vec4(1.2f, 1.0f, 1.7f, 1.5f)};
276
277 // Render cells.
278 for (int gridY = 0; gridY < gridHeight; gridY++)
279 {
280 for (int gridX = 0; gridX < gridWidth; gridX++)
281 {
282 const int curX = cellWidth * gridX;
283 const int curY = cellHeight * gridY;
284 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
285 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
286 const int cellNdx = gridY * gridWidth + gridX;
287
288 // Compute texcoord.
289 switch (m_testParameters.coordType)
290 {
291 case COORDTYPE_BASIC_BIAS: // Fall-through.
292 case COORDTYPE_PROJECTED:
293 case COORDTYPE_BASIC:
294 getBasicTexCoord2D(texCoord, cellNdx);
295 break;
296 case COORDTYPE_AFFINE:
297 getAffineTexCoord2D(texCoord, cellNdx);
298 break;
299 default:
300 DE_ASSERT(false);
301 }
302
303 if (isProjected)
304 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
305
306 if (useLodBias)
307 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
308
309 m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
310 m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
311 }
312 }
313
314 // Compare and log.
315 {
316 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
317 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
318 const bool isTrilinear = m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR ||
319 m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
320 tcu::Surface referenceFrame(viewportWidth, viewportHeight);
321 tcu::Surface errorMask(viewportWidth, viewportHeight);
322 tcu::LookupPrecision lookupPrec;
323 tcu::LodPrecision lodPrec;
324 int numFailedPixels = 0;
325
326 lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
327 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
328 lookupPrec.colorThreshold =
329 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
330 lookupPrec.colorMask = getCompareMask(pixelFormat);
331 lodPrec.derivateBits = 10;
332 lodPrec.lodBits = isProjected ? 6 : 8;
333
334 for (int gridY = 0; gridY < gridHeight; gridY++)
335 {
336 for (int gridX = 0; gridX < gridWidth; gridX++)
337 {
338 const int curX = cellWidth * gridX;
339 const int curY = cellHeight * gridY;
340 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
341 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
342 const int cellNdx = gridY * gridWidth + gridX;
343
344 // Compute texcoord.
345 switch (m_testParameters.coordType)
346 {
347 case COORDTYPE_BASIC_BIAS: // Fall-through.
348 case COORDTYPE_PROJECTED:
349 case COORDTYPE_BASIC:
350 getBasicTexCoord2D(texCoord, cellNdx);
351 break;
352 case COORDTYPE_AFFINE:
353 getAffineTexCoord2D(texCoord, cellNdx);
354 break;
355 default:
356 DE_ASSERT(false);
357 }
358
359 if (isProjected)
360 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
361
362 if (useLodBias)
363 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
364
365 // Render ideal result
366 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
367 m_texture->getTexture(), &texCoord[0], refParams);
368
369 // Compare this cell
370 numFailedPixels += computeTextureLookupDiff(
371 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
372 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
373 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
374 &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
375 }
376 }
377
378 if (numFailedPixels > 0)
379 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
380 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
381
382 m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
383 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
384
385 if (numFailedPixels > 0)
386 {
387 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
388 << TestLog::Image("ErrorMask", "Error mask", errorMask);
389 }
390
391 m_context.getTestContext().getLog() << TestLog::EndImageSet;
392
393 {
394 const bool isOk = numFailedPixels == 0;
395 return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
396 }
397 }
398 }
399
400 // TextureCubeMipmapTestInstance
401 class TextureCubeMipmapTestInstance : public TestInstance
402 {
403 public:
404 typedef TextureCubeMipmapTestCaseParameters ParameterType;
405
406 TextureCubeMipmapTestInstance(Context &context, const ParameterType &testParameters);
407 ~TextureCubeMipmapTestInstance(void);
408
409 virtual tcu::TestStatus iterate(void);
410
411 private:
412 TextureCubeMipmapTestInstance(const TextureCubeMipmapTestInstance &other);
413 TextureCubeMipmapTestInstance &operator=(const TextureCubeMipmapTestInstance &other);
414
415 const ParameterType m_testParameters;
416 TestTextureCubeSp m_texture;
417 TextureRenderer m_renderer;
418 };
419
TextureCubeMipmapTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)420 TextureCubeMipmapTestInstance::TextureCubeMipmapTestInstance(Context &context,
421 const TextureCubeMipmapTestCaseParameters &testParameters)
422 : TestInstance(context)
423 , m_testParameters(testParameters)
424 , m_renderer(context, m_testParameters.sampleCount, m_testParameters.size * 2, m_testParameters.size * 2)
425 {
426 TCU_CHECK_INTERNAL(
427 !(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
428
429 m_texture = TestTextureCubeSp(
430 new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size));
431
432 const int numLevels = deLog2Floor32(m_testParameters.size) + 1;
433
434 // Fill texture with colored grid.
435 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
436 {
437 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
438 {
439 const uint32_t step = 0xff / (numLevels - 1);
440 const uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
441 const uint32_t dec = 0xff - inc;
442 uint32_t rgb = 0;
443
444 switch (faceNdx)
445 {
446 case 0:
447 rgb = (inc << 16) | (dec << 8) | 255;
448 break;
449 case 1:
450 rgb = (255 << 16) | (inc << 8) | dec;
451 break;
452 case 2:
453 rgb = (dec << 16) | (255 << 8) | inc;
454 break;
455 case 3:
456 rgb = (dec << 16) | (inc << 8) | 255;
457 break;
458 case 4:
459 rgb = (255 << 16) | (dec << 8) | inc;
460 break;
461 case 5:
462 rgb = (inc << 16) | (255 << 8) | dec;
463 break;
464 }
465
466 const uint32_t color = 0xff000000 | rgb;
467 tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
468 }
469 }
470
471 m_renderer.addCubeTexture(m_texture, testParameters.aspectMask);
472 }
473
~TextureCubeMipmapTestInstance(void)474 TextureCubeMipmapTestInstance::~TextureCubeMipmapTestInstance(void)
475 {
476 }
477
randomPartition(vector<IVec4> & dst,de::Random & rnd,int x,int y,int width,int height)478 static void randomPartition(vector<IVec4> &dst, de::Random &rnd, int x, int y, int width, int height)
479 {
480 const int minWidth = 8;
481 const int minHeight = 8;
482
483 const bool partition = rnd.getFloat() > 0.4f;
484 const bool partitionX = partition && width > minWidth && rnd.getBool();
485 const bool partitionY = partition && height > minHeight && !partitionX;
486
487 if (partitionX)
488 {
489 const int split = width / 2 + rnd.getInt(-width / 4, +width / 4);
490 randomPartition(dst, rnd, x, y, split, height);
491 randomPartition(dst, rnd, x + split, y, width - split, height);
492 }
493 else if (partitionY)
494 {
495 const int split = height / 2 + rnd.getInt(-height / 4, +height / 4);
496 randomPartition(dst, rnd, x, y, width, split);
497 randomPartition(dst, rnd, x, y + split, width, height - split);
498 }
499 else
500 dst.push_back(IVec4(x, y, width, height));
501 }
502
computeGridLayout(vector<IVec4> & dst,int width,int height)503 static void computeGridLayout(vector<IVec4> &dst, int width, int height)
504 {
505 de::Random rnd(7);
506 randomPartition(dst, rnd, 0, 0, width, height);
507 }
508
iterate(void)509 tcu::TestStatus TextureCubeMipmapTestInstance::iterate(void)
510 {
511 const int viewportWidth = m_renderer.getRenderWidth();
512 const int viewportHeight = m_renderer.getRenderHeight();
513
514 const bool isProjected = m_testParameters.coordType == COORDTYPE_PROJECTED;
515 const bool useLodBias = m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
516
517 ReferenceParams refParams(TEXTURETYPE_CUBE);
518 vector<float> texCoord;
519 tcu::Surface renderedFrame(viewportWidth, viewportHeight);
520
521 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter,
522 m_testParameters.magFilter);
523 refParams.samplerType = getSamplerType(vk::mapVkFormat(m_testParameters.format));
524 refParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
525 refParams.lodMode = LODMODE_EXACT; // Use ideal lod.
526
527 // Compute grid.
528 vector<IVec4> gridLayout;
529 computeGridLayout(gridLayout, viewportWidth, viewportHeight);
530
531 // Bias values.
532 static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
533
534 // Projection values \note Less agressive than in 2D case due to smaller quads.
535 static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 1.1f),
536 Vec4(0.8f, 1.0f, 1.2f, 0.8f), Vec4(1.2f, 1.0f, 1.3f, 0.9f)};
537
538 // Render with GL
539 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
540 {
541 const float curX = (float)gridLayout[cellNdx].x();
542 const float curY = (float)gridLayout[cellNdx].y();
543 const float curW = (float)gridLayout[cellNdx].z();
544 const float curH = (float)gridLayout[cellNdx].w();
545 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
546
547 DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
548 computeQuadTexCoordCube(texCoord, cubeFace);
549
550 if (isProjected)
551 {
552 refParams.flags |= ReferenceParams::PROJECTED;
553 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
554 }
555
556 if (useLodBias)
557 {
558 refParams.flags |= ReferenceParams::USE_BIAS;
559 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
560 }
561
562 // Render
563 m_renderer.setViewport(curX, curY, curW, curH);
564 m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
565 }
566
567 // Render reference and compare
568 {
569 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
570 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
571 tcu::Surface referenceFrame(viewportWidth, viewportHeight);
572 tcu::Surface errorMask(viewportWidth, viewportHeight);
573 int numFailedPixels = 0;
574 tcu::LookupPrecision lookupPrec;
575 tcu::LodPrecision lodPrec;
576
577 // Params for rendering reference
578 refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT,
579 m_testParameters.minFilter, m_testParameters.magFilter);
580 refParams.sampler.seamlessCubeMap = true;
581 refParams.lodMode = LODMODE_EXACT;
582
583 // Comparison parameters
584 lookupPrec.colorMask = getCompareMask(pixelFormat);
585 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - 2, tcu::IVec4(0)));
586 lookupPrec.coordBits = isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
587 lookupPrec.uvwBits = tcu::IVec3(5, 5, 0);
588 lodPrec.derivateBits = 10;
589 lodPrec.lodBits = isProjected ? 3 : 6;
590
591 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
592 {
593 const int curX = gridLayout[cellNdx].x();
594 const int curY = gridLayout[cellNdx].y();
595 const int curW = gridLayout[cellNdx].z();
596 const int curH = gridLayout[cellNdx].w();
597 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
598
599 DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
600 computeQuadTexCoordCube(texCoord, cubeFace);
601
602 if (isProjected)
603 {
604 refParams.flags |= ReferenceParams::PROJECTED;
605 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
606 }
607
608 if (useLodBias)
609 {
610 refParams.flags |= ReferenceParams::USE_BIAS;
611 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
612 }
613
614 // Render ideal reference.
615 {
616 tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
617 sampleTexture(idealDst, m_texture->getTexture(), &texCoord[0], refParams);
618 }
619
620 // Compare this cell
621 numFailedPixels += computeTextureLookupDiff(
622 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
623 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
624 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(), &texCoord[0],
625 refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
626 }
627
628 if (numFailedPixels > 0)
629 {
630 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
631 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
632 }
633
634 m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
635 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
636
637 if (numFailedPixels > 0)
638 {
639 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
640 << TestLog::Image("ErrorMask", "Error mask", errorMask);
641 }
642
643 m_context.getTestContext().getLog() << TestLog::EndImageSet;
644
645 {
646 const bool isOk = numFailedPixels == 0;
647 return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
648 }
649 }
650 }
651
652 // Texture3DMipmapTestInstance
653 class Texture3DMipmapTestInstance : public TestInstance
654 {
655 public:
656 typedef Texture3DMipmapTestCaseParameters ParameterType;
657
658 Texture3DMipmapTestInstance(Context &context, const ParameterType &testParameters);
659 ~Texture3DMipmapTestInstance(void);
660
661 virtual tcu::TestStatus iterate(void);
662
663 private:
664 Texture3DMipmapTestInstance(const Texture3DMipmapTestInstance &other);
665 Texture3DMipmapTestInstance &operator=(const Texture3DMipmapTestInstance &other);
666
667 const ParameterType m_testParameters;
668 TestTexture3DSp m_texture;
669 TextureRenderer m_renderer;
670 };
671
Texture3DMipmapTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)672 Texture3DMipmapTestInstance::Texture3DMipmapTestInstance(Context &context,
673 const Texture3DMipmapTestCaseParameters &testParameters)
674 : TestInstance(context)
675 , m_testParameters(testParameters)
676 , m_renderer(context, testParameters.sampleCount, testParameters.width * 4, testParameters.height * 4)
677 {
678 TCU_CHECK_INTERNAL(
679 !(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
680
681 const tcu::TextureFormat &texFmt = mapVkFormat(testParameters.format);
682 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
683 const tcu::Vec4 &cScale = fmtInfo.lookupScale;
684 const tcu::Vec4 &cBias = fmtInfo.lookupBias;
685 const int numLevels =
686 deLog2Floor32(de::max(de::max(testParameters.width, testParameters.height), testParameters.depth)) + 1;
687
688 m_texture =
689 TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width,
690 m_testParameters.height, m_testParameters.depth));
691
692 // Fill texture with colored grid.
693 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
694 {
695 const uint32_t step = 0xff / (numLevels - 1);
696 const uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
697 const uint32_t dec = 0xff - inc;
698 const uint32_t rgb = (0xff << 16) | (dec << 8) | inc;
699 const uint32_t color = 0xff000000 | rgb;
700
701 tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec() * cScale + cBias);
702 }
703
704 m_renderer.add3DTexture(m_texture, testParameters.aspectMask);
705 }
706
~Texture3DMipmapTestInstance(void)707 Texture3DMipmapTestInstance::~Texture3DMipmapTestInstance(void)
708 {
709 }
710
getBasicTexCoord3D(std::vector<float> & dst,int cellNdx)711 static void getBasicTexCoord3D(std::vector<float> &dst, int cellNdx)
712 {
713 static const struct
714 {
715 const float sScale;
716 const float sBias;
717 const float tScale;
718 const float tBias;
719 const float rScale;
720 const float rBias;
721 } s_params[] = {// sScale sBias tScale tBias rScale rBias
722 {0.9f, -0.1f, 0.7f, 0.3f, 0.8f, 0.9f}, {1.2f, -0.1f, 1.1f, 0.3f, 1.0f, 0.9f},
723 {1.5f, 0.7f, 0.9f, -0.3f, 1.1f, 0.1f}, {1.2f, 0.7f, -2.3f, -0.3f, 1.1f, 0.2f},
724 {1.1f, 0.8f, -1.3f, -0.3f, 2.9f, 0.9f}, {3.4f, 0.8f, 4.0f, 0.0f, -3.3f, -1.0f},
725 {-3.4f, -0.1f, -4.0f, 0.0f, -5.1f, 1.0f}, {-4.0f, -0.1f, 3.4f, 0.1f, 5.7f, 0.0f},
726 {-5.6f, 0.0f, 0.5f, 1.2f, 3.9f, 4.0f}, {5.0f, -2.0f, 3.1f, 1.2f, 5.1f, 0.2f},
727 {2.5f, -2.0f, 6.3f, 3.0f, 5.1f, 0.2f}, {-8.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f},
728 {3.8f, 0.0f, 9.7f, 1.0f, 7.0f, 0.7f}, {13.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f},
729 {16.0f, 8.0f, 12.7f, 1.0f, 17.1f, 0.7f}, {15.3f, 0.0f, 20.1f, 3.0f, 33.0f, 3.2f}};
730
731 const float sScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].sScale;
732 const float sBias = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].sBias;
733 const float tScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].tScale;
734 const float tBias = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].tBias;
735 const float rScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].rScale;
736 const float rBias = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].rBias;
737
738 dst.resize(3 * 4);
739
740 dst[0] = sBias;
741 dst[1] = tBias;
742 dst[2] = rBias;
743 dst[3] = sBias;
744 dst[4] = tBias + tScale;
745 dst[5] = rBias + rScale * 0.5f;
746 dst[6] = sBias + sScale;
747 dst[7] = tBias;
748 dst[8] = rBias + rScale * 0.5f;
749 dst[9] = sBias + sScale;
750 dst[10] = tBias + tScale;
751 dst[11] = rBias + rScale;
752 }
753
getBasicTexCoord3DImageViewMinlodIntTexCoord(std::vector<float> & dst)754 static void getBasicTexCoord3DImageViewMinlodIntTexCoord(std::vector<float> &dst)
755 {
756 const float sScale = 1.0f;
757 const float sBias = 0.0f;
758 const float tScale = 1.0f;
759 const float tBias = 0.0f;
760 const float rScale = 1.0f;
761 const float rBias = 0.0f;
762
763 dst.resize(3 * 4);
764
765 dst[0] = sBias;
766 dst[1] = tBias;
767 dst[2] = rBias;
768 dst[3] = sBias;
769 dst[4] = tBias + tScale;
770 dst[5] = rBias + rScale * 0.5f;
771 dst[6] = sBias + sScale;
772 dst[7] = tBias;
773 dst[8] = rBias + rScale * 0.5f;
774 dst[9] = sBias + sScale;
775 dst[10] = tBias + tScale;
776 dst[11] = rBias + rScale;
777 }
778
getAffineTexCoord3D(std::vector<float> & dst,int cellNdx)779 static void getAffineTexCoord3D(std::vector<float> &dst, int cellNdx)
780 {
781 // Use basic coords as base.
782 getBasicTexCoord3D(dst, cellNdx);
783
784 // Rotate based on cell index.
785 const float angleX = 0.0f + 2.0f * DE_PI * ((float)cellNdx / 16.0f);
786 const float angleY = 1.0f + 2.0f * DE_PI * ((float)cellNdx / 32.0f);
787 const tcu::Mat3 rotMatrix = tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY);
788
789 const Vec3 p0 = rotMatrix * Vec3(dst[0], dst[1], dst[2]);
790 const Vec3 p1 = rotMatrix * Vec3(dst[3], dst[4], dst[5]);
791 const Vec3 p2 = rotMatrix * Vec3(dst[6], dst[7], dst[8]);
792 const Vec3 p3 = rotMatrix * Vec3(dst[9], dst[10], dst[11]);
793
794 dst[0] = p0.x();
795 dst[1] = p0.y();
796 dst[2] = p0.z();
797 dst[3] = p1.x();
798 dst[4] = p1.y();
799 dst[5] = p1.z();
800 dst[6] = p2.x();
801 dst[7] = p2.y();
802 dst[8] = p2.z();
803 dst[9] = p3.x();
804 dst[10] = p3.y();
805 dst[11] = p3.z();
806 }
807
iterate(void)808 tcu::TestStatus Texture3DMipmapTestInstance::iterate(void)
809 {
810 const tcu::TextureFormat &texFmt = m_texture->getTextureFormat();
811 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
812 const Sampler::FilterMode magFilter = Sampler::NEAREST;
813 const int viewportWidth = m_renderer.getRenderWidth();
814 const int viewportHeight = m_renderer.getRenderHeight();
815
816 const bool isProjected = m_testParameters.coordType == COORDTYPE_PROJECTED;
817 const bool useLodBias = m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
818
819 // Viewport is divided into 4x4 grid.
820 const int gridWidth = 4;
821 const int gridHeight = 4;
822 const int cellWidth = viewportWidth / gridWidth;
823 const int cellHeight = viewportHeight / gridHeight;
824
825 ReferenceParams refParams(TEXTURETYPE_3D);
826
827 tcu::Surface renderedFrame(viewportWidth, viewportHeight);
828 vector<float> texCoord;
829
830 // Sampling parameters.
831 refParams.sampler =
832 util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
833 refParams.samplerType = getSamplerType(texFmt);
834
835 refParams.colorBias = fmtInfo.lookupBias;
836 refParams.colorScale = fmtInfo.lookupScale;
837 refParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
838
839 // Bias values.
840 static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
841
842 // Projection values.
843 static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 2.0f),
844 Vec4(0.8f, 1.0f, 1.7f, 0.6f), Vec4(1.2f, 1.0f, 1.7f, 1.5f)};
845
846 // Render cells.
847 for (int gridY = 0; gridY < gridHeight; gridY++)
848 {
849 for (int gridX = 0; gridX < gridWidth; gridX++)
850 {
851 const int curX = cellWidth * gridX;
852 const int curY = cellHeight * gridY;
853 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
854 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
855 const int cellNdx = gridY * gridWidth + gridX;
856
857 // Compute texcoord.
858 switch (m_testParameters.coordType)
859 {
860 case COORDTYPE_BASIC_BIAS: // Fall-through.
861 case COORDTYPE_PROJECTED:
862 case COORDTYPE_BASIC:
863 getBasicTexCoord3D(texCoord, cellNdx);
864 break;
865 case COORDTYPE_AFFINE:
866 getAffineTexCoord3D(texCoord, cellNdx);
867 break;
868 default:
869 DE_ASSERT(false);
870 }
871
872 // Set projection.
873 if (isProjected)
874 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
875
876 // Set LOD bias.
877 if (useLodBias)
878 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
879
880 m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
881 m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
882 }
883 }
884
885 // Compare and log
886 {
887 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
888 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
889 const bool isTrilinear = m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR ||
890 m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
891 tcu::Surface referenceFrame(viewportWidth, viewportHeight);
892 tcu::Surface errorMask(viewportWidth, viewportHeight);
893 tcu::LookupPrecision lookupPrec;
894 tcu::LodPrecision lodPrec;
895 int numFailedPixels = 0;
896
897 lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
898 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
899 lookupPrec.colorThreshold =
900 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
901 lookupPrec.colorMask = getCompareMask(pixelFormat);
902 lodPrec.derivateBits = 10;
903 lodPrec.lodBits = isProjected ? 6 : 8;
904
905 for (int gridY = 0; gridY < gridHeight; gridY++)
906 {
907 for (int gridX = 0; gridX < gridWidth; gridX++)
908 {
909 const int curX = cellWidth * gridX;
910 const int curY = cellHeight * gridY;
911 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
912 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
913 const int cellNdx = gridY * gridWidth + gridX;
914
915 switch (m_testParameters.coordType)
916 {
917 case COORDTYPE_BASIC_BIAS: // Fall-through.
918 case COORDTYPE_PROJECTED:
919 case COORDTYPE_BASIC:
920 getBasicTexCoord3D(texCoord, cellNdx);
921 break;
922 case COORDTYPE_AFFINE:
923 getAffineTexCoord3D(texCoord, cellNdx);
924 break;
925 default:
926 DE_ASSERT(false);
927 }
928
929 if (isProjected)
930 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
931
932 if (useLodBias)
933 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
934
935 // Render ideal result
936 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
937 m_texture->getTexture(), &texCoord[0], refParams);
938
939 // Compare this cell
940 numFailedPixels += computeTextureLookupDiff(
941 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
942 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
943 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
944 &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
945 }
946 }
947
948 if (numFailedPixels > 0)
949 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
950 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
951
952 m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
953 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
954
955 if (numFailedPixels > 0)
956 {
957 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
958 << TestLog::Image("ErrorMask", "Error mask", errorMask);
959 }
960
961 m_context.getTestContext().getLog() << TestLog::EndImageSet;
962
963 {
964 const bool isOk = numFailedPixels == 0;
965 return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
966 }
967 }
968 }
969
970 // Texture2DLodControlTestInstance
971 class Texture2DLodControlTestInstance : public TestInstance
972 {
973 public:
974 typedef Texture2DMipmapTestCaseParameters ParameterType;
975
976 Texture2DLodControlTestInstance(Context &context, const ParameterType &testParameters);
977 ~Texture2DLodControlTestInstance(void);
978
979 virtual tcu::TestStatus iterate(void);
980
981 protected:
982 virtual void getReferenceParams(ReferenceParams ¶ms, int cellNdx) = 0;
983
984 const int m_texWidth;
985 const int m_texHeight;
986
987 private:
988 Texture2DLodControlTestInstance(const Texture2DLodControlTestInstance &other);
989 Texture2DLodControlTestInstance &operator=(const Texture2DLodControlTestInstance &other);
990
991 const ParameterType m_testParameters;
992 tcu::Sampler::FilterMode m_minFilter;
993 TestTexture2DSp m_texture;
994 TextureRenderer m_renderer;
995 };
996
Texture2DLodControlTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)997 Texture2DLodControlTestInstance::Texture2DLodControlTestInstance(
998 Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
999 : TestInstance(context)
1000 , m_texWidth(64) //64
1001 , m_texHeight(64) //64
1002 , m_testParameters(testParameters)
1003 , m_minFilter(testParameters.minFilter)
1004 , m_texture(DE_NULL)
1005 , m_renderer(context, testParameters.sampleCount, m_texWidth * 4, m_texHeight * 4, vk::makeComponentMappingRGBA(),
1006 testParameters.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD,
1007 testParameters.testType >= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD)
1008 {
1009 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1010 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1011
1012 m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(format), m_texWidth, m_texHeight));
1013
1014 // Fill texture with colored grid.
1015 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1016 {
1017 const uint32_t step = 0xff / (numLevels - 1);
1018 const uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
1019 const uint32_t dec = 0xff - inc;
1020 const uint32_t rgb = (inc << 16) | (dec << 8) | 0xff;
1021 const uint32_t color = 0xff000000 | rgb;
1022
1023 tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
1024 }
1025
1026 m_renderer.add2DTexture(m_texture, testParameters.aspectMask);
1027 }
1028
~Texture2DLodControlTestInstance(void)1029 Texture2DLodControlTestInstance::~Texture2DLodControlTestInstance(void)
1030 {
1031 }
1032
iterate(void)1033 tcu::TestStatus Texture2DLodControlTestInstance::iterate(void)
1034 {
1035 const tcu::Sampler::WrapMode wrapS = Sampler::REPEAT_GL;
1036 const tcu::Sampler::WrapMode wrapT = Sampler::REPEAT_GL;
1037 const tcu::Sampler::FilterMode magFilter = Sampler::NEAREST;
1038
1039 const tcu::Texture2D &refTexture = m_texture->getTexture();
1040
1041 const int viewportWidth = m_renderer.getRenderWidth();
1042 const int viewportHeight = m_renderer.getRenderHeight();
1043
1044 tcu::Sampler sampler = util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1045
1046 ReferenceParams refParams(TEXTURETYPE_2D, sampler);
1047 vector<float> texCoord;
1048 tcu::Surface renderedFrame(viewportWidth, viewportHeight);
1049
1050 // Viewport is divided into 4x4 grid.
1051 const int gridWidth = 4;
1052 const int gridHeight = 4;
1053 const int cellWidth = viewportWidth / gridWidth;
1054 const int cellHeight = viewportHeight / gridHeight;
1055
1056 refParams.maxLevel = deLog2Floor32(de::max(m_texWidth, m_texHeight));
1057
1058 // Render cells.
1059 for (int gridY = 0; gridY < gridHeight; gridY++)
1060 {
1061 for (int gridX = 0; gridX < gridWidth; gridX++)
1062 {
1063 const int curX = cellWidth * gridX;
1064 const int curY = cellHeight * gridY;
1065 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1066 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1067 const int cellNdx = gridY * gridWidth + gridX;
1068
1069 getReferenceParams(refParams, cellNdx);
1070
1071 // Compute texcoord.
1072 getBasicTexCoord2D(texCoord, cellNdx);
1073 // Render
1074 m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1075 m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel,
1076 refParams.imageViewMinLod);
1077 m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1078 }
1079 }
1080
1081 // Compare and log.
1082 {
1083 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1084 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1085 const bool isTrilinear =
1086 m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1087 tcu::LookupPrecision lookupPrec;
1088 tcu::LodPrecision lodPrec;
1089
1090 lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
1091 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
1092 lookupPrec.colorThreshold =
1093 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1094 lookupPrec.colorMask = getCompareMask(pixelFormat);
1095 lodPrec.derivateBits = 10;
1096 lodPrec.lodBits = 8;
1097
1098 auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1099 {
1100 tcu::Surface referenceFrame(viewportWidth, viewportHeight);
1101 tcu::Surface errorMask(viewportWidth, viewportHeight);
1102
1103 int numFailedPixels = 0;
1104
1105 for (int gridY = 0; gridY < gridHeight; gridY++)
1106 {
1107 for (int gridX = 0; gridX < gridWidth; gridX++)
1108 {
1109 const int curX = cellWidth * gridX;
1110 const int curY = cellHeight * gridY;
1111 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1112 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1113 const int cellNdx = gridY * gridWidth + gridX;
1114
1115 getReferenceParams(refParams, cellNdx);
1116
1117 refParams.imageViewMinLodMode = imageViewLodMode;
1118
1119 // Compute texcoord.
1120 if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
1121 getBasicTexCoord2DImageViewMinLodIntTexCoord(texCoord);
1122 else
1123 getBasicTexCoord2D(texCoord, cellNdx);
1124
1125 // Render ideal result
1126 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
1127 &texCoord[0], refParams);
1128
1129 // Compare this cell
1130 numFailedPixels += computeTextureLookupDiff(
1131 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1132 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1133 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
1134 &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1135 }
1136 }
1137
1138 if (numFailedPixels > 0)
1139 {
1140 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1141 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1142 }
1143 return numFailedPixels;
1144 };
1145
1146 m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1147 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1148
1149 int numFailedPixels = compareAndLogImages();
1150
1151 if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1152 {
1153 numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1154 }
1155 m_context.getTestContext().getLog() << TestLog::EndImageSet;
1156
1157 if (numFailedPixels > 0)
1158 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
1159 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1160
1161 {
1162 const bool isOk = numFailedPixels == 0;
1163 return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1164 }
1165 }
1166 }
1167
1168 class Texture2DMinLodTestInstance : public Texture2DLodControlTestInstance
1169 {
1170 public:
Texture2DMinLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1171 Texture2DMinLodTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1172 : Texture2DLodControlTestInstance(context, testParameters)
1173 {
1174 }
1175
1176 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1177 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1178 {
1179 params.minLod = getMinLodForCell(cellNdx);
1180 }
1181 };
1182
1183 class Texture2DMaxLodTestInstance : public Texture2DLodControlTestInstance
1184 {
1185 public:
Texture2DMaxLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1186 Texture2DMaxLodTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1187 : Texture2DLodControlTestInstance(context, testParameters)
1188 {
1189 }
1190
1191 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1192 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1193 {
1194 params.maxLod = getMaxLodForCell(cellNdx);
1195 }
1196 };
1197
1198 class Texture2DBaseLevelTestInstance : public Texture2DLodControlTestInstance
1199 {
1200 public:
Texture2DBaseLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1201 Texture2DBaseLevelTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1202 : Texture2DLodControlTestInstance(context, testParameters)
1203 , m_testParam(testParameters)
1204 {
1205 }
1206
1207 protected:
1208 const Texture2DMipmapTestCaseParameters m_testParam;
1209
getBaseLevel(int cellNdx) const1210 int getBaseLevel(int cellNdx) const
1211 {
1212 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1213 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
1214
1215 return baseLevel;
1216 }
1217
getReferenceParams(ReferenceParams & params,int cellNdx)1218 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1219 {
1220 params.baseLevel = getBaseLevel(cellNdx);
1221 }
1222 };
1223
1224 class Texture2DMaxLevelTestInstance : public Texture2DLodControlTestInstance
1225 {
1226 public:
Texture2DMaxLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1227 Texture2DMaxLevelTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1228 : Texture2DLodControlTestInstance(context, testParameters)
1229 , m_testParam(testParameters)
1230 {
1231 }
1232
1233 protected:
1234 const Texture2DMipmapTestCaseParameters m_testParam;
1235
getMaxLevel(int cellNdx) const1236 int getMaxLevel(int cellNdx) const
1237 {
1238 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1239 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x82cfa4e) % numLevels;
1240
1241 return maxLevel;
1242 }
1243
getReferenceParams(ReferenceParams & params,int cellNdx)1244 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1245 {
1246 params.maxLevel = getMaxLevel(cellNdx);
1247 }
1248 };
1249
1250 // TextureCubeLodControlTestInstance
1251 class TextureCubeLodControlTestInstance : public TestInstance
1252 {
1253 public:
1254 typedef TextureCubeMipmapTestCaseParameters ParameterType;
1255
1256 TextureCubeLodControlTestInstance(Context &context, const ParameterType &testParameters);
1257 ~TextureCubeLodControlTestInstance(void);
1258
1259 virtual tcu::TestStatus iterate(void);
1260
1261 protected:
1262 virtual void getReferenceParams(ReferenceParams ¶ms, int cellNdx) = DE_NULL;
1263
1264 const int m_texSize;
1265
1266 private:
1267 TextureCubeLodControlTestInstance(const TextureCubeLodControlTestInstance &other);
1268 TextureCubeLodControlTestInstance &operator=(const TextureCubeLodControlTestInstance &other);
1269
1270 const ParameterType m_testParameters;
1271 tcu::Sampler::FilterMode m_minFilter;
1272 TestTextureCubeSp m_texture;
1273 TextureRenderer m_renderer;
1274 };
1275
TextureCubeLodControlTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1276 TextureCubeLodControlTestInstance::TextureCubeLodControlTestInstance(
1277 Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1278 : TestInstance(context)
1279 , m_texSize(64)
1280 , m_testParameters(testParameters)
1281 , m_minFilter(testParameters.minFilter)
1282 , m_texture(DE_NULL)
1283
1284 , m_renderer(context, testParameters.sampleCount, m_texSize * 2, m_texSize * 2)
1285 {
1286 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1287 const int numLevels = deLog2Floor32(m_texSize) + 1;
1288
1289 m_texture = TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(format), m_texSize));
1290
1291 // Fill texture with colored grid.
1292 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1293 {
1294 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1295 {
1296 const uint32_t step = 0xff / (numLevels - 1);
1297 const uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
1298 const uint32_t dec = 0xff - inc;
1299 uint32_t rgb = 0;
1300
1301 switch (faceNdx)
1302 {
1303 case 0:
1304 rgb = (inc << 16) | (dec << 8) | 255;
1305 break;
1306 case 1:
1307 rgb = (255 << 16) | (inc << 8) | dec;
1308 break;
1309 case 2:
1310 rgb = (dec << 16) | (255 << 8) | inc;
1311 break;
1312 case 3:
1313 rgb = (dec << 16) | (inc << 8) | 255;
1314 break;
1315 case 4:
1316 rgb = (255 << 16) | (dec << 8) | inc;
1317 break;
1318 case 5:
1319 rgb = (inc << 16) | (255 << 8) | dec;
1320 break;
1321 }
1322
1323 const uint32_t color = 0xff000000 | rgb;
1324
1325 tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
1326 }
1327 }
1328
1329 m_renderer.addCubeTexture(m_texture, testParameters.aspectMask);
1330 }
1331
~TextureCubeLodControlTestInstance(void)1332 TextureCubeLodControlTestInstance::~TextureCubeLodControlTestInstance(void)
1333 {
1334 }
1335
iterate(void)1336 tcu::TestStatus TextureCubeLodControlTestInstance::iterate(void)
1337 {
1338 const tcu::Sampler::WrapMode wrapS = Sampler::CLAMP_TO_EDGE;
1339 const tcu::Sampler::WrapMode wrapT = Sampler::CLAMP_TO_EDGE;
1340 const tcu::Sampler::FilterMode magFilter = Sampler::NEAREST;
1341
1342 const tcu::TextureCube &refTexture = m_texture->getTexture();
1343 const int viewportWidth = m_renderer.getRenderWidth();
1344 const int viewportHeight = m_renderer.getRenderHeight();
1345
1346 tcu::Sampler sampler = util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1347 ReferenceParams refParams(TEXTURETYPE_CUBE, sampler);
1348 vector<float> texCoord;
1349 tcu::Surface renderedFrame(viewportWidth, viewportHeight);
1350
1351 refParams.maxLevel = deLog2Floor32(m_texSize);
1352
1353 // Compute grid.
1354 vector<tcu::IVec4> gridLayout;
1355 computeGridLayout(gridLayout, viewportWidth, viewportHeight);
1356
1357 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1358 {
1359 const int curX = gridLayout[cellNdx].x();
1360 const int curY = gridLayout[cellNdx].y();
1361 const int curW = gridLayout[cellNdx].z();
1362 const int curH = gridLayout[cellNdx].w();
1363 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1364
1365 computeQuadTexCoordCube(texCoord, cubeFace);
1366 getReferenceParams(refParams, cellNdx);
1367
1368 // Render with GL.
1369 m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1370 m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel,
1371 refParams.imageViewMinLod);
1372 m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1373 }
1374
1375 // Render reference and compare
1376 {
1377 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1378 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1379 tcu::LookupPrecision lookupPrec;
1380 tcu::LodPrecision lodPrec;
1381
1382 // Params for rendering reference
1383 refParams.sampler = util::createSampler(wrapS, wrapT, m_testParameters.minFilter, magFilter);
1384 refParams.sampler.seamlessCubeMap = true;
1385 refParams.lodMode = LODMODE_EXACT;
1386
1387 // Comparison parameters
1388 lookupPrec.colorMask = getCompareMask(pixelFormat);
1389 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - 2, IVec4(0)));
1390 lookupPrec.coordBits = tcu::IVec3(10);
1391 lookupPrec.uvwBits = tcu::IVec3(5, 5, 0);
1392 lodPrec.derivateBits = 10;
1393 lodPrec.lodBits = 6;
1394
1395 auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1396 {
1397 tcu::Surface referenceFrame(viewportWidth, viewportHeight);
1398 tcu::Surface errorMask(viewportWidth, viewportHeight);
1399 int numFailedPixels = 0;
1400
1401 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1402 {
1403 const int curX = gridLayout[cellNdx].x();
1404 const int curY = gridLayout[cellNdx].y();
1405 const int curW = gridLayout[cellNdx].z();
1406 const int curH = gridLayout[cellNdx].w();
1407 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1408
1409 computeQuadTexCoordCube(texCoord, cubeFace);
1410 getReferenceParams(refParams, cellNdx);
1411
1412 refParams.imageViewMinLodMode = imageViewLodMode;
1413
1414 // Render ideal reference.
1415 {
1416 tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
1417 sampleTexture(idealDst, refTexture, &texCoord[0], refParams);
1418 }
1419
1420 // Compare this cell
1421 numFailedPixels += computeTextureLookupDiff(
1422 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1423 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1424 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
1425 &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1426 }
1427 if (numFailedPixels > 0)
1428 {
1429 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1430 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1431 }
1432 return numFailedPixels;
1433 };
1434
1435 m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1436 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1437
1438 int numFailedPixels = compareAndLogImages();
1439
1440 if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1441 {
1442 numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1443 }
1444 m_context.getTestContext().getLog() << TestLog::EndImageSet;
1445
1446 if (numFailedPixels > 0)
1447 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
1448 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1449
1450 {
1451 const bool isOk = numFailedPixels == 0;
1452 return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1453 }
1454 }
1455 }
1456
1457 class TextureCubeMinLodTestInstance : public TextureCubeLodControlTestInstance
1458 {
1459 public:
TextureCubeMinLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1460 TextureCubeMinLodTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1461 : TextureCubeLodControlTestInstance(context, testParameters)
1462 {
1463 }
1464
1465 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1466 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1467 {
1468 params.minLod = getMinLodForCell(cellNdx);
1469 }
1470 };
1471
1472 class TextureCubeMaxLodTestInstance : public TextureCubeLodControlTestInstance
1473 {
1474 public:
TextureCubeMaxLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1475 TextureCubeMaxLodTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1476 : TextureCubeLodControlTestInstance(context, testParameters)
1477 {
1478 }
1479
1480 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1481 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1482 {
1483 params.maxLod = getMaxLodForCell(cellNdx);
1484 }
1485 };
1486
1487 class TextureCubeBaseLevelTestInstance : public TextureCubeLodControlTestInstance
1488 {
1489 public:
TextureCubeBaseLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1490 TextureCubeBaseLevelTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1491 : TextureCubeLodControlTestInstance(context, testParameters)
1492 , m_testParam(testParameters)
1493 {
1494 }
1495
1496 protected:
1497 const TextureCubeMipmapTestCaseParameters m_testParam;
1498
getBaseLevel(int cellNdx) const1499 int getBaseLevel(int cellNdx) const
1500 {
1501 const int numLevels = deLog2Floor32(m_texSize) + 1;
1502 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x23fae13) % numLevels;
1503
1504 return baseLevel;
1505 }
1506
getReferenceParams(ReferenceParams & params,int cellNdx)1507 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1508 {
1509 params.baseLevel = getBaseLevel(cellNdx);
1510 }
1511 };
1512
1513 class TextureCubeMaxLevelTestInstance : public TextureCubeLodControlTestInstance
1514 {
1515 public:
TextureCubeMaxLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1516 TextureCubeMaxLevelTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1517 : TextureCubeLodControlTestInstance(context, testParameters)
1518 , m_testParam(testParameters)
1519 {
1520 }
1521
1522 protected:
1523 const TextureCubeMipmapTestCaseParameters m_testParam;
getMaxLevel(int cellNdx) const1524 int getMaxLevel(int cellNdx) const
1525 {
1526 const int numLevels = deLog2Floor32(m_texSize) + 1;
1527 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x974e21) % numLevels;
1528
1529 return maxLevel;
1530 }
1531
getReferenceParams(ReferenceParams & params,int cellNdx)1532 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1533 {
1534 params.maxLevel = getMaxLevel(cellNdx);
1535 }
1536 };
1537
1538 // Texture3DLodControlTestInstance
1539 class Texture3DLodControlTestInstance : public TestInstance
1540 {
1541 public:
1542 typedef Texture3DMipmapTestCaseParameters ParameterType;
1543
1544 Texture3DLodControlTestInstance(Context &context, const ParameterType &testParameters);
1545 ~Texture3DLodControlTestInstance(void);
1546
1547 virtual tcu::TestStatus iterate(void);
1548
1549 protected:
1550 virtual void getReferenceParams(ReferenceParams ¶ms, int cellNdx) = DE_NULL;
1551
1552 const int m_texWidth;
1553 const int m_texHeight;
1554 const int m_texDepth;
1555
1556 private:
1557 Texture3DLodControlTestInstance(const Texture3DLodControlTestInstance &other);
1558 Texture3DLodControlTestInstance &operator=(const Texture3DLodControlTestInstance &other);
1559
1560 const ParameterType m_testParameters;
1561 tcu::Sampler::FilterMode m_minFilter;
1562 TestTexture3DSp m_texture;
1563 TextureRenderer m_renderer;
1564 };
1565
Texture3DLodControlTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1566 Texture3DLodControlTestInstance::Texture3DLodControlTestInstance(
1567 Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1568 : TestInstance(context)
1569 , m_texWidth(32)
1570 , m_texHeight(32)
1571 , m_texDepth(32)
1572 , m_testParameters(testParameters)
1573 , m_minFilter(testParameters.minFilter)
1574 , m_texture(DE_NULL)
1575 , m_renderer(context, testParameters.sampleCount, m_texWidth * 4, m_texHeight * 4, vk::makeComponentMappingRGBA(),
1576 testParameters.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD,
1577 testParameters.testType >= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD)
1578 {
1579 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1580 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(mapVkFormat(format));
1581 const tcu::Vec4 &cScale = fmtInfo.lookupScale;
1582 const tcu::Vec4 &cBias = fmtInfo.lookupBias;
1583 const int numLevels = deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth)) + 1;
1584
1585 m_texture =
1586 TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(format), m_texWidth, m_texHeight, m_texDepth));
1587
1588 // Fill texture with colored grid.
1589 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1590 {
1591 const uint32_t step = 0xff / (numLevels - 1);
1592 const uint32_t inc = deClamp32(step * levelNdx, 0x00, 0xff);
1593 const uint32_t dec = 0xff - inc;
1594 const uint32_t rgb = (inc << 16) | (dec << 8) | 0xff;
1595 const uint32_t color = 0xff000000 | rgb;
1596
1597 tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec() * cScale + cBias);
1598 }
1599
1600 m_renderer.add3DTexture(m_texture, testParameters.aspectMask);
1601 }
1602
~Texture3DLodControlTestInstance(void)1603 Texture3DLodControlTestInstance::~Texture3DLodControlTestInstance(void)
1604 {
1605 }
1606
iterate(void)1607 tcu::TestStatus Texture3DLodControlTestInstance::iterate(void)
1608 {
1609 const tcu::Sampler::WrapMode wrapS = Sampler::CLAMP_TO_EDGE;
1610 const tcu::Sampler::WrapMode wrapT = Sampler::CLAMP_TO_EDGE;
1611 const tcu::Sampler::WrapMode wrapR = Sampler::CLAMP_TO_EDGE;
1612 const tcu::Sampler::FilterMode magFilter = Sampler::NEAREST;
1613
1614 const tcu::Texture3D &refTexture = m_texture->getTexture();
1615 const tcu::TextureFormat &texFmt = refTexture.getFormat();
1616 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
1617 const int viewportWidth = m_renderer.getRenderWidth();
1618 const int viewportHeight = m_renderer.getRenderHeight();
1619
1620 tcu::Sampler sampler = util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1621 ReferenceParams refParams(TEXTURETYPE_3D, sampler);
1622 vector<float> texCoord;
1623 tcu::Surface renderedFrame(viewportWidth, viewportHeight);
1624
1625 // Viewport is divided into 4x4 grid.
1626 const int gridWidth = 4;
1627 const int gridHeight = 4;
1628 const int cellWidth = viewportWidth / gridWidth;
1629 const int cellHeight = viewportHeight / gridHeight;
1630
1631 // Sampling parameters.
1632 refParams.sampler = util::createSampler(wrapS, wrapT, wrapR, m_testParameters.minFilter, magFilter);
1633 refParams.samplerType = getSamplerType(texFmt);
1634 refParams.colorBias = fmtInfo.lookupBias;
1635 refParams.colorScale = fmtInfo.lookupScale;
1636 refParams.maxLevel = deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth));
1637
1638 // Render cells.
1639 for (int gridY = 0; gridY < gridHeight; gridY++)
1640 {
1641 for (int gridX = 0; gridX < gridWidth; gridX++)
1642 {
1643 const int curX = cellWidth * gridX;
1644 const int curY = cellHeight * gridY;
1645 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1646 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1647 const int cellNdx = gridY * gridWidth + gridX;
1648
1649 // Compute texcoord.
1650 getBasicTexCoord3D(texCoord, cellNdx);
1651
1652 getReferenceParams(refParams, cellNdx);
1653 //Render
1654 m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1655 m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel,
1656 refParams.imageViewMinLod);
1657 m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1658 }
1659 }
1660
1661 // Compare and log
1662 {
1663 const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1664 const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1665 const bool isTrilinear =
1666 m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1667 tcu::LookupPrecision lookupPrec;
1668 tcu::LodPrecision lodPrec;
1669
1670 lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
1671 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
1672 lookupPrec.colorThreshold =
1673 tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1674 lookupPrec.colorMask = getCompareMask(pixelFormat);
1675 lodPrec.derivateBits = 10;
1676 lodPrec.lodBits = 8;
1677
1678 auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1679 {
1680 tcu::Surface referenceFrame(viewportWidth, viewportHeight);
1681 tcu::Surface errorMask(viewportWidth, viewportHeight);
1682 int numFailedPixels = 0;
1683
1684 for (int gridY = 0; gridY < gridHeight; gridY++)
1685 {
1686 for (int gridX = 0; gridX < gridWidth; gridX++)
1687 {
1688 const int curX = cellWidth * gridX;
1689 const int curY = cellHeight * gridY;
1690 const int curW = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1691 const int curH = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1692 const int cellNdx = gridY * gridWidth + gridX;
1693
1694 getReferenceParams(refParams, cellNdx);
1695
1696 refParams.imageViewMinLodMode = imageViewLodMode;
1697
1698 // Compute texcoord.
1699 if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
1700 getBasicTexCoord3DImageViewMinlodIntTexCoord(texCoord);
1701 else
1702 getBasicTexCoord3D(texCoord, cellNdx);
1703
1704 // Render ideal result
1705 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
1706 &texCoord[0], refParams);
1707
1708 // Compare this cell
1709 numFailedPixels += computeTextureLookupDiff(
1710 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1711 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1712 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
1713 &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1714 }
1715 }
1716 if (numFailedPixels > 0)
1717 {
1718 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1719 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1720 }
1721
1722 return numFailedPixels;
1723 };
1724
1725 m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1726 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1727
1728 int numFailedPixels = compareAndLogImages();
1729
1730 if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1731 {
1732 numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1733 }
1734 m_context.getTestContext().getLog() << TestLog::EndImageSet;
1735
1736 if (numFailedPixels > 0)
1737 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
1738 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1739
1740 {
1741 const bool isOk = numFailedPixels == 0;
1742 return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1743 }
1744 }
1745 }
1746
1747 class Texture3DMinLodTestInstance : public Texture3DLodControlTestInstance
1748 {
1749 public:
Texture3DMinLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1750 Texture3DMinLodTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1751 : Texture3DLodControlTestInstance(context, testParameters)
1752 {
1753 }
1754
1755 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1756 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1757 {
1758 params.minLod = getMinLodForCell(cellNdx);
1759 }
1760 };
1761
1762 class Texture3DMaxLodTestInstance : public Texture3DLodControlTestInstance
1763 {
1764 public:
Texture3DMaxLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1765 Texture3DMaxLodTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1766 : Texture3DLodControlTestInstance(context, testParameters)
1767 {
1768 }
1769
1770 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1771 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1772 {
1773 params.maxLod = getMaxLodForCell(cellNdx);
1774 }
1775 };
1776
1777 class Texture3DBaseLevelTestInstance : public Texture3DLodControlTestInstance
1778 {
1779 public:
Texture3DBaseLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1780 Texture3DBaseLevelTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1781 : Texture3DLodControlTestInstance(context, testParameters)
1782 , m_testParam(testParameters)
1783 {
1784 }
1785
1786 protected:
1787 const Texture3DMipmapTestCaseParameters m_testParam;
1788
getBaseLevel(int cellNdx) const1789 int getBaseLevel(int cellNdx) const
1790 {
1791 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
1792 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
1793
1794 return baseLevel;
1795 }
1796
getReferenceParams(ReferenceParams & params,int cellNdx)1797 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1798 {
1799 params.baseLevel = getBaseLevel(cellNdx);
1800 }
1801 };
1802
1803 class Texture3DMaxLevelTestInstance : public Texture3DLodControlTestInstance
1804 {
1805 public:
Texture3DMaxLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1806 Texture3DMaxLevelTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1807 : Texture3DLodControlTestInstance(context, testParameters)
1808 , m_testParam(testParameters)
1809 {
1810 }
1811
1812 protected:
1813 const Texture3DMipmapTestCaseParameters m_testParam;
1814
getMaxLevel(int cellNdx) const1815 int getMaxLevel(int cellNdx) const
1816 {
1817 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
1818 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x9111e7) % numLevels;
1819
1820 return maxLevel;
1821 }
1822
getReferenceParams(ReferenceParams & params,int cellNdx)1823 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1824 {
1825 params.maxLevel = getMaxLevel(cellNdx);
1826 }
1827 };
1828
1829 #ifndef CTS_USES_VULKANSC
1830
1831 class Texture2DImageViewMinLodTestInstance : public Texture2DLodControlTestInstance
1832 {
1833 public:
Texture2DImageViewMinLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1834 Texture2DImageViewMinLodTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1835 : Texture2DLodControlTestInstance(context, testParameters)
1836 {
1837 }
1838
1839 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1840 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1841 {
1842 de::Random rnd(cellNdx + 1);
1843
1844 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1845 float minBaseLevel = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1846 return rnd.getFloat(minBaseLevel, (float)maxLevel);
1847 }
1848
getReferenceParams(ReferenceParams & params,int cellNdx)1849 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1850 {
1851 params.minLod = getMinLodForCell(cellNdx);
1852 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1853 }
1854 };
1855
1856 class Texture2DImageViewMinLodBaseLevelTestInstance : public Texture2DLodControlTestInstance
1857 {
1858 public:
Texture2DImageViewMinLodBaseLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1859 Texture2DImageViewMinLodBaseLevelTestInstance(Context &context,
1860 const Texture2DMipmapTestCaseParameters &testParameters)
1861 : Texture2DLodControlTestInstance(context, testParameters)
1862 , m_testParam(testParameters)
1863 {
1864 }
1865
1866 protected:
1867 const Texture2DMipmapTestCaseParameters m_testParam;
1868
getBaseLevel(int cellNdx) const1869 int getBaseLevel(int cellNdx) const
1870 {
1871 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1872 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
1873
1874 return baseLevel;
1875 }
1876
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1877 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1878 {
1879 de::Random rnd(cellNdx + 1);
1880
1881 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1882 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1883 return rnd.getFloat(minValue, (float)maxLevel);
1884 }
1885
getReferenceParams(ReferenceParams & params,int cellNdx)1886 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1887 {
1888 params.baseLevel = getBaseLevel(cellNdx);
1889 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1890 }
1891 };
1892
1893 class Texture3DImageViewMinLodTestInstance : public Texture3DLodControlTestInstance
1894 {
1895 public:
Texture3DImageViewMinLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1896 Texture3DImageViewMinLodTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1897 : Texture3DLodControlTestInstance(context, testParameters)
1898 {
1899 }
1900
1901 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1902 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1903 {
1904 de::Random rnd(cellNdx + 1);
1905
1906 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1907 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1908 return rnd.getFloat(minValue, (float)maxLevel);
1909 }
1910
getReferenceParams(ReferenceParams & params,int cellNdx)1911 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1912 {
1913 params.minLod = getMinLodForCell(cellNdx);
1914 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1915 }
1916 };
1917
1918 class Texture3DImageViewMinLodBaseLevelTestInstance : public Texture3DLodControlTestInstance
1919 {
1920 public:
Texture3DImageViewMinLodBaseLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1921 Texture3DImageViewMinLodBaseLevelTestInstance(Context &context,
1922 const Texture3DMipmapTestCaseParameters &testParameters)
1923 : Texture3DLodControlTestInstance(context, testParameters)
1924 , m_testParam(testParameters)
1925 {
1926 }
1927
1928 protected:
1929 const Texture3DMipmapTestCaseParameters m_testParam;
1930
getBaseLevel(int cellNdx) const1931 int getBaseLevel(int cellNdx) const
1932 {
1933 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
1934 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
1935
1936 return baseLevel;
1937 }
1938
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1939 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1940 {
1941 de::Random rnd(cellNdx + 1);
1942
1943 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1944 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1945 return rnd.getFloat(minValue, (float)maxLevel);
1946 }
1947
getReferenceParams(ReferenceParams & params,int cellNdx)1948 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1949 {
1950 params.baseLevel = getBaseLevel(cellNdx);
1951 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1952 }
1953 };
1954
1955 class TextureCubeImageViewMinLodTestInstance : public TextureCubeLodControlTestInstance
1956 {
1957 public:
TextureCubeImageViewMinLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1958 TextureCubeImageViewMinLodTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1959 : TextureCubeLodControlTestInstance(context, testParameters)
1960 {
1961 }
1962
1963 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1964 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1965 {
1966 de::Random rnd(cellNdx + 1);
1967
1968 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1969 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1970 return rnd.getFloat(minValue, (float)maxLevel);
1971 }
1972
getReferenceParams(ReferenceParams & params,int cellNdx)1973 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
1974 {
1975 params.minLod = getMinLodForCell(cellNdx);
1976 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1977 }
1978 };
1979
1980 class TextureCubeImageViewMinLodBaseLevelTestInstance : public TextureCubeLodControlTestInstance
1981 {
1982 public:
TextureCubeImageViewMinLodBaseLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1983 TextureCubeImageViewMinLodBaseLevelTestInstance(Context &context,
1984 const TextureCubeMipmapTestCaseParameters &testParameters)
1985 : TextureCubeLodControlTestInstance(context, testParameters)
1986 , m_testParam(testParameters)
1987 {
1988 }
1989
1990 protected:
1991 const TextureCubeMipmapTestCaseParameters m_testParam;
1992
getBaseLevel(int cellNdx) const1993 int getBaseLevel(int cellNdx) const
1994 {
1995 const int numLevels = deLog2Floor32(m_texSize) + 1;
1996 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x23fae13) % numLevels;
1997
1998 return baseLevel;
1999 }
2000
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2001 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2002 {
2003 de::Random rnd(cellNdx + 1);
2004
2005 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2006 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2007 return rnd.getFloat(minValue, (float)maxLevel);
2008 }
2009
getReferenceParams(ReferenceParams & params,int cellNdx)2010 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2011 {
2012 params.baseLevel = getBaseLevel(cellNdx);
2013 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2014 }
2015 };
2016
2017 class Texture2DImageViewMinLodIntTexCoordTestInstance : public Texture2DLodControlTestInstance
2018 {
2019 public:
Texture2DImageViewMinLodIntTexCoordTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2020 Texture2DImageViewMinLodIntTexCoordTestInstance(Context &context,
2021 const Texture2DMipmapTestCaseParameters &testParameters)
2022 : Texture2DLodControlTestInstance(context, testParameters)
2023 , m_testParam(testParameters)
2024 {
2025 }
2026
2027 protected:
2028 const Texture2DMipmapTestCaseParameters m_testParam;
2029
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2030 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2031 {
2032 de::Random rnd(cellNdx + 1);
2033
2034 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2035 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2036 return rnd.getFloat(minValue, (float)maxLevel);
2037 }
2038
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2039 int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2040 {
2041 de::Random rnd(cellNdx + 1);
2042 return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2043 }
2044
getReferenceParams(ReferenceParams & params,int cellNdx)2045 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2046 {
2047 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2048 params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2049 params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2050 }
2051 };
2052
2053 class Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance : public Texture2DLodControlTestInstance
2054 {
2055 public:
Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2056 Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context &context,
2057 const Texture2DMipmapTestCaseParameters &testParameters)
2058 : Texture2DLodControlTestInstance(context, testParameters)
2059 , m_testParam(testParameters)
2060 {
2061 }
2062
2063 protected:
2064 const Texture2DMipmapTestCaseParameters m_testParam;
2065
getBaseLevel(int cellNdx) const2066 int getBaseLevel(int cellNdx) const
2067 {
2068 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
2069 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
2070
2071 return baseLevel;
2072 }
2073
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2074 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2075 {
2076 de::Random rnd(cellNdx + 1);
2077
2078 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2079 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2080 return rnd.getFloat(minValue, (float)maxLevel);
2081 }
2082
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2083 int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2084 {
2085 de::Random rnd(cellNdx + 1);
2086 return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2087 }
2088
getReferenceParams(ReferenceParams & params,int cellNdx)2089 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2090 {
2091 params.baseLevel = getBaseLevel(cellNdx);
2092 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2093 params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2094 params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2095 }
2096 };
2097
2098 class Texture2DImageViewMinLodIntTexCoordTest : public vkt::TestCase
2099 {
2100 public:
2101 Texture2DImageViewMinLodIntTexCoordTest(tcu::TestContext &testContext, const string &name,
2102 const Texture2DMipmapTestCaseParameters ¶ms);
2103 ~Texture2DImageViewMinLodIntTexCoordTest(void);
2104 void initPrograms(SourceCollections &sourceCollections) const;
2105 TestInstance *createInstance(Context &context) const;
2106 void checkSupport(Context &context) const;
2107
2108 protected:
2109 const Texture2DMipmapTestCaseParameters m_params;
2110 };
2111
Texture2DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const Texture2DMipmapTestCaseParameters & params)2112 Texture2DImageViewMinLodIntTexCoordTest::Texture2DImageViewMinLodIntTexCoordTest(
2113 tcu::TestContext &testContext, const string &name, const Texture2DMipmapTestCaseParameters ¶ms)
2114 : vkt::TestCase(testContext, name)
2115 , m_params(params)
2116 {
2117 }
2118
~Texture2DImageViewMinLodIntTexCoordTest(void)2119 Texture2DImageViewMinLodIntTexCoordTest::~Texture2DImageViewMinLodIntTexCoordTest(void)
2120 {
2121 }
2122
initPrograms(SourceCollections & sourceCollections) const2123 void Texture2DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections &sourceCollections) const
2124 {
2125 static const char *vertShader = "#version 450\n"
2126 "layout(location = 0) in vec4 a_position;\n"
2127 "layout(location = 1) in vec2 a_texCoord;\n"
2128 "out gl_PerVertex { vec4 gl_Position; };\n"
2129 "\n"
2130 "void main (void)\n"
2131 "{\n"
2132 " gl_Position = a_position;\n"
2133 "}\n";
2134
2135 static const char *fragShader =
2136 "#version 450\n"
2137 "layout(location = 0) out vec4 outColor;\n"
2138 "layout (set=0, binding=0, std140) uniform Block \n"
2139 "{\n"
2140 " float u_bias;\n"
2141 " float u_ref;\n"
2142 " vec4 u_colorScale;\n"
2143 " vec4 u_colorBias;\n"
2144 " int u_lod;\n"
2145 "};\n\n"
2146 "layout (set=1, binding=0) uniform sampler2D u_sampler;\n"
2147 "void main (void)\n"
2148 "{\n"
2149 " ivec2 texCoord = ivec2(0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2150 " outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2151 "}\n";
2152 sourceCollections.glslSources.add("vertex_2D_FETCH_LOD") << glu::VertexSource(vertShader);
2153 sourceCollections.glslSources.add("fragment_2D_FETCH_LOD") << glu::FragmentSource(fragShader);
2154 }
2155
checkSupport(Context & context) const2156 void Texture2DImageViewMinLodIntTexCoordTest::checkSupport(Context &context) const
2157 {
2158 DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2159
2160 context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2161 context.requireDeviceFunctionality("VK_EXT_robustness2");
2162 vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2163 imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2164 imageViewMinLodFeatures.pNext = DE_NULL;
2165
2166 VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2167 robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2168 robustness2Features.pNext = &imageViewMinLodFeatures;
2169 vk::VkPhysicalDeviceFeatures2 features2;
2170
2171 features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2172 features2.pNext = &robustness2Features;
2173
2174 context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2175
2176 if (imageViewMinLodFeatures.minLod == false)
2177 TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2178
2179 if (robustness2Features.robustImageAccess2 == false)
2180 TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2181 }
2182
createInstance(Context & context) const2183 TestInstance *Texture2DImageViewMinLodIntTexCoordTest::createInstance(Context &context) const
2184 {
2185 if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2186 return new Texture2DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2187 else
2188 return new Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2189 }
2190
2191 class Texture3DImageViewMinLodIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2192 {
2193 public:
Texture3DImageViewMinLodIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2194 Texture3DImageViewMinLodIntTexCoordTestInstance(Context &context,
2195 const Texture3DMipmapTestCaseParameters &testParameters)
2196 : Texture3DLodControlTestInstance(context, testParameters)
2197 , m_testParam(testParameters)
2198 {
2199 }
2200
2201 protected:
2202 const Texture3DMipmapTestCaseParameters m_testParam;
2203
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2204 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2205 {
2206 de::Random rnd(cellNdx + 1);
2207
2208 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2209 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2210 return rnd.getFloat(minValue, (float)maxLevel);
2211 }
2212
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2213 int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2214 {
2215 de::Random rnd(cellNdx + 1);
2216 return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2217 }
2218
getReferenceParams(ReferenceParams & params,int cellNdx)2219 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2220 {
2221 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2222 params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2223 params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2224 }
2225 };
2226
2227 class Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2228 {
2229 public:
Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2230 Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context &context,
2231 const Texture3DMipmapTestCaseParameters &testParameters)
2232 : Texture3DLodControlTestInstance(context, testParameters)
2233 , m_testParam(testParameters)
2234 {
2235 }
2236
2237 protected:
2238 const Texture3DMipmapTestCaseParameters m_testParam;
2239
getBaseLevel(int cellNdx) const2240 int getBaseLevel(int cellNdx) const
2241 {
2242 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
2243 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
2244
2245 return baseLevel;
2246 }
2247
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2248 float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2249 {
2250 de::Random rnd(cellNdx + 1);
2251
2252 // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2253 float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2254 return rnd.getFloat(minValue, (float)maxLevel);
2255 }
2256
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2257 int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2258 {
2259 de::Random rnd(cellNdx + 1);
2260 return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2261 }
2262
getReferenceParams(ReferenceParams & params,int cellNdx)2263 void getReferenceParams(ReferenceParams ¶ms, int cellNdx)
2264 {
2265 params.baseLevel = getBaseLevel(cellNdx);
2266 params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2267 params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2268 params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2269 }
2270 };
2271
2272 class Texture3DImageViewMinLodIntTexCoordTest : public vkt::TestCase
2273 {
2274 public:
2275 Texture3DImageViewMinLodIntTexCoordTest(tcu::TestContext &testContext, const string &name,
2276 const Texture3DMipmapTestCaseParameters ¶ms);
2277 ~Texture3DImageViewMinLodIntTexCoordTest(void);
2278 void initPrograms(SourceCollections &sourceCollections) const;
2279 TestInstance *createInstance(Context &context) const;
2280 void checkSupport(Context &context) const;
2281
2282 protected:
2283 const Texture3DMipmapTestCaseParameters m_params;
2284 };
2285
Texture3DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const Texture3DMipmapTestCaseParameters & params)2286 Texture3DImageViewMinLodIntTexCoordTest::Texture3DImageViewMinLodIntTexCoordTest(
2287 tcu::TestContext &testContext, const string &name, const Texture3DMipmapTestCaseParameters ¶ms)
2288 : vkt::TestCase(testContext, name)
2289 , m_params(params)
2290 {
2291 }
2292
~Texture3DImageViewMinLodIntTexCoordTest(void)2293 Texture3DImageViewMinLodIntTexCoordTest::~Texture3DImageViewMinLodIntTexCoordTest(void)
2294 {
2295 }
2296
initPrograms(SourceCollections & sourceCollections) const2297 void Texture3DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections &sourceCollections) const
2298 {
2299 static const char *vertShader = "#version 450\n"
2300 "layout(location = 0) in vec4 a_position;\n"
2301 "layout(location = 1) in vec3 a_texCoord;\n"
2302 "out gl_PerVertex { vec4 gl_Position; };\n"
2303 "\n"
2304 "void main (void)\n"
2305 "{\n"
2306 " gl_Position = a_position;\n"
2307 "}\n";
2308
2309 static const char *fragShader =
2310 "#version 450\n"
2311 "layout(location = 0) out vec4 outColor;\n"
2312 "layout (set=0, binding=0, std140) uniform Block \n"
2313 "{\n"
2314 " float u_bias;\n"
2315 " float u_ref;\n"
2316 " vec4 u_colorScale;\n"
2317 " vec4 u_colorBias;\n"
2318 " int u_lod;\n"
2319 "};\n\n"
2320 "layout (set=1, binding=0) uniform sampler3D u_sampler;\n"
2321 "void main (void)\n"
2322 "{\n"
2323 " ivec3 texCoord = ivec3(0,0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2324 " outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2325 "}\n";
2326 sourceCollections.glslSources.add("vertex_3D_FETCH_LOD") << glu::VertexSource(vertShader);
2327 sourceCollections.glslSources.add("fragment_3D_FETCH_LOD") << glu::FragmentSource(fragShader);
2328 }
2329
checkSupport(Context & context) const2330 void Texture3DImageViewMinLodIntTexCoordTest::checkSupport(Context &context) const
2331 {
2332 DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2333
2334 context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2335 context.requireDeviceFunctionality("VK_EXT_robustness2");
2336 vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2337 imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2338 imageViewMinLodFeatures.pNext = DE_NULL;
2339
2340 VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2341 robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2342 robustness2Features.pNext = &imageViewMinLodFeatures;
2343 vk::VkPhysicalDeviceFeatures2 features2;
2344
2345 features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2346 features2.pNext = &robustness2Features;
2347
2348 context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2349
2350 if (imageViewMinLodFeatures.minLod == false)
2351 TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2352
2353 if (robustness2Features.robustImageAccess2 == false)
2354 TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2355 }
2356
createInstance(Context & context) const2357 TestInstance *Texture3DImageViewMinLodIntTexCoordTest::createInstance(Context &context) const
2358 {
2359 if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2360 return new Texture3DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2361 else
2362 return new Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2363 }
2364
2365 // Texture gather tests.
2366 enum class GatherMinLod
2367 {
2368 MINLOD_0_1, // 0.1
2369 MINLOD_1_1, // 1.1
2370 };
2371
2372 struct GatherParams
2373 {
2374 uint32_t randomSeed; // Seed for the pseudorandom number generator.
2375 GatherMinLod minLod; // Idea: make it 0.1 or 1.1
2376 int component; // 0, 1, 2, 3 for the gather operation.
2377
getNumericMinLodvkt::texture::__anonf5bf78d20111::GatherParams2378 float getNumericMinLod(void) const
2379 {
2380 float lod = 0.0f;
2381
2382 switch (minLod)
2383 {
2384 case GatherMinLod::MINLOD_0_1:
2385 lod = 0.1f;
2386 break;
2387 case GatherMinLod::MINLOD_1_1:
2388 lod = 1.1f;
2389 break;
2390 default:
2391 DE_ASSERT(false);
2392 break;
2393 }
2394
2395 return lod;
2396 }
2397
getMinLodIntegervkt::texture::__anonf5bf78d20111::GatherParams2398 uint32_t getMinLodInteger(void) const
2399 {
2400 uint32_t lod = 0u;
2401
2402 switch (minLod)
2403 {
2404 case GatherMinLod::MINLOD_0_1:
2405 lod = 0u;
2406 break;
2407 case GatherMinLod::MINLOD_1_1:
2408 lod = 1u;
2409 break;
2410 default:
2411 DE_ASSERT(false);
2412 break;
2413 }
2414
2415 return lod;
2416 }
2417
needsRobustness2vkt::texture::__anonf5bf78d20111::GatherParams2418 bool needsRobustness2(void) const
2419 {
2420 return (getNumericMinLod() >= 1.0f);
2421 }
2422 };
2423
2424 class TextureGatherMinLodTest : public vkt::TestCase
2425 {
2426 public:
TextureGatherMinLodTest(tcu::TestContext & testCtx,const std::string & name,const GatherParams & params)2427 TextureGatherMinLodTest(tcu::TestContext &testCtx, const std::string &name, const GatherParams ¶ms)
2428 : vkt::TestCase(testCtx, name)
2429 , m_params(params)
2430 {
2431 }
~TextureGatherMinLodTest(void)2432 virtual ~TextureGatherMinLodTest(void)
2433 {
2434 }
2435
2436 void initPrograms(vk::SourceCollections &programCollection) const override;
2437 TestInstance *createInstance(Context &context) const override;
2438 void checkSupport(Context &context) const override;
2439
2440 protected:
2441 GatherParams m_params;
2442 };
2443
2444 class TextureGatherMinLodInstance : public vkt::TestInstance
2445 {
2446 public:
TextureGatherMinLodInstance(Context & context,const GatherParams & params)2447 TextureGatherMinLodInstance(Context &context, const GatherParams ¶ms)
2448 : vkt::TestInstance(context)
2449 , m_params(params)
2450 {
2451 }
~TextureGatherMinLodInstance(void)2452 virtual ~TextureGatherMinLodInstance(void)
2453 {
2454 }
2455
2456 tcu::TestStatus iterate(void) override;
2457
2458 protected:
2459 GatherParams m_params;
2460 };
2461
2462 // Test idea: create texture with 3 levels, each of them having a unique nonzero color. Render gathering the color from a fixed
2463 // position in that texture (center point). Use the minLod parameter when creating the view to control which one should be the
2464 // output color. If minLod is 0.1, minLodInteger should be 0 and gathering from the base level is defined, so we should get the
2465 // output color from the base level. If minLod is 1.1, gathering texels from the base level requires robustness2 and will result in
2466 // zeros instead of the color from levels 0 or 1.
initPrograms(vk::SourceCollections & programCollection) const2467 void TextureGatherMinLodTest::initPrograms(vk::SourceCollections &programCollection) const
2468 {
2469 // Full screen triangle covering the whole viewport.
2470 std::ostringstream vert;
2471 vert << "#version 450\n"
2472 << "\n"
2473 << "vec2 positions[3] = vec2[](\n"
2474 << " vec2(-1.0, -1.0),\n"
2475 << " vec2(3.0, -1.0),\n"
2476 << " vec2(-1.0, 3.0)\n"
2477 << ");\n"
2478 << "\n"
2479 << "void main (void)\n"
2480 << "{\n"
2481 << " gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
2482 << "}\n";
2483 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2484
2485 std::ostringstream frag;
2486 frag << "#version 450\n"
2487 << "\n"
2488 << "layout (location=0) out vec4 outColor;\n"
2489 << "layout (set=0, binding=0) uniform sampler2D u_sampler;\n"
2490 << "\n"
2491 << "void main (void)\n"
2492 << "{\n"
2493 << " const vec2 gatherCoords = vec2(0.5, 0.5);\n"
2494 << " const vec4 gatherRes = textureGather(u_sampler, gatherCoords, " << m_params.component << ");\n"
2495 << " outColor = vec4(gatherRes.xyz, 1.0);\n"
2496 << "}\n";
2497 ;
2498 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2499 }
2500
checkSupport(Context & context) const2501 void TextureGatherMinLodTest::checkSupport(Context &context) const
2502 {
2503 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
2504 context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2505
2506 if (m_params.needsRobustness2())
2507 {
2508 context.requireDeviceFunctionality("VK_EXT_robustness2");
2509
2510 VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features = initVulkanStructure();
2511 VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&robustness2Features);
2512
2513 context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2514
2515 if (robustness2Features.robustImageAccess2 == false)
2516 TCU_THROW(NotSupportedError, "robustImageAccess2 not supported");
2517 }
2518 }
2519
createInstance(Context & context) const2520 TestInstance *TextureGatherMinLodTest::createInstance(Context &context) const
2521 {
2522 return new TextureGatherMinLodInstance(context, m_params);
2523 }
2524
2525 // Device helper: this is needed because we sometimes need a custom device with robustImageAccess2.
2526 class DeviceHelper
2527 {
2528 public:
~DeviceHelper()2529 virtual ~DeviceHelper()
2530 {
2531 }
2532 virtual const DeviceInterface &getDeviceInterface(void) const = 0;
2533 virtual VkDevice getDevice(void) const = 0;
2534 virtual uint32_t getQueueFamilyIndex(void) const = 0;
2535 virtual VkQueue getQueue(void) const = 0;
2536 virtual Allocator &getAllocator(void) const = 0;
2537 };
2538
2539 // This one just reuses the default device from the context.
2540 class ContextDeviceHelper : public DeviceHelper
2541 {
2542 public:
ContextDeviceHelper(Context & context)2543 ContextDeviceHelper(Context &context)
2544 : m_deviceInterface(context.getDeviceInterface())
2545 , m_device(context.getDevice())
2546 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
2547 , m_queue(context.getUniversalQueue())
2548 , m_allocator(context.getDefaultAllocator())
2549 {
2550 }
2551
~ContextDeviceHelper()2552 virtual ~ContextDeviceHelper()
2553 {
2554 }
2555
getDeviceInterface(void) const2556 const DeviceInterface &getDeviceInterface(void) const override
2557 {
2558 return m_deviceInterface;
2559 }
getDevice(void) const2560 VkDevice getDevice(void) const override
2561 {
2562 return m_device;
2563 }
getQueueFamilyIndex(void) const2564 uint32_t getQueueFamilyIndex(void) const override
2565 {
2566 return m_queueFamilyIndex;
2567 }
getQueue(void) const2568 VkQueue getQueue(void) const override
2569 {
2570 return m_queue;
2571 }
getAllocator(void) const2572 Allocator &getAllocator(void) const override
2573 {
2574 return m_allocator;
2575 }
2576
2577 protected:
2578 const DeviceInterface &m_deviceInterface;
2579 const VkDevice m_device;
2580 const uint32_t m_queueFamilyIndex;
2581 const VkQueue m_queue;
2582 Allocator &m_allocator;
2583 };
2584
2585 // This one creates a new device with robustImageAccess2.
2586 class RobustImageAccess2DeviceHelper : public DeviceHelper
2587 {
2588 public:
RobustImageAccess2DeviceHelper(Context & context)2589 RobustImageAccess2DeviceHelper(Context &context)
2590 {
2591 const auto &vkp = context.getPlatformInterface();
2592 const auto &vki = context.getInstanceInterface();
2593 const auto instance = context.getInstance();
2594 const auto physicalDevice = context.getPhysicalDevice();
2595 const auto queuePriority = 1.0f;
2596
2597 // Queue index first.
2598 m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2599
2600 // Create a universal queue that supports graphics and compute.
2601 const VkDeviceQueueCreateInfo queueParams = {
2602 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
2603 DE_NULL, // const void* pNext;
2604 0u, // VkDeviceQueueCreateFlags flags;
2605 m_queueFamilyIndex, // uint32_t queueFamilyIndex;
2606 1u, // uint32_t queueCount;
2607 &queuePriority // const float* pQueuePriorities;
2608 };
2609
2610 const char *extensions[] = {
2611 "VK_EXT_robustness2",
2612 "VK_EXT_image_view_min_lod",
2613 };
2614
2615 VkPhysicalDeviceImageViewMinLodFeaturesEXT minLodfeatures = initVulkanStructure();
2616 VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features = initVulkanStructure(&minLodfeatures);
2617 VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&robustness2Features);
2618
2619 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
2620
2621 const VkDeviceCreateInfo deviceCreateInfo = {
2622 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
2623 &features2, //pNext;
2624 0u, //flags
2625 1u, //queueRecordCount;
2626 &queueParams, //pRequestedQueues;
2627 0u, //layerCount;
2628 nullptr, //ppEnabledLayerNames;
2629 static_cast<uint32_t>(de::arrayLength(extensions)), // uint32_t enabledExtensionCount;
2630 extensions, // const char* const* ppEnabledExtensionNames;
2631 nullptr, //pEnabledFeatures;
2632 };
2633
2634 m_device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance,
2635 vki, physicalDevice, &deviceCreateInfo);
2636 m_vkd.reset(new DeviceDriver(vkp, instance, m_device.get(), context.getUsedApiVersion(),
2637 context.getTestContext().getCommandLine()));
2638 m_queue = getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
2639 m_allocator.reset(
2640 new SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
2641 }
2642
~RobustImageAccess2DeviceHelper()2643 virtual ~RobustImageAccess2DeviceHelper()
2644 {
2645 }
2646
getDeviceInterface(void) const2647 const DeviceInterface &getDeviceInterface(void) const override
2648 {
2649 return *m_vkd;
2650 }
getDevice(void) const2651 VkDevice getDevice(void) const override
2652 {
2653 return m_device.get();
2654 }
getQueueFamilyIndex(void) const2655 uint32_t getQueueFamilyIndex(void) const override
2656 {
2657 return m_queueFamilyIndex;
2658 }
getQueue(void) const2659 VkQueue getQueue(void) const override
2660 {
2661 return m_queue;
2662 }
getAllocator(void) const2663 Allocator &getAllocator(void) const override
2664 {
2665 return *m_allocator;
2666 }
2667
2668 protected:
2669 Move<VkDevice> m_device;
2670 std::unique_ptr<DeviceDriver> m_vkd;
2671 uint32_t m_queueFamilyIndex;
2672 VkQueue m_queue;
2673 std::unique_ptr<SimpleAllocator> m_allocator;
2674 };
2675
2676 std::unique_ptr<DeviceHelper> g_robustness2DeviceHelper;
2677 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
2678
getDeviceHelper(Context & context,bool needsRobustness2)2679 DeviceHelper &getDeviceHelper(Context &context, bool needsRobustness2)
2680 {
2681 if (needsRobustness2)
2682 {
2683 if (!g_robustness2DeviceHelper)
2684 g_robustness2DeviceHelper.reset(new RobustImageAccess2DeviceHelper(context));
2685 return *g_robustness2DeviceHelper;
2686 }
2687
2688 if (!g_contextDeviceHelper)
2689 g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
2690 return *g_contextDeviceHelper;
2691 }
2692
2693 // Cleanup function for the test group.
destroyDeviceHelpers(tcu::TestCaseGroup *)2694 void destroyDeviceHelpers(tcu::TestCaseGroup *)
2695 {
2696 g_robustness2DeviceHelper.reset(nullptr);
2697 g_contextDeviceHelper.reset(nullptr);
2698 }
2699
iterate(void)2700 tcu::TestStatus TextureGatherMinLodInstance::iterate(void)
2701 {
2702 const auto &deviceHelper = getDeviceHelper(m_context, m_params.needsRobustness2());
2703 const auto &vkd = deviceHelper.getDeviceInterface();
2704 const auto device = deviceHelper.getDevice();
2705 const auto queueIndex = deviceHelper.getQueueFamilyIndex();
2706 const auto queue = deviceHelper.getQueue();
2707 auto &alloc = deviceHelper.getAllocator();
2708
2709 const auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
2710 const auto tcuFormat = mapVkFormat(imageFormat);
2711 const auto colorExtent = makeExtent3D(1u, 1u, 1u);
2712 const tcu::IVec3 iColorExtent(static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height),
2713 static_cast<int>(colorExtent.depth));
2714 const auto texExtent = makeExtent3D(8u, 8u, 1u);
2715 const auto texMipLevels = 3u;
2716 const auto colorUsage =
2717 (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2718 const auto texUsage =
2719 (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2720 const auto minLodF = m_params.getNumericMinLod();
2721 const auto minLodU = m_params.getMinLodInteger();
2722 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2723
2724 // Color attachment: a simple 1x1 image.
2725 const VkImageCreateInfo colorCreateInfo = {
2726 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2727 nullptr, // const void* pNext;
2728 0u, // VkImageCreateFlags flags;
2729 VK_IMAGE_TYPE_2D, // VkImageType imageType;
2730 imageFormat, // VkFormat format;
2731 colorExtent, // VkExtent3D extent;
2732 1u, // uint32_t mipLevels;
2733 1u, // uint32_t arrayLayers;
2734 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
2735 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2736 colorUsage, // VkImageUsageFlags usage;
2737 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2738 0u, // uint32_t queueFamilyIndexCount;
2739 nullptr, // const uint32_t* pQueueFamilyIndices;
2740 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2741 };
2742
2743 ImageWithMemory colorBuffer(vkd, device, alloc, colorCreateInfo, MemoryRequirement::Any);
2744 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2745 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2746 const auto colorBufferView =
2747 makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2748
2749 // Texture: an 8x8 image with several mip levels.
2750 const VkImageCreateInfo texCreateInfo = {
2751 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2752 nullptr, // const void* pNext;
2753 0u, // VkImageCreateFlags flags;
2754 VK_IMAGE_TYPE_2D, // VkImageType imageType;
2755 imageFormat, // VkFormat format;
2756 texExtent, // VkExtent3D extent;
2757 texMipLevels, // uint32_t mipLevels;
2758 1u, // uint32_t arrayLayers;
2759 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
2760 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2761 texUsage, // VkImageUsageFlags usage;
2762 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2763 0u, // uint32_t queueFamilyIndexCount;
2764 nullptr, // const uint32_t* pQueueFamilyIndices;
2765 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2766 };
2767
2768 ImageWithMemory texture(vkd, device, alloc, texCreateInfo, MemoryRequirement::Any);
2769 const auto texSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texMipLevels, 0u, 1u);
2770
2771 DE_ASSERT(texMipLevels > 0u);
2772 DE_ASSERT(minLodU < texMipLevels);
2773
2774 const VkImageViewMinLodCreateInfoEXT texMinLodInfo = {
2775 VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT, // VkStructureType sType;
2776 nullptr, // const void* pNext;
2777 minLodF, // float minLod;
2778 };
2779
2780 const VkImageViewCreateInfo texViewCreateInfo = {
2781 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
2782 &texMinLodInfo, // const void* pNext;
2783 0u, // VkImageViewCreateFlags flags;
2784 texture.get(), // VkImage image;
2785 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
2786 imageFormat, // VkFormat format;
2787 makeComponentMappingRGBA(), // VkComponentMapping components;
2788 texSRR, // VkImageSubresourceRange subresourceRange;
2789 };
2790
2791 const auto texView = createImageView(vkd, device, &texViewCreateInfo);
2792
2793 // Verification buffer for the color attachment.
2794 const auto verifBufferSize = static_cast<VkDeviceSize>(iColorExtent.x() * iColorExtent.y() * iColorExtent.z() *
2795 tcu::getPixelSize(tcuFormat));
2796 const auto verifBufferCreateInfo = makeBufferCreateInfo(verifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2797 BufferWithMemory verifBuffer(vkd, device, alloc, verifBufferCreateInfo, MemoryRequirement::HostVisible);
2798 auto &verifBufferAlloc = verifBuffer.getAllocation();
2799 void *verifBufferData = verifBufferAlloc.getHostPtr();
2800
2801 // Descriptor set layout.
2802 DescriptorSetLayoutBuilder setLayoutBuilder;
2803 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
2804 const auto setLayout = setLayoutBuilder.build(vkd, device);
2805
2806 // Pipeline layout.
2807 const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
2808
2809 // Sampler.
2810 const VkSamplerCreateInfo samplerCreateInfo = {
2811 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
2812 nullptr, // const void* pNext;
2813 0u, // VkSamplerCreateFlags flags;
2814 VK_FILTER_LINEAR, // VkFilter magFilter;
2815 VK_FILTER_LINEAR, // VkFilter minFilter;
2816 VK_SAMPLER_MIPMAP_MODE_LINEAR, // VkSamplerMipmapMode mipmapMode;
2817 VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeU;
2818 VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeV;
2819 VK_SAMPLER_ADDRESS_MODE_REPEAT, // VkSamplerAddressMode addressModeW;
2820 0.0f, // float mipLodBias;
2821 VK_FALSE, // VkBool32 anisotropyEnable;
2822 0.0f, // float maxAnisotropy;
2823 VK_FALSE, // VkBool32 compareEnable;
2824 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
2825 0.0f, // float minLod;
2826 static_cast<float>(texMipLevels), // float maxLod;
2827 VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
2828 VK_FALSE, // VkBool32 unnormalizedCoordinates;
2829 };
2830 const auto sampler = createSampler(vkd, device, &samplerCreateInfo);
2831
2832 // Descriptor pool and set.
2833 DescriptorPoolBuilder poolBuilder;
2834 poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
2835 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2836 const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
2837
2838 // Update descriptor set.
2839 DescriptorSetUpdateBuilder setUpdateBuilder;
2840 const auto combinedSamplerInfo =
2841 makeDescriptorImageInfo(sampler.get(), texView.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2842 setUpdateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
2843 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &combinedSamplerInfo);
2844 setUpdateBuilder.update(vkd, device);
2845
2846 // Render pass and framebuffer.
2847 const auto renderPass = makeRenderPass(vkd, device, imageFormat);
2848 const auto framebuffer =
2849 makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorExtent.width, colorExtent.height);
2850
2851 // Shader modules.
2852 const auto &binaries = m_context.getBinaryCollection();
2853 const auto vertModule = createShaderModule(vkd, device, binaries.get("vert"));
2854 const auto fragModule = createShaderModule(vkd, device, binaries.get("frag"));
2855
2856 // Viewports and scissors.
2857 std::vector<VkViewport> viewports(1u, makeViewport(colorExtent));
2858 std::vector<VkRect2D> scissors(1u, makeRect2D(colorExtent));
2859
2860 // Pipeline.
2861 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2862
2863 const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(), vertModule.get(), DE_NULL, DE_NULL,
2864 DE_NULL, fragModule.get(), renderPass.get(), viewports, scissors,
2865 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u /*subpass*/,
2866 0u /*patchControlPoints*/, &vertexInputState);
2867
2868 // Command pool and buffer.
2869 const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
2870 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2871 const auto cmdBuffer = cmdBufferPtr.get();
2872
2873 beginCommandBuffer(vkd, cmdBuffer);
2874
2875 // Move the whole texture to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
2876 const auto preClearBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2877 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.get(), texSRR);
2878 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2879 &preClearBarrier);
2880
2881 // Fill each texture mip level with a different pseudorandom nonzero color.
2882 std::vector<tcu::Vec4> levelColors;
2883 de::Random rnd(m_params.randomSeed);
2884
2885 levelColors.reserve(texMipLevels);
2886
2887 const auto minColor = 0.004f; // Slightly above 1/255.
2888 const auto maxColor = 1.0f;
2889
2890 for (uint32_t level = 0u; level < texMipLevels; ++level)
2891 {
2892 const auto r = rnd.getFloat(minColor, maxColor);
2893 const auto g = rnd.getFloat(minColor, maxColor);
2894 const auto b = rnd.getFloat(minColor, maxColor);
2895 const auto a = rnd.getFloat(minColor, maxColor);
2896 const auto levelColor = makeClearValueColorF32(r, g, b, a).color;
2897 const auto levelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, 1u, 0u, 1u);
2898
2899 levelColors.emplace_back(r, g, b, a);
2900 vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &levelColor, 1u,
2901 &levelRange);
2902 }
2903
2904 // Move the whole texture to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
2905 const auto postClearBarrier = makeImageMemoryBarrier(
2906 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2907 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.get(), texSRR);
2908 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2909 &postClearBarrier);
2910
2911 beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2912 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
2913 &descriptorSet.get(), 0u, nullptr);
2914 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2915 vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u); // This has to match the vertex shader.
2916 endRenderPass(vkd, cmdBuffer);
2917
2918 // Copy color buffer to verification buffer.
2919 const auto postColorBarier = makeImageMemoryBarrier(
2920 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2921 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
2922 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2923 VK_PIPELINE_STAGE_TRANSFER_BIT, &postColorBarier);
2924
2925 const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL);
2926 vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u,
2927 ©Region);
2928
2929 const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2930 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2931 &preHostBarrier);
2932
2933 endCommandBuffer(vkd, cmdBuffer);
2934 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2935
2936 // Verify color buffer.
2937 invalidateAlloc(vkd, device, verifBufferAlloc);
2938 tcu::ConstPixelBufferAccess resultAccess(tcuFormat, iColorExtent, verifBufferData);
2939
2940 const auto resultColor = resultAccess.getPixel(0, 0);
2941 const auto srcLevelColor = levelColors.at(minLodU);
2942 const auto compColor = srcLevelColor[m_params.component];
2943 const auto expectedColor = (m_params.needsRobustness2() // This has to match the fragment shader.
2944 ?
2945 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) :
2946 tcu::Vec4(compColor, compColor, compColor, 1.0f));
2947 const auto threshold = (m_params.needsRobustness2() ? 0.0f : 0.005f); // 1/255 < 0.005 < 2/255
2948
2949 const auto diff = abs(resultColor - expectedColor);
2950 const tcu::Vec4 thresholdVec(threshold, threshold, threshold, 0.0f);
2951 const auto thresholdMet = tcu::lessThanEqual(diff, thresholdVec);
2952
2953 if (!tcu::boolAll(thresholdMet))
2954 {
2955 std::ostringstream msg;
2956 msg << "Unexpected output buffer color: expected " << expectedColor << " but found " << resultColor
2957 << " [diff=" << diff << "]";
2958 TCU_FAIL(msg.str());
2959 }
2960
2961 return tcu::TestStatus::pass("Pass");
2962 }
2963
2964 #endif // CTS_USES_VULKANSC
2965
2966 } // namespace
2967
2968 #ifndef CTS_USES_VULKANSC
2969
2970 namespace util
2971 {
2972
2973 template <>
checkTextureSupport(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2974 void checkTextureSupport(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
2975 {
2976 if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2977 {
2978 context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2979 vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2980 imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2981 imageViewMinLodFeatures.pNext = DE_NULL;
2982
2983 vk::VkPhysicalDeviceFeatures2 features2;
2984
2985 features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2986 features2.pNext = &imageViewMinLodFeatures;
2987
2988 context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2989
2990 if (imageViewMinLodFeatures.minLod == false)
2991 TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2992 }
2993 }
2994
2995 template <>
checkTextureSupport(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)2996 void checkTextureSupport(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
2997 {
2998 if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2999 {
3000 context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
3001 vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
3002 imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
3003 imageViewMinLodFeatures.pNext = DE_NULL;
3004
3005 vk::VkPhysicalDeviceFeatures2 features2;
3006
3007 features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
3008 features2.pNext = &imageViewMinLodFeatures;
3009
3010 context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
3011
3012 if (imageViewMinLodFeatures.minLod == false)
3013 TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
3014 }
3015 }
3016
3017 template <>
checkTextureSupport(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)3018 void checkTextureSupport(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
3019 {
3020 if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
3021 {
3022 context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
3023 vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
3024 imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
3025 imageViewMinLodFeatures.pNext = DE_NULL;
3026
3027 vk::VkPhysicalDeviceFeatures2 features2;
3028
3029 features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
3030 features2.pNext = &imageViewMinLodFeatures;
3031
3032 context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
3033
3034 if (imageViewMinLodFeatures.minLod == false)
3035 TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
3036 }
3037 }
3038
3039 } // namespace util
3040
populateMinLodGatherGroup(tcu::TestCaseGroup * minLodGatherGroup)3041 void populateMinLodGatherGroup(tcu::TestCaseGroup *minLodGatherGroup)
3042 {
3043 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
3044
3045 const struct
3046 {
3047 GatherMinLod minLod;
3048 const char *name;
3049 } GatherMinLodCases[] = {
3050 {GatherMinLod::MINLOD_0_1, "minlod_0_1"},
3051 {GatherMinLod::MINLOD_1_1, "minlod_1_1"},
3052 };
3053
3054 const struct
3055 {
3056 int component;
3057 const char *name;
3058 } ComponentCases[] = {
3059 {0, "component_0"},
3060 {1, "component_1"},
3061 {2, "component_2"},
3062 {3, "component_3"},
3063 };
3064
3065 auto &testCtx = minLodGatherGroup->getTestContext();
3066
3067 for (const auto &gatherMinLodCase : GatherMinLodCases)
3068 {
3069 GroupPtr minLodGroup(new tcu::TestCaseGroup(testCtx, gatherMinLodCase.name));
3070
3071 for (const auto &componentCase : ComponentCases)
3072 {
3073 const uint32_t seed = (static_cast<uint32_t>(gatherMinLodCase.minLod) + 1000u) * 1000u +
3074 (static_cast<uint32_t>(componentCase.component) + 1000u);
3075
3076 GatherParams params;
3077 params.randomSeed = seed;
3078 params.minLod = gatherMinLodCase.minLod;
3079 params.component = componentCase.component;
3080
3081 minLodGroup->addChild(new TextureGatherMinLodTest(testCtx, componentCase.name, params));
3082 }
3083
3084 minLodGatherGroup->addChild(minLodGroup.release());
3085 }
3086 }
3087
3088 #endif // CTS_USES_VULKANSC
3089
populateTextureMipmappingTests(tcu::TestCaseGroup * textureMipmappingTests)3090 void populateTextureMipmappingTests(tcu::TestCaseGroup *textureMipmappingTests)
3091 {
3092 tcu::TestContext &testCtx = textureMipmappingTests->getTestContext();
3093
3094 static const struct
3095 {
3096 const char *name;
3097 const Sampler::WrapMode mode;
3098 } wrapModes[] = {
3099 {"clamp", Sampler::CLAMP_TO_EDGE}, {"repeat", Sampler::REPEAT_GL}, {"mirror", Sampler::MIRRORED_REPEAT_GL}};
3100
3101 static const struct
3102 {
3103 const char *name;
3104 const Sampler::FilterMode mode;
3105 } minFilterModes[] = {{"nearest_nearest", Sampler::NEAREST_MIPMAP_NEAREST},
3106 {"linear_nearest", Sampler::LINEAR_MIPMAP_NEAREST},
3107 {"nearest_linear", Sampler::NEAREST_MIPMAP_LINEAR},
3108 {"linear_linear", Sampler::LINEAR_MIPMAP_LINEAR}};
3109
3110 static const struct
3111 {
3112 const char *name;
3113 const Sampler::FilterMode mode;
3114 } magFilterModes[] = {{"nearest", Sampler::NEAREST}, {"linear", Sampler::LINEAR}};
3115
3116 static const struct
3117 {
3118 const CoordType type;
3119 const char *name;
3120 } coordTypes[] = {// Mipmapping with translated and scaled coordinates
3121 {COORDTYPE_BASIC, "basic"},
3122 // Mipmapping with affine coordinate transform
3123 {COORDTYPE_AFFINE, "affine"},
3124 // Mipmapping with perspective projection
3125 {COORDTYPE_PROJECTED, "projected"}};
3126
3127 static const struct
3128 {
3129 const char *name;
3130 const int width;
3131 const int height;
3132 } tex2DSizes[] = {{DE_NULL, 64, 64}, // Default.
3133 {"npot", 63, 57},
3134 {"non_square", 32, 64}};
3135
3136 static const struct
3137 {
3138 const char *name;
3139 const int width;
3140 const int height;
3141 const int depth;
3142 } tex3DSizes[] = {{DE_NULL, 32, 32, 32}, // Default.
3143 {"npot", 33, 29, 27}};
3144
3145 const int cubeMapSize = 64;
3146
3147 static const struct
3148 {
3149 const CoordType type;
3150 const char *name;
3151 } cubeCoordTypes[] = {// Mipmapping with translated and scaled coordinates
3152 {COORDTYPE_BASIC, "basic"},
3153 // Mipmapping with perspective projection
3154 {COORDTYPE_PROJECTED, "projected"},
3155 // User-supplied bias value
3156 {COORDTYPE_BASIC_BIAS, "bias"}};
3157
3158 // 2D cases.
3159 {
3160 // 2D Mipmap Filtering
3161 de::MovePtr<tcu::TestCaseGroup> group2D(new tcu::TestCaseGroup(testCtx, "2d"));
3162
3163 // User-supplied bias value
3164 de::MovePtr<tcu::TestCaseGroup> biasGroup2D(new tcu::TestCaseGroup(testCtx, "bias"));
3165 de::MovePtr<tcu::TestCaseGroup> minLodGroup2D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3166 de::MovePtr<tcu::TestCaseGroup> maxLodGroup2D(new tcu::TestCaseGroup(testCtx, "max_lod"));
3167 de::MovePtr<tcu::TestCaseGroup> baseLevelGroup2D(new tcu::TestCaseGroup(testCtx, "base_level"));
3168 de::MovePtr<tcu::TestCaseGroup> maxLevelGroup2D(new tcu::TestCaseGroup(testCtx, "max_level"));
3169
3170 #ifndef CTS_USES_VULKANSC
3171 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup2D(
3172 new tcu::TestCaseGroup(testCtx, "image_view_min_lod"));
3173 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup2D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3174 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup2D(new tcu::TestCaseGroup(testCtx, "base_level"));
3175 #endif // CTS_USES_VULKANSC
3176
3177 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3178 {
3179 de::MovePtr<tcu::TestCaseGroup> coordTypeGroup(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name));
3180
3181 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3182 {
3183 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3184 {
3185 // Add non_square variants to basic cases only.
3186 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
3187
3188 for (int size = 0; size < sizeEnd; size++)
3189 {
3190 Texture2DMipmapTestCaseParameters testParameters;
3191
3192 testParameters.coordType = coordTypes[coordType].type;
3193 testParameters.minFilter = minFilterModes[minFilter].mode;
3194 testParameters.wrapS = wrapModes[wrapMode].mode;
3195 testParameters.wrapT = wrapModes[wrapMode].mode;
3196 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
3197 testParameters.width = tex2DSizes[size].width;
3198 testParameters.height = tex2DSizes[size].height;
3199 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3200 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3201
3202 std::ostringstream name;
3203 name << minFilterModes[minFilter].name << "_" << wrapModes[wrapMode].name;
3204
3205 if (tex2DSizes[size].name)
3206 name << "_" << tex2DSizes[size].name;
3207
3208 coordTypeGroup->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(
3209 testCtx, name.str().c_str(), testParameters));
3210 }
3211 }
3212 }
3213
3214 group2D->addChild(coordTypeGroup.release());
3215 }
3216
3217 // 2D bias variants.
3218 {
3219 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3220 {
3221 Texture2DMipmapTestCaseParameters testParameters;
3222
3223 testParameters.coordType = COORDTYPE_BASIC_BIAS;
3224 testParameters.minFilter = minFilterModes[minFilter].mode;
3225 testParameters.magFilter = minFilterModes[minFilter].mode;
3226 testParameters.wrapS = Sampler::REPEAT_GL;
3227 testParameters.wrapT = Sampler::REPEAT_GL;
3228 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
3229 testParameters.width = tex2DSizes[0].width;
3230 testParameters.height = tex2DSizes[0].height;
3231 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3232 testParameters.programs.push_back(PROGRAM_2D_FLOAT_BIAS);
3233
3234 std::ostringstream name;
3235 name << minFilterModes[minFilter].name;
3236
3237 biasGroup2D->addChild(
3238 new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), testParameters));
3239 }
3240 }
3241
3242 // 2D LOD controls.
3243 {
3244 // MIN_LOD
3245 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3246 {
3247 Texture2DMipmapTestCaseParameters testParameters;
3248 testParameters.minFilter = minFilterModes[minFilter].mode;
3249 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3250 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3251
3252 minLodGroup2D->addChild(new TextureTestCase<Texture2DMinLodTestInstance>(
3253 testCtx, minFilterModes[minFilter].name, testParameters));
3254 }
3255
3256 // MAX_LOD
3257 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3258 {
3259 Texture2DMipmapTestCaseParameters testParameters;
3260 testParameters.minFilter = minFilterModes[minFilter].mode;
3261 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3262 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3263
3264 maxLodGroup2D->addChild(new TextureTestCase<Texture2DMaxLodTestInstance>(
3265 testCtx, minFilterModes[minFilter].name, testParameters));
3266 }
3267 }
3268
3269 {
3270 // BASE_LEVEL
3271 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3272 {
3273 Texture2DMipmapTestCaseParameters testParameters;
3274 testParameters.minFilter = minFilterModes[minFilter].mode;
3275 testParameters.minFilterName = minFilterModes[minFilter].name;
3276 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3277 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3278
3279 baseLevelGroup2D->addChild(new TextureTestCase<Texture2DBaseLevelTestInstance>(
3280 testCtx, minFilterModes[minFilter].name, testParameters));
3281 }
3282
3283 // MAX_LEVEL
3284 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3285 {
3286 Texture2DMipmapTestCaseParameters testParameters;
3287 testParameters.minFilter = minFilterModes[minFilter].mode;
3288 testParameters.minFilterName = minFilterModes[minFilter].name;
3289 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3290 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3291
3292 maxLevelGroup2D->addChild(new TextureTestCase<Texture2DMaxLevelTestInstance>(
3293 testCtx, minFilterModes[minFilter].name, testParameters));
3294 }
3295 }
3296
3297 // 2D VK_EXT_image_view_min_lod.
3298 #ifndef CTS_USES_VULKANSC
3299 {
3300 // MIN_LOD
3301 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3302 {
3303 Texture2DMipmapTestCaseParameters testParameters;
3304 testParameters.minFilter = minFilterModes[minFilter].mode;
3305 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3306 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3307 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3308
3309 imageViewMinLodGroup2D->addChild(new TextureTestCase<Texture2DImageViewMinLodTestInstance>(
3310 testCtx, minFilterModes[minFilter].name, testParameters));
3311
3312 std::ostringstream name;
3313 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3314 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3315 imageViewMinLodGroup2D->addChild(
3316 new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3317 }
3318
3319 // BASE_LEVEL
3320 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3321 {
3322 Texture2DMipmapTestCaseParameters testParameters;
3323 testParameters.minFilter = minFilterModes[minFilter].mode;
3324 testParameters.minFilterName = minFilterModes[minFilter].name;
3325 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3326 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3327 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3328
3329 imageViewMinLodBaseLevelGroup2D->addChild(
3330 new TextureTestCase<Texture2DImageViewMinLodBaseLevelTestInstance>(
3331 testCtx, minFilterModes[minFilter].name, testParameters));
3332
3333 std::ostringstream name;
3334 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3335 testParameters.testType =
3336 util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3337 imageViewMinLodBaseLevelGroup2D->addChild(
3338 new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3339 }
3340
3341 imageViewMinLodExtGroup2D->addChild(imageViewMinLodGroup2D.release());
3342 imageViewMinLodExtGroup2D->addChild(imageViewMinLodBaseLevelGroup2D.release());
3343 }
3344 #endif // CTS_USES_VULKANSC
3345
3346 group2D->addChild(biasGroup2D.release());
3347 group2D->addChild(minLodGroup2D.release());
3348 group2D->addChild(maxLodGroup2D.release());
3349 group2D->addChild(baseLevelGroup2D.release());
3350 group2D->addChild(maxLevelGroup2D.release());
3351 #ifndef CTS_USES_VULKANSC
3352 group2D->addChild(imageViewMinLodExtGroup2D.release());
3353 #endif // CTS_USES_VULKANSC
3354
3355 textureMipmappingTests->addChild(group2D.release());
3356 }
3357
3358 // Cubemap cases.
3359 {
3360 de::MovePtr<tcu::TestCaseGroup> groupCube(new tcu::TestCaseGroup(testCtx, "cubemap"));
3361
3362 de::MovePtr<tcu::TestCaseGroup> minLodGroupCube(new tcu::TestCaseGroup(testCtx, "min_lod"));
3363 de::MovePtr<tcu::TestCaseGroup> maxLodGroupCube(new tcu::TestCaseGroup(testCtx, "max_lod"));
3364 de::MovePtr<tcu::TestCaseGroup> baseLevelGroupCube(new tcu::TestCaseGroup(testCtx, "base_level"));
3365 de::MovePtr<tcu::TestCaseGroup> maxLevelGroupCube(new tcu::TestCaseGroup(testCtx, "max_level"));
3366
3367 #ifndef CTS_USES_VULKANSC
3368 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroupCube(
3369 new tcu::TestCaseGroup(testCtx, "image_view_min_lod"));
3370 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroupCube(new tcu::TestCaseGroup(testCtx, "min_lod"));
3371 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroupCube(
3372 new tcu::TestCaseGroup(testCtx, "base_level"));
3373 #endif // CTS_USES_VULKANSC
3374
3375 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
3376 {
3377 de::MovePtr<tcu::TestCaseGroup> coordTypeGroup(
3378 new tcu::TestCaseGroup(testCtx, cubeCoordTypes[coordType].name));
3379
3380 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3381 {
3382 for (int magFilter = 0; magFilter < DE_LENGTH_OF_ARRAY(magFilterModes); magFilter++)
3383 {
3384 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3385 {
3386 TextureCubeMipmapTestCaseParameters testParameters;
3387
3388 testParameters.coordType = cubeCoordTypes[coordType].type;
3389 testParameters.minFilter = minFilterModes[minFilter].mode;
3390 testParameters.magFilter = magFilterModes[magFilter].mode;
3391 testParameters.minFilterName = minFilterModes[minFilter].name;
3392 testParameters.wrapS = wrapModes[wrapMode].mode;
3393 testParameters.wrapT = wrapModes[wrapMode].mode;
3394 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
3395 testParameters.size = cubeMapSize;
3396 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3397
3398 if (testParameters.coordType == COORDTYPE_BASIC_BIAS)
3399 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT_BIAS);
3400 else
3401 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3402
3403 std::ostringstream name;
3404 name << minFilterModes[minFilter].name << "_" << magFilterModes[magFilter].name << "_"
3405 << wrapModes[wrapMode].name;
3406
3407 coordTypeGroup->addChild(new TextureTestCase<TextureCubeMipmapTestInstance>(
3408 testCtx, name.str().c_str(), testParameters));
3409 }
3410 }
3411 }
3412
3413 groupCube->addChild(coordTypeGroup.release());
3414 }
3415
3416 // Cubemap LOD controls.
3417 {
3418 // MIN_LOD
3419 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3420 {
3421 TextureCubeMipmapTestCaseParameters testParameters;
3422 testParameters.minFilter = minFilterModes[minFilter].mode;
3423 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3424 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3425
3426 minLodGroupCube->addChild(new TextureTestCase<TextureCubeMinLodTestInstance>(
3427 testCtx, minFilterModes[minFilter].name, testParameters));
3428 }
3429
3430 // MAX_LOD
3431 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3432 {
3433 TextureCubeMipmapTestCaseParameters testParameters;
3434 testParameters.minFilter = minFilterModes[minFilter].mode;
3435 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3436 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3437
3438 maxLodGroupCube->addChild(new TextureTestCase<TextureCubeMaxLodTestInstance>(
3439 testCtx, minFilterModes[minFilter].name, testParameters));
3440 }
3441 }
3442
3443 {
3444 // BASE_LEVEL
3445 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3446 {
3447 TextureCubeMipmapTestCaseParameters testParameters;
3448 testParameters.minFilter = minFilterModes[minFilter].mode;
3449 testParameters.minFilterName = minFilterModes[minFilter].name;
3450 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3451 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3452
3453 baseLevelGroupCube->addChild(new TextureTestCase<TextureCubeBaseLevelTestInstance>(
3454 testCtx, minFilterModes[minFilter].name, testParameters));
3455 }
3456
3457 // MAX_LEVEL
3458 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3459 {
3460 TextureCubeMipmapTestCaseParameters testParameters;
3461 testParameters.minFilter = minFilterModes[minFilter].mode;
3462 testParameters.minFilterName = minFilterModes[minFilter].name;
3463 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3464 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3465
3466 maxLevelGroupCube->addChild(new TextureTestCase<TextureCubeMaxLevelTestInstance>(
3467 testCtx, minFilterModes[minFilter].name, testParameters));
3468 }
3469 }
3470
3471 // Cube VK_EXT_image_view_min_lod.
3472 #ifndef CTS_USES_VULKANSC
3473 {
3474 // MIN_LOD
3475 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3476 {
3477 TextureCubeMipmapTestCaseParameters testParameters;
3478 testParameters.minFilter = minFilterModes[minFilter].mode;
3479 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3480 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3481 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3482
3483 imageViewMinLodGroupCube->addChild(new TextureTestCase<TextureCubeImageViewMinLodTestInstance>(
3484 testCtx, minFilterModes[minFilter].name, testParameters));
3485 }
3486
3487 // BASE_LEVEL
3488 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3489 {
3490 TextureCubeMipmapTestCaseParameters testParameters;
3491 testParameters.minFilter = minFilterModes[minFilter].mode;
3492 testParameters.minFilterName = minFilterModes[minFilter].name;
3493 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3494 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3495 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3496
3497 imageViewMinLodBaseLevelGroupCube->addChild(
3498 new TextureTestCase<TextureCubeImageViewMinLodBaseLevelTestInstance>(
3499 testCtx, minFilterModes[minFilter].name, testParameters));
3500 }
3501
3502 imageViewMinLodExtGroupCube->addChild(imageViewMinLodGroupCube.release());
3503 imageViewMinLodExtGroupCube->addChild(imageViewMinLodBaseLevelGroupCube.release());
3504 }
3505 #endif // CTS_USES_VULKANSC
3506
3507 groupCube->addChild(minLodGroupCube.release());
3508 groupCube->addChild(maxLodGroupCube.release());
3509 groupCube->addChild(baseLevelGroupCube.release());
3510 groupCube->addChild(maxLevelGroupCube.release());
3511 #ifndef CTS_USES_VULKANSC
3512 groupCube->addChild(imageViewMinLodExtGroupCube.release());
3513 #endif // CTS_USES_VULKANSC
3514
3515 textureMipmappingTests->addChild(groupCube.release());
3516 }
3517
3518 // 3D cases.
3519 {
3520 de::MovePtr<tcu::TestCaseGroup> group3D(new tcu::TestCaseGroup(testCtx, "3d"));
3521
3522 de::MovePtr<tcu::TestCaseGroup> biasGroup3D(new tcu::TestCaseGroup(testCtx, "bias"));
3523 de::MovePtr<tcu::TestCaseGroup> minLodGroup3D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3524 de::MovePtr<tcu::TestCaseGroup> maxLodGroup3D(new tcu::TestCaseGroup(testCtx, "max_lod"));
3525 de::MovePtr<tcu::TestCaseGroup> baseLevelGroup3D(new tcu::TestCaseGroup(testCtx, "base_level"));
3526 de::MovePtr<tcu::TestCaseGroup> maxLevelGroup3D(new tcu::TestCaseGroup(testCtx, "max_level"));
3527
3528 #ifndef CTS_USES_VULKANSC
3529 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup3D(
3530 new tcu::TestCaseGroup(testCtx, "image_view_min_lod"));
3531 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup3D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3532 de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup3D(new tcu::TestCaseGroup(testCtx, "base_level"));
3533 #endif // CTS_USES_VULKANSC
3534
3535 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3536 {
3537 de::MovePtr<tcu::TestCaseGroup> coordTypeGroup(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name));
3538
3539 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3540 {
3541 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3542 {
3543 // Add other size variants to basic cases only.
3544 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;
3545
3546 Texture3DMipmapTestCaseParameters testParameters;
3547
3548 testParameters.coordType = coordTypes[coordType].type;
3549 testParameters.minFilter = minFilterModes[minFilter].mode;
3550 testParameters.minFilterName = minFilterModes[minFilter].name;
3551 testParameters.wrapR = wrapModes[wrapMode].mode;
3552 testParameters.wrapS = wrapModes[wrapMode].mode;
3553 testParameters.wrapT = wrapModes[wrapMode].mode;
3554 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
3555 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3556 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3557
3558 for (int size = 0; size < sizeEnd; size++)
3559 {
3560 testParameters.width = tex3DSizes[size].width;
3561 testParameters.height = tex3DSizes[size].height;
3562 testParameters.depth = tex3DSizes[size].depth;
3563
3564 std::ostringstream name;
3565 name << minFilterModes[minFilter].name << "_" << wrapModes[wrapMode].name;
3566
3567 if (tex3DSizes[size].name)
3568 name << "_" << tex3DSizes[size].name;
3569
3570 coordTypeGroup->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(
3571 testCtx, name.str().c_str(), testParameters));
3572 }
3573 }
3574 }
3575
3576 group3D->addChild(coordTypeGroup.release());
3577 }
3578
3579 // 3D bias variants.
3580 {
3581 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3582 {
3583 Texture3DMipmapTestCaseParameters testParameters;
3584 testParameters.coordType = COORDTYPE_BASIC_BIAS;
3585 testParameters.minFilter = minFilterModes[minFilter].mode;
3586 testParameters.wrapR = Sampler::REPEAT_GL;
3587 testParameters.wrapS = Sampler::REPEAT_GL;
3588 testParameters.wrapT = Sampler::REPEAT_GL;
3589 testParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
3590 testParameters.width = tex3DSizes[0].width;
3591 testParameters.height = tex3DSizes[0].height;
3592 testParameters.depth = tex3DSizes[0].depth;
3593 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3594 testParameters.programs.push_back(PROGRAM_3D_FLOAT_BIAS);
3595
3596 biasGroup3D->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(
3597 testCtx, minFilterModes[minFilter].name, testParameters));
3598 }
3599 }
3600
3601 // 3D LOD controls.
3602 {
3603 // MIN_LOD
3604 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3605 {
3606 Texture3DMipmapTestCaseParameters testParameters;
3607 testParameters.minFilter = minFilterModes[minFilter].mode;
3608 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3609 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3610
3611 minLodGroup3D->addChild(new TextureTestCase<Texture3DMinLodTestInstance>(
3612 testCtx, minFilterModes[minFilter].name, testParameters));
3613 }
3614
3615 // MAX_LOD
3616 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3617 {
3618 Texture3DMipmapTestCaseParameters testParameters;
3619 testParameters.minFilter = minFilterModes[minFilter].mode;
3620 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3621 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3622
3623 maxLodGroup3D->addChild(new TextureTestCase<Texture3DMaxLodTestInstance>(
3624 testCtx, minFilterModes[minFilter].name, testParameters));
3625 }
3626 }
3627
3628 {
3629 // BASE_LEVEL
3630 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3631 {
3632 Texture3DMipmapTestCaseParameters testParameters;
3633 testParameters.minFilter = minFilterModes[minFilter].mode;
3634 testParameters.minFilterName = minFilterModes[minFilter].name;
3635 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3636 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3637
3638 baseLevelGroup3D->addChild(new TextureTestCase<Texture3DBaseLevelTestInstance>(
3639 testCtx, minFilterModes[minFilter].name, testParameters));
3640 }
3641
3642 // MAX_LEVEL
3643 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3644 {
3645 Texture3DMipmapTestCaseParameters testParameters;
3646 testParameters.minFilter = minFilterModes[minFilter].mode;
3647 testParameters.minFilterName = minFilterModes[minFilter].name;
3648 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3649 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3650
3651 maxLevelGroup3D->addChild(new TextureTestCase<Texture3DMaxLevelTestInstance>(
3652 testCtx, minFilterModes[minFilter].name, testParameters));
3653 }
3654 }
3655
3656 // 3D VK_EXT_image_view_min_lod.
3657 #ifndef CTS_USES_VULKANSC
3658 {
3659 // MIN_LOD
3660 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3661 {
3662 Texture3DMipmapTestCaseParameters testParameters;
3663 testParameters.minFilter = minFilterModes[minFilter].mode;
3664 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3665 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3666 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3667
3668 imageViewMinLodGroup3D->addChild(new TextureTestCase<Texture3DImageViewMinLodTestInstance>(
3669 testCtx, minFilterModes[minFilter].name, testParameters));
3670
3671 std::ostringstream name;
3672 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3673 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3674 imageViewMinLodGroup3D->addChild(
3675 new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3676 }
3677
3678 // BASE_LEVEL
3679 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3680 {
3681 Texture3DMipmapTestCaseParameters testParameters;
3682 testParameters.minFilter = minFilterModes[minFilter].mode;
3683 testParameters.minFilterName = minFilterModes[minFilter].name;
3684 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3685 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3686 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3687
3688 imageViewMinLodBaseLevelGroup3D->addChild(
3689 new TextureTestCase<Texture3DImageViewMinLodBaseLevelTestInstance>(
3690 testCtx, minFilterModes[minFilter].name, testParameters));
3691
3692 std::ostringstream name;
3693 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3694 testParameters.testType =
3695 util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3696 imageViewMinLodBaseLevelGroup3D->addChild(
3697 new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3698 }
3699
3700 imageViewMinLodExtGroup3D->addChild(imageViewMinLodGroup3D.release());
3701 imageViewMinLodExtGroup3D->addChild(imageViewMinLodBaseLevelGroup3D.release());
3702 }
3703 #endif // CTS_USES_VULKANSC
3704
3705 group3D->addChild(biasGroup3D.release());
3706 group3D->addChild(minLodGroup3D.release());
3707 group3D->addChild(maxLodGroup3D.release());
3708 group3D->addChild(baseLevelGroup3D.release());
3709 group3D->addChild(maxLevelGroup3D.release());
3710 #ifndef CTS_USES_VULKANSC
3711 group3D->addChild(imageViewMinLodExtGroup3D.release());
3712 #endif // CTS_USES_VULKANSC
3713
3714 textureMipmappingTests->addChild(group3D.release());
3715 }
3716
3717 #ifndef CTS_USES_VULKANSC
3718 {
3719 // Test minLod with textureGather operations
3720 const auto minLodGatherGroup =
3721 createTestGroup(testCtx, "min_lod_gather", populateMinLodGatherGroup, destroyDeviceHelpers);
3722 textureMipmappingTests->addChild(minLodGatherGroup);
3723 }
3724 #endif // CTS_USES_VULKANSC
3725 }
3726
createTextureMipmappingTests(tcu::TestContext & testCtx)3727 tcu::TestCaseGroup *createTextureMipmappingTests(tcu::TestContext &testCtx)
3728 {
3729 return createTestGroup(testCtx, "mipmap", populateTextureMipmappingTests);
3730 }
3731
3732 } // namespace texture
3733 } // namespace vkt
3734