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