Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / texture / vktTextureShadowTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  * Copyright (c) 2016 The Khronos Group Inc.
7  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 Shadow texture lookup tests.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktTextureShadowTests.hpp"
27 #include "vktAmberTestCase.hpp"
28
29 #include "deMath.h"
30 #include "deString.h"
31 #include "deStringUtil.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluTextureTestUtil.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuImageIO.hpp"
37 #include "tcuRenderTarget.hpp"
38 #include "tcuTexCompareVerifier.hpp"
39 #include "tcuTexVerifierUtil.hpp"
40 #include "tcuTexture.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "vkImageUtil.hpp"
43 #include "vkTypeUtil.hpp"
44 #include "vktTestGroupUtil.hpp"
45 #include "vktTextureTestUtil.hpp"
46
47 using namespace vk;
48
49 namespace vkt
50 {
51 namespace texture
52 {
53 namespace
54 {
55
56 using std::vector;
57 using std::string;
58 using tcu::TestLog;
59 using tcu::Sampler;
60 using namespace texture::util;
61 using namespace glu::TextureTestUtil;
62
63 enum
64 {
65         TEXCUBE_VIEWPORT_SIZE   = 28,
66         TEX1D_VIEWPORT_WIDTH    = 64,
67         TEX2D_VIEWPORT_WIDTH    = 64,
68         TEX2D_VIEWPORT_HEIGHT   = 64
69 };
70
71 struct TextureShadowCommonTestCaseParameters
72 {
73                                                                                 TextureShadowCommonTestCaseParameters   (void);
74         Sampler::CompareMode                            compareOp;
75         TextureBinding::ImageBackingMode        backingMode;
76 };
77
78 TextureShadowCommonTestCaseParameters::TextureShadowCommonTestCaseParameters (void)
79         : compareOp                                                     (Sampler::COMPAREMODE_EQUAL)
80         , backingMode                                           (TextureBinding::IMAGE_BACKING_MODE_REGULAR)
81 {
82 }
83
84 struct Texture2DShadowTestCaseParameters : public Texture2DTestCaseParameters, public TextureShadowCommonTestCaseParameters
85 {
86 };
87
88 bool isFloatingPointDepthFormat (const tcu::TextureFormat& format)
89 {
90         // Only two depth and depth-stencil formats are floating point
91         return  (format.order == tcu::TextureFormat::D && format.type == tcu::TextureFormat::FLOAT) ||
92                         (format.order == tcu::TextureFormat::DS && format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV);
93 }
94
95 void clampFloatingPointTexture (const tcu::PixelBufferAccess& access)
96 {
97         DE_ASSERT(isFloatingPointDepthFormat(access.getFormat()));
98
99         for (int z = 0; z < access.getDepth(); ++z)
100         for (int y = 0; y < access.getHeight(); ++y)
101         for (int x = 0; x < access.getWidth(); ++x)
102                 access.setPixDepth(de::clamp(access.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
103 }
104
105 void clampFloatingPointTexture (tcu::Texture2D& target)
106 {
107         for (int level = 0; level < target.getNumLevels(); ++level)
108                 if (!target.isLevelEmpty(level))
109                         clampFloatingPointTexture(target.getLevel(level));
110 }
111
112 static void clampFloatingPointTexture (tcu::Texture2DArray& target)
113 {
114         for (int level = 0; level < target.getNumLevels(); ++level)
115                 if (!target.isLevelEmpty(level))
116                         clampFloatingPointTexture(target.getLevel(level));
117 }
118
119 void clampFloatingPointTexture (tcu::TextureCube& target)
120 {
121         for (int level = 0; level < target.getNumLevels(); ++level)
122                 for (int face = tcu::CUBEFACE_NEGATIVE_X; face < tcu::CUBEFACE_LAST; ++face)
123                         clampFloatingPointTexture(target.getLevelFace(level, (tcu::CubeFace)face));
124 }
125
126 void clampFloatingPointTexture (tcu::Texture1D& target)
127 {
128         for (int level = 0; level < target.getNumLevels(); ++level)
129                 if (!target.isLevelEmpty(level))
130                         clampFloatingPointTexture(target.getLevel(level));
131 }
132
133 static void clampFloatingPointTexture (tcu::Texture1DArray& target)
134 {
135         for (int level = 0; level < target.getNumLevels(); ++level)
136                 if (!target.isLevelEmpty(level))
137                         clampFloatingPointTexture(target.getLevel(level));
138 }
139
140 void clampFloatingPointTexture (tcu::TextureCubeArray& target)
141 {
142         for (int level = 0; level < target.getNumLevels(); ++level)
143                 clampFloatingPointTexture(target.getLevel(level)); // face and layer are inside level's depth
144 }
145
146 tcu::PixelFormat getPixelFormat(tcu::TextureFormat texFormat)
147 {
148         const tcu::IVec4                        formatBitDepth          = tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(texFormat, Sampler::MODE_DEPTH));
149         return tcu::PixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
150 }
151
152 template<typename TextureType>
153 bool verifyTexCompareResult (tcu::TestContext&                                          testCtx,
154                                                          const tcu::ConstPixelBufferAccess&             result,
155                                                          const TextureType&                                             src,
156                                                          const float*                                                   texCoord,
157                                                          const ReferenceParams&                                 sampleParams,
158                                                          const tcu::TexComparePrecision&                comparePrec,
159                                                          const tcu::LodPrecision&                               lodPrec,
160                                                          const tcu::PixelFormat&                                pixelFormat)
161 {
162         tcu::TestLog&   log                                     = testCtx.getLog();
163         tcu::Surface    reference                       (result.getWidth(), result.getHeight());
164         tcu::Surface    errorMask                       (result.getWidth(), result.getHeight());
165         const tcu::Vec3 nonShadowThreshold      = tcu::computeFixedPointThreshold(getBitsVec(pixelFormat)-1).swizzle(1,2,3);
166         int                             numFailedPixels;
167
168         // sampleTexture() expects source image to be the same state as it would be in a GL implementation, that is
169         // the floating point depth values should be in [0, 1] range as data is clamped during texture upload. Since
170         // we don't have a separate "uploading" phase and just reuse the buffer we used for GL-upload, do the clamping
171         // here if necessary.
172
173         if (isFloatingPointDepthFormat(src.getFormat()))
174         {
175                 TextureType clampedSource(src);
176
177                 clampFloatingPointTexture(clampedSource);
178
179                 // sample clamped values
180
181                 sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), clampedSource, texCoord, sampleParams);
182                 numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), clampedSource, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold);
183         }
184         else
185         {
186                 // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
187
188                 sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
189                 numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold);
190         }
191
192         if (numFailedPixels > 0)
193                 log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
194
195         log << TestLog::ImageSet("VerifyResult", "Verification result")
196                 << TestLog::Image("Rendered", "Rendered image", result);
197
198         if (numFailedPixels > 0)
199         {
200                 log << TestLog::Image("Reference", "Ideal reference image", reference)
201                         << TestLog::Image("ErrorMask", "Error mask", errorMask);
202         }
203
204         log << TestLog::EndImageSet;
205
206         return numFailedPixels == 0;
207 }
208
209 #ifdef CTS_USES_VULKANSC
210 bool isDepthFormat(VkFormat format)
211 {
212         if (isCompressedFormat(format))
213                 return false;
214
215         if (isYCbCrFormat(format))
216                 return false;
217
218         const tcu::TextureFormat tcuFormat = mapVkFormat(format);
219         return tcuFormat.order == tcu::TextureFormat::D || tcuFormat.order == tcu::TextureFormat::DS;
220 }
221 #endif // CTS_USES_VULKANSC
222
223 void checkTextureSupport (Context& context, const Texture2DShadowTestCaseParameters& testParameters)
224 {
225 #ifndef CTS_USES_VULKANSC
226         const VkFormatProperties3 formatProperties = context.getFormatProperties(testParameters.format);
227         if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
228                 TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
229 #else
230         DE_UNREF(context);
231         if (!isDepthFormat(testParameters.format))
232                 TCU_THROW(NotSupportedError, "Format cannot be used as depth format");
233 #endif // CTS_USES_VULKANSC
234 }
235
236 class Texture2DShadowTestInstance : public TestInstance
237 {
238 public:
239         typedef Texture2DShadowTestCaseParameters       ParameterType;
240                                                                                                 Texture2DShadowTestInstance             (Context& context, const ParameterType& testParameters);
241                                                                                                 ~Texture2DShadowTestInstance    (void);
242
243         virtual tcu::TestStatus                                         iterate                                                 (void);
244
245 private:
246                                                                                                 Texture2DShadowTestInstance             (const Texture2DShadowTestInstance& other);
247         Texture2DShadowTestInstance&                            operator=                                               (const Texture2DShadowTestInstance& other);
248
249         struct FilterCase
250         {
251                 int                     textureIndex;
252
253                 tcu::Vec2       minCoord;
254                 tcu::Vec2       maxCoord;
255                 float           ref;
256
257                 FilterCase      (void)
258                         : textureIndex(-1)
259                         , ref           (0.0f)
260                 {
261                 }
262
263                 FilterCase      (int tex_, const float ref_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
264                         : textureIndex  (tex_)
265                         , minCoord              (minCoord_)
266                         , maxCoord              (maxCoord_)
267                         , ref                   (ref_)
268                 {
269                 }
270         };
271
272         const ParameterType&                    m_testParameters;
273         std::vector<TestTexture2DSp>    m_textures;
274         std::vector<FilterCase>                 m_cases;
275
276         TextureRenderer                                 m_renderer;
277
278         int                                                             m_caseNdx;
279 };
280
281 Texture2DShadowTestInstance::Texture2DShadowTestInstance (Context& context, const ParameterType& testParameters)
282         : TestInstance                  (context)
283         , m_testParameters              (testParameters)
284         , m_renderer                    (context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
285         , m_caseNdx                             (0)
286 {
287         // Create 2 textures.
288         m_textures.reserve(2);
289         for (int ndx = 0; ndx < 2; ndx++)
290         {
291                 m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
292         }
293
294         const int       numLevels       = m_textures[0]->getNumLevels();
295
296         // Fill first gradient texture.
297         for (int levelNdx = 0; levelNdx < numLevels; ++levelNdx)
298         {
299                 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
300         }
301
302         // Fill second with grid texture.
303         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
304         {
305                 const deUint32  step    = 0x00ffffff / numLevels;
306                 const deUint32  rgb             = step*levelNdx;
307                 const deUint32  colorA  = 0xff000000 | rgb;
308                 const deUint32  colorB  = 0xff000000 | ~rgb;
309
310                 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec(), tcu::RGBA(colorB).toVec());
311         }
312
313         // Upload.
314         for (std::vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
315         {
316                 m_renderer.add2DTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
317         }
318
319         // Compute cases.
320         {
321                 const float refInRangeUpper             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
322                 const float refInRangeLower             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
323                 const float refOutOfBoundsUpper = 1.1f;         // !< lookup function should clamp values to [0, 1] range
324                 const float refOutOfBoundsLower = -0.1f;
325
326                 const struct
327                 {
328                         const int       texNdx;
329                         const float     ref;
330                         const float     lodX;
331                         const float     lodY;
332                         const float     oX;
333                         const float     oY;
334                 } cases[] =
335                 {
336                         { 0,    refInRangeUpper,                1.6f,   2.9f,   -1.0f,  -2.7f   },
337                         { 0,    refInRangeLower,                -2.0f,  -1.35f, -0.2f,  0.7f    },
338                         { 1,    refInRangeUpper,                0.14f,  0.275f, -1.5f,  -1.1f   },
339                         { 1,    refInRangeLower,                -0.92f, -2.64f, 0.4f,   -0.1f   },
340                         { 1,    refOutOfBoundsUpper,    -0.39f, -0.52f, 0.65f,  0.87f   },
341                         { 1,    refOutOfBoundsLower,    -1.55f, 0.65f,  0.35f,  0.91f   },
342                 };
343
344                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
345                 {
346                         const int       texNdx  = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
347                         const float ref         = cases[caseNdx].ref;
348                         const float     lodX    = cases[caseNdx].lodX;
349                         const float     lodY    = cases[caseNdx].lodY;
350                         const float     oX              = cases[caseNdx].oX;
351                         const float     oY              = cases[caseNdx].oY;
352                         const float     sX              = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
353                         const float     sY              = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[texNdx]->getTexture().getHeight());
354
355                         m_cases.push_back(FilterCase(texNdx, ref, tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY)));
356                 }
357         }
358
359         m_caseNdx = 0;
360 }
361
362 Texture2DShadowTestInstance::~Texture2DShadowTestInstance (void)
363 {
364         m_textures.clear();
365         m_cases.clear();
366 }
367
368 tcu::TestStatus Texture2DShadowTestInstance::iterate (void)
369 {
370         tcu::TestLog&                                   log                             = m_context.getTestContext().getLog();
371         const pipeline::TestTexture2D&  texture                 = m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
372         const tcu::TextureFormat                texFmt                  = texture.getTextureFormat();
373         const tcu::TextureFormatInfo    fmtInfo                 = tcu::getTextureFormatInfo(texFmt);
374         const tcu::ScopedLogSection             section                 (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
375
376         const FilterCase&                               curCase                 = m_cases[m_caseNdx];
377         ReferenceParams                                 sampleParams    (TEXTURETYPE_2D);
378         tcu::Surface                                    rendered                (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
379         vector<float>                                   texCoord;
380
381         // Setup params for reference.
382         sampleParams.sampler                    = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
383         sampleParams.sampler.compare    = m_testParameters.compareOp;
384         sampleParams.samplerType                = SAMPLERTYPE_SHADOW;
385         sampleParams.lodMode                    = LODMODE_EXACT;
386         sampleParams.colorBias                  = fmtInfo.lookupBias;
387         sampleParams.colorScale                 = fmtInfo.lookupScale;
388         sampleParams.ref                                = curCase.ref;
389
390         log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;
391
392         // Compute texture coordinates.
393         log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
394         computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
395
396         m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
397
398         {
399                 const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
400                 tcu::LodPrecision                       lodPrecision;
401                 tcu::TexComparePrecision        texComparePrecision;
402
403                 lodPrecision.derivateBits                       = 18;
404                 lodPrecision.lodBits                            = 6;
405                 texComparePrecision.coordBits           = tcu::IVec3(20,20,0);
406                 texComparePrecision.uvwBits                     = tcu::IVec3(7,7,0);
407                 texComparePrecision.pcfBits                     = 5;
408                 texComparePrecision.referenceBits       = 16;
409                 texComparePrecision.resultBits          = pixelFormat.redBits-1;
410
411 #ifdef CTS_USES_VULKANSC
412                 if (m_context.getTestContext().getCommandLine().isSubProcess())
413 #endif // CTS_USES_VULKANSC
414                 {
415                         const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
416                                                                                                                           &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
417
418                         if (!isHighQuality)
419                         {
420                                 m_context.getTestContext().getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
421
422                                 lodPrecision.lodBits                    = 4;
423                                 texComparePrecision.uvwBits             = tcu::IVec3(4,4,0);
424                                 texComparePrecision.pcfBits             = 0;
425
426                                 const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
427                                                                                                                  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
428
429                                 if (!isOk)
430                                 {
431                                         m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
432                                         return tcu::TestStatus::fail("Image verification failed");
433                                 }
434                         }
435                 }
436         }
437
438         m_caseNdx += 1;
439         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
440 }
441
442 struct TextureCubeShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public TextureCubeTestCaseParameters
443 {
444 };
445
446 void checkTextureSupport (Context& context, const TextureCubeShadowTestCaseParameters& testParameters)
447 {
448 #ifndef CTS_USES_VULKANSC
449         const VkFormatProperties3 formatProperties = context.getFormatProperties(testParameters.format);
450         if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
451                 TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
452         if (!testParameters.seamless)
453                 context.requireDeviceFunctionality("VK_EXT_non_seamless_cube_map");
454 #else
455         DE_UNREF(context);
456         if (!isDepthFormat(testParameters.format))
457                 TCU_THROW(NotSupportedError, "Format cannot be used as depth format");
458 #endif // CTS_USES_VULKANSC
459 }
460
461
462 class TextureCubeShadowTestInstance : public TestInstance
463 {
464 public:
465         typedef TextureCubeShadowTestCaseParameters ParameterType;
466                                                                                                 TextureCubeShadowTestInstance           (Context& context, const ParameterType& testParameters);
467                                                                                                 ~TextureCubeShadowTestInstance          (void);
468
469         virtual tcu::TestStatus                                         iterate                                                         (void);
470
471 private:
472                                                                                                 TextureCubeShadowTestInstance           (const TextureCubeShadowTestInstance& other);
473         TextureCubeShadowTestInstance&                          operator=                                                       (const TextureCubeShadowTestInstance& other);
474
475         struct FilterCase
476         {
477                 int                                             textureIndex;
478                 tcu::Vec2                               bottomLeft;
479                 tcu::Vec2                               topRight;
480                 float                                   ref;
481
482                 FilterCase (void)
483                         : textureIndex  (-1)
484                         , ref                   (0.0f)
485                 {
486                 }
487
488                 FilterCase (const int tex_, const float ref_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
489                         : textureIndex  (tex_)
490                         , bottomLeft    (bottomLeft_)
491                         , topRight              (topRight_)
492                         , ref                   (ref_)
493                 {
494                 }
495         };
496
497         const ParameterType&            m_testParameters;
498         vector<TestTextureCubeSp>       m_textures;
499         std::vector<FilterCase>         m_cases;
500
501         TextureRenderer                         m_renderer;
502         int                                                     m_caseNdx;
503 };
504
505 TextureCubeShadowTestInstance::TextureCubeShadowTestInstance (Context& context, const ParameterType& testParameters)
506         : TestInstance                  (context)
507         , m_testParameters              (testParameters)
508         , m_renderer                    (context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
509         , m_caseNdx                             (0)
510 {
511         const int                                               numLevels       = deLog2Floor32(m_testParameters.size)+1;
512         const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
513         const tcu::Vec4                                 cBias           = fmtInfo.valueMin;
514         const tcu::Vec4                                 cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
515
516         // Create textures.
517
518         m_textures.reserve(2);
519         for (int ndx = 0; ndx < 2; ndx++)
520         {
521                 m_textures.push_back(TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
522         }
523
524         // Fill first with gradient texture.
525         static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
526         {
527                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
528                 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
529                 { tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
530                 { tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
531                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
532                 { tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
533         };
534
535         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
536         {
537                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
538                 {
539                         tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
540                 }
541         }
542
543         // Fill second with grid texture.
544         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
545         {
546                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
547                 {
548                         const deUint32  step    = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
549                         const deUint32  rgb             = step*levelNdx*face;
550                         const deUint32  colorA  = 0xff000000 | rgb;
551                         const deUint32  colorB  = 0xff000000 | ~rgb;
552
553                         tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
554                 }
555         }
556
557         // Upload.
558         for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
559         {
560                 m_renderer.addCubeTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
561         }
562
563         // Compute cases
564         {
565                 const float refInRangeUpper             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
566                 const float refInRangeLower             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
567                 const float refOutOfBoundsUpper = 1.1f;
568                 const float refOutOfBoundsLower = -0.1f;
569
570                 m_cases.push_back(FilterCase(0, refInRangeUpper,                tcu::Vec2(-1.25f, -1.2f),       tcu::Vec2(1.2f, 1.25f)));       // minification
571                 m_cases.push_back(FilterCase(0, refInRangeLower,                tcu::Vec2(0.8f, 0.8f),          tcu::Vec2(1.25f, 1.20f)));      // magnification
572                 m_cases.push_back(FilterCase(1, refInRangeUpper,                tcu::Vec2(-1.19f, -1.3f),       tcu::Vec2(1.1f, 1.35f)));       // minification
573                 m_cases.push_back(FilterCase(1, refInRangeLower,                tcu::Vec2(-1.2f, -1.1f),        tcu::Vec2(-0.8f, -0.8f)));      // magnification
574                 m_cases.push_back(FilterCase(1, refOutOfBoundsUpper,    tcu::Vec2(-0.61f, -0.1f),       tcu::Vec2(0.9f, 1.18f)));       // reference value clamp, upper
575                 m_cases.push_back(FilterCase(1, refOutOfBoundsLower,    tcu::Vec2(-0.75f, 1.0f),        tcu::Vec2(0.05f, 0.75f)));      // reference value clamp, lower
576         }
577 }
578
579 TextureCubeShadowTestInstance::~TextureCubeShadowTestInstance   (void)
580 {
581 }
582
583 static const char* getFaceDesc (const tcu::CubeFace face)
584 {
585         switch (face)
586         {
587                 case tcu::CUBEFACE_NEGATIVE_X:  return "-X";
588                 case tcu::CUBEFACE_POSITIVE_X:  return "+X";
589                 case tcu::CUBEFACE_NEGATIVE_Y:  return "-Y";
590                 case tcu::CUBEFACE_POSITIVE_Y:  return "+Y";
591                 case tcu::CUBEFACE_NEGATIVE_Z:  return "-Z";
592                 case tcu::CUBEFACE_POSITIVE_Z:  return "+Z";
593                 default:
594                         DE_ASSERT(false);
595                         return DE_NULL;
596         }
597 }
598
599 tcu::TestStatus TextureCubeShadowTestInstance::iterate (void)
600 {
601
602         tcu::TestLog&                                           log                             = m_context.getTestContext().getLog();
603         const tcu::ScopedLogSection                     iterSection             (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
604         const FilterCase&                                       curCase                 = m_cases[m_caseNdx];
605         const pipeline::TestTextureCube&        texture                 = m_renderer.getCubeTexture(curCase.textureIndex);
606
607         ReferenceParams                                         sampleParams    (TEXTURETYPE_CUBE);
608
609         // Params for reference computation.
610         sampleParams.sampler                                    = util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
611         sampleParams.sampler.seamlessCubeMap    = m_testParameters.seamless;
612         sampleParams.sampler.compare                    = m_testParameters.compareOp;
613         sampleParams.samplerType                                = SAMPLERTYPE_SHADOW;
614         sampleParams.lodMode                                    = LODMODE_EXACT;
615         sampleParams.ref                                                = curCase.ref;
616
617         log     << TestLog::Message
618                 << "Compare reference value = " << sampleParams.ref << "\n"
619                 << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight
620                 << TestLog::EndMessage;
621
622         for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
623         {
624                 const tcu::CubeFace             face            = tcu::CubeFace(faceNdx);
625                 tcu::Surface                    result          (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
626                 vector<float>                   texCoord;
627
628                 computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
629
630                 log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
631
632                 // \todo Log texture coordinates.
633
634                 m_renderer.renderQuad(result, curCase.textureIndex, &texCoord[0], sampleParams);
635
636                 {
637                         const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
638                         tcu::LodPrecision                       lodPrecision;
639                         tcu::TexComparePrecision        texComparePrecision;
640
641                         lodPrecision.derivateBits                       = 10;
642                         lodPrecision.lodBits                            = 5;
643                         texComparePrecision.coordBits           = tcu::IVec3(10,10,10);
644                         texComparePrecision.uvwBits                     = tcu::IVec3(6,6,0);
645                         texComparePrecision.pcfBits                     = 5;
646                         texComparePrecision.referenceBits       = 16;
647                         texComparePrecision.resultBits          = pixelFormat.redBits-1;
648
649 #ifdef CTS_USES_VULKANSC
650                         if (m_context.getTestContext().getCommandLine().isSubProcess())
651 #endif // CTS_USES_VULKANSC
652                         {
653                                 const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
654                                                                                                                                   &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
655
656                                 if (!isHighQuality)
657                                 {
658                                         log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
659
660                                         lodPrecision.lodBits                    = 4;
661                                         texComparePrecision.uvwBits             = tcu::IVec3(4,4,0);
662                                         texComparePrecision.pcfBits             = 0;
663
664                                         const bool isOk = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
665                                                                                                                          &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
666
667                                         if (!isOk)
668                                         {
669                                                 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
670                                                 return tcu::TestStatus::fail("Image verification failed");
671                                         }
672                                 }
673                         }
674                 }
675         }
676
677         m_caseNdx += 1;
678         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
679 }
680
681 struct Texture2DArrayShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public Texture2DArrayTestCaseParameters
682 {
683 };
684
685 void checkTextureSupport (Context& context, const Texture2DArrayShadowTestCaseParameters& testParameters)
686 {
687 #ifndef CTS_USES_VULKANSC
688         const VkFormatProperties3 formatProperties = context.getFormatProperties(testParameters.format);
689         if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
690                 TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
691 #else
692         DE_UNREF(context);
693         if (!isDepthFormat(testParameters.format))
694                 TCU_THROW(NotSupportedError, "Format cannot be used as depth format");
695 #endif // CTS_USES_VULKANSC
696 }
697
698 class Texture2DArrayShadowTestInstance : public TestInstance
699 {
700 public:
701         typedef Texture2DArrayShadowTestCaseParameters  ParameterType;
702                                                                                                         Texture2DArrayShadowTestInstance                (Context& context, const ParameterType& testParameters);
703                                                                                                         ~Texture2DArrayShadowTestInstance               (void);
704
705         virtual tcu::TestStatus                                                 iterate                                                                 (void);
706
707 private:
708                                                                                                         Texture2DArrayShadowTestInstance                (const Texture2DArrayShadowTestInstance& other);
709         Texture2DArrayShadowTestInstance&                               operator=                                                               (const Texture2DArrayShadowTestInstance& other);
710
711         struct FilterCase
712         {
713                 int                                                     textureIndex;
714                 tcu::Vec3                                       minCoord;
715                 tcu::Vec3                                       maxCoord;
716                 float                                           ref;
717
718                 FilterCase (void)
719                         : textureIndex  (-1)
720                         , ref                   (0.0f)
721                 {
722                 }
723
724                 FilterCase (const int tex_, float ref_, const tcu::Vec3& minCoord_, const tcu::Vec3& maxCoord_)
725                         : textureIndex  (tex_)
726                         , minCoord              (minCoord_)
727                         , maxCoord              (maxCoord_)
728                         , ref                   (ref_)
729                 {
730                 }
731         };
732
733         const ParameterType&                            m_testParameters;
734         std::vector<TestTexture2DArraySp>       m_textures;
735         std::vector<FilterCase>                         m_cases;
736
737         TextureRenderer                                         m_renderer;
738
739         int                                                                     m_caseNdx;
740 };
741
742 Texture2DArrayShadowTestInstance::Texture2DArrayShadowTestInstance (Context& context, const ParameterType& testParameters)
743         : TestInstance                  (context)
744         , m_testParameters              (testParameters)
745         , m_renderer                    (context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
746         , m_caseNdx                             (0)
747 {
748         const int                                               numLevels       = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height))+1;
749         const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
750         const tcu::Vec4                                 cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
751         const tcu::Vec4                                 cBias           = fmtInfo.valueMin;
752
753         // Create 2 textures.
754         m_textures.reserve(2);
755         for (int ndx = 0; ndx < 2; ndx++)
756         {
757                 m_textures.push_back(TestTexture2DArraySp(new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.numLayers)));
758         }
759
760         // Fill first gradient texture.
761         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
762         {
763                 const tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
764                 const tcu::Vec4 gMax = tcu::Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
765
766                 tcu::fillWithComponentGradients(m_textures[0]->getTexture().getLevel(levelNdx), gMin, gMax);
767         }
768
769         // Fill second with grid texture.
770         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
771         {
772                 const deUint32  step    = 0x00ffffff / numLevels;
773                 const deUint32  rgb             = step*levelNdx;
774                 const deUint32  colorA  = 0xff000000 | rgb;
775                 const deUint32  colorB  = 0xff000000 | ~rgb;
776
777                 tcu::fillWithGrid(m_textures[1]->getTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
778         }
779
780         // Upload.
781         for (std::vector<TestTexture2DArraySp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
782         {
783                 m_renderer.add2DArrayTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
784         }
785
786         // Compute cases.
787         {
788                 const float refInRangeUpper             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
789                 const float refInRangeLower             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
790                 const float refOutOfBoundsUpper = 1.1f;         // !< lookup function should clamp values to [0, 1] range
791                 const float refOutOfBoundsLower = -0.1f;
792
793                 const struct
794                 {
795                         const int       texNdx;
796                         const float     ref;
797                         const float     lodX;
798                         const float     lodY;
799                         const float     oX;
800                         const float     oY;
801                 } cases[] =
802                 {
803                         { 0,    refInRangeUpper,                1.6f,   2.9f,   -1.0f,  -2.7f   },
804                         { 0,    refInRangeLower,                -2.0f,  -1.35f, -0.2f,  0.7f    },
805                         { 1,    refInRangeUpper,                0.14f,  0.275f, -1.5f,  -1.1f   },
806                         { 1,    refInRangeLower,                -0.92f, -2.64f, 0.4f,   -0.1f   },
807                         { 1,    refOutOfBoundsUpper,    -0.49f, -0.22f, 0.45f,  0.97f   },
808                         { 1,    refOutOfBoundsLower,    -0.85f, 0.75f,  0.25f,  0.61f   },
809                 };
810
811                 const float     minLayer        = -0.5f;
812                 const float     maxLayer        = (float)m_testParameters.numLayers;
813
814                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
815                 {
816                         const int       tex             = cases[caseNdx].texNdx > 0 ? 1 : 0;
817                         const float     ref             = cases[caseNdx].ref;
818                         const float     lodX    = cases[caseNdx].lodX;
819                         const float     lodY    = cases[caseNdx].lodY;
820                         const float     oX              = cases[caseNdx].oX;
821                         const float     oY              = cases[caseNdx].oY;
822                         const float     sX              = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[tex]->getTexture().getWidth());
823                         const float     sY              = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[tex]->getTexture().getHeight());
824
825                         m_cases.push_back(FilterCase(tex, ref, tcu::Vec3(oX, oY, minLayer), tcu::Vec3(oX+sX, oY+sY, maxLayer)));
826                 }
827         }
828 }
829
830 Texture2DArrayShadowTestInstance::~Texture2DArrayShadowTestInstance (void)
831 {
832 }
833
834 tcu::TestStatus Texture2DArrayShadowTestInstance::iterate (void)
835 {
836         tcu::TestLog&                                           log                             = m_context.getTestContext().getLog();
837         const FilterCase&                                       curCase                 = m_cases[m_caseNdx];
838         const pipeline::TestTexture2DArray&     texture                 = m_renderer.get2DArrayTexture(curCase.textureIndex);
839
840         ReferenceParams                                         sampleParams    (TEXTURETYPE_2D_ARRAY);
841         tcu::Surface                                            rendered                (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
842         const tcu::ScopedLogSection                     section                 (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
843
844         const float                                                     texCoord[]              =
845         {
846                 curCase.minCoord.x(), curCase.minCoord.y(), curCase.minCoord.z(),
847                 curCase.minCoord.x(), curCase.maxCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f,
848                 curCase.maxCoord.x(), curCase.minCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f,
849                 curCase.maxCoord.x(), curCase.maxCoord.y(), curCase.maxCoord.z()
850         };
851
852         // Setup params for reference.
853         sampleParams.sampler                    = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
854         sampleParams.sampler.compare    = m_testParameters.compareOp;
855         sampleParams.samplerType                = SAMPLERTYPE_SHADOW;
856         sampleParams.lodMode                    = LODMODE_EXACT;
857         sampleParams.ref                                = curCase.ref;
858
859         log     << TestLog::Message
860                 << "Compare reference value = " << sampleParams.ref << "\n"
861                 << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord
862                 << TestLog::EndMessage;
863
864         m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
865
866         {
867                 const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
868                 tcu::LodPrecision                       lodPrecision;
869                 tcu::TexComparePrecision        texComparePrecision;
870
871                 lodPrecision.derivateBits                       = 18;
872                 lodPrecision.lodBits                            = 6;
873                 texComparePrecision.coordBits           = tcu::IVec3(20,20,20);
874                 texComparePrecision.uvwBits                     = tcu::IVec3(7,7,7);
875                 texComparePrecision.pcfBits                     = 5;
876                 texComparePrecision.referenceBits       = 16;
877                 texComparePrecision.resultBits          = pixelFormat.redBits-1;
878
879 #ifdef CTS_USES_VULKANSC
880                 if (m_context.getTestContext().getCommandLine().isSubProcess())
881 #endif // CTS_USES_VULKANSC
882                 {
883                         const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
884                                                                                                                           &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
885
886                         if (!isHighQuality)
887                         {
888                                 log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
889
890                                 lodPrecision.lodBits                    = 4;
891                                 texComparePrecision.uvwBits             = tcu::IVec3(4,4,4);
892                                 texComparePrecision.pcfBits             = 0;
893
894                                 const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
895                                                                                                                  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
896
897                                 if (!isOk)
898                                 {
899                                         log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
900                                         return tcu::TestStatus::fail("Image verification failed");
901                                 }
902                         }
903                 }
904         }
905
906         m_caseNdx += 1;
907         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
908 }
909
910 struct Texture1DShadowTestCaseParameters : public Texture1DTestCaseParameters, public TextureShadowCommonTestCaseParameters
911 {
912 };
913
914 void checkTextureSupport (Context& context, const Texture1DShadowTestCaseParameters& testParameters)
915 {
916 #ifndef CTS_USES_VULKANSC
917         const VkFormatProperties3 formatProperties = context.getFormatProperties(testParameters.format);
918         if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
919                 TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
920 #else
921         DE_UNREF(context);
922         if (!isDepthFormat(testParameters.format))
923                 TCU_THROW(NotSupportedError, "Format cannot be used as depth format");
924 #endif // CTS_USES_VULKANSC
925 }
926
927 class Texture1DShadowTestInstance : public TestInstance
928 {
929 public:
930         typedef Texture1DShadowTestCaseParameters       ParameterType;
931                                                                                                 Texture1DShadowTestInstance             (Context& context, const ParameterType& testParameters);
932                                                                                                 ~Texture1DShadowTestInstance    (void);
933
934         virtual tcu::TestStatus                                         iterate                                                 (void);
935
936 private:
937                                                                                                 Texture1DShadowTestInstance             (const Texture1DShadowTestInstance& other) = delete;
938         Texture1DShadowTestInstance&                            operator=                                               (const Texture1DShadowTestInstance& other) = delete;
939
940         struct FilterCase
941         {
942                 int                     textureIndex;
943
944                 float           minCoord;
945                 float           maxCoord;
946                 float           ref;
947
948                 FilterCase      (void)
949                         : textureIndex(-1)
950                         , minCoord      (0)
951                         , maxCoord      (0)
952                         , ref           (0.0f)
953                 {
954                 }
955
956                 FilterCase      (int tex_, const float ref_, const float& minCoord_, const float& maxCoord_)
957                         : textureIndex  (tex_)
958                         , minCoord              (minCoord_)
959                         , maxCoord              (maxCoord_)
960                         , ref                   (ref_)
961                 {
962                 }
963         };
964
965         const ParameterType&                    m_testParameters;
966         std::vector<TestTexture1DSp>    m_textures;
967         std::vector<FilterCase>                 m_cases;
968
969         TextureRenderer                                 m_renderer;
970
971         int                                                             m_caseNdx;
972 };
973
974 Texture1DShadowTestInstance::Texture1DShadowTestInstance (Context& context, const ParameterType& testParameters)
975         : TestInstance                  (context)
976         , m_testParameters              (testParameters)
977         , m_renderer                    (context, testParameters.sampleCount, TEX1D_VIEWPORT_WIDTH, 1, 1, vk::makeComponentMappingRGBA(), vk::VK_IMAGE_TYPE_1D, vk::VK_IMAGE_VIEW_TYPE_1D)
978         , m_caseNdx                             (0)
979 {
980         // Create 2 textures.
981         m_textures.reserve(2);
982         for (int ndx = 0; ndx < 2; ndx++)
983         {
984                 m_textures.push_back(TestTexture1DSp(new pipeline::TestTexture1D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width)));
985         }
986
987         const int       numLevels       = m_textures[0]->getNumLevels();
988
989         // Fill first gradient texture.
990         for (int levelNdx = 0; levelNdx < numLevels; ++levelNdx)
991         {
992                 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
993         }
994
995         // Fill second with grid texture.
996         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
997         {
998                 const deUint32  step    = 0x00ffffff / numLevels;
999                 const deUint32  rgb             = step*levelNdx;
1000                 const deUint32  colorA  = 0xff000000 | rgb;
1001                 const deUint32  colorB  = 0xff000000 | ~rgb;
1002
1003                 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec(), tcu::RGBA(colorB).toVec());
1004         }
1005
1006         // Upload.
1007         for (std::vector<TestTexture1DSp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
1008         {
1009                 m_renderer.add1DTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
1010         }
1011
1012         // Compute cases.
1013         {
1014                 const bool      compareModeSet          = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL);
1015                 const float refInRangeUpper             = compareModeSet ? 1.0f : 0.5f;
1016                 const float refInRangeLower             = compareModeSet ? 0.0f : 0.5f;
1017                 const float refOutOfBoundsUpper = 1.1f;         // !< lookup function should clamp values to [0, 1] range
1018                 const float refOutOfBoundsLower = -0.1f;
1019
1020                 const struct
1021                 {
1022                         const int       texNdx;
1023                         const float     ref;
1024                         const float     lodX;
1025                         const float     oX;
1026                 }
1027                 cases[] =
1028                 {
1029                         { 0,    refInRangeUpper,                +1.600f,        -1.000f },
1030                         { 0,    refInRangeLower,                -2.000f,        -0.200f },
1031                         { 1,    refInRangeUpper,                +0.140f,        -1.500f },
1032                         { 1,    refInRangeLower,                -0.920f,        +0.400f },
1033                         { 1,    refOutOfBoundsUpper,    -0.390f,        +0.650f },
1034                         { 1,    refOutOfBoundsLower,    -1.550f,        +0.350f },
1035                 };
1036
1037                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1038                 {
1039                         const int       texNdx  = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
1040                         const float ref         = cases[caseNdx].ref;
1041                         const float     lodX    = cases[caseNdx].lodX;
1042                         const float     oX              = cases[caseNdx].oX;
1043                         const float     sX              = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
1044
1045                         m_cases.push_back(FilterCase(texNdx, ref, oX, oX+sX));
1046                 }
1047         }
1048
1049         m_caseNdx = 0;
1050 }
1051
1052 Texture1DShadowTestInstance::~Texture1DShadowTestInstance (void)
1053 {
1054         m_textures.clear();
1055         m_cases.clear();
1056 }
1057
1058 tcu::TestStatus Texture1DShadowTestInstance::iterate (void)
1059 {
1060         tcu::TestLog&                                   log                             = m_context.getTestContext().getLog();
1061         const pipeline::TestTexture1D&  texture                 = m_renderer.get1DTexture(m_cases[m_caseNdx].textureIndex);
1062         const tcu::TextureFormat                texFmt                  = texture.getTextureFormat();
1063         const tcu::TextureFormatInfo    fmtInfo                 = tcu::getTextureFormatInfo(texFmt);
1064         const tcu::ScopedLogSection             section                 (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
1065
1066         const FilterCase&                               curCase                 = m_cases[m_caseNdx];
1067         ReferenceParams                                 sampleParams    (TEXTURETYPE_1D);
1068         tcu::Surface                                    rendered                (m_renderer.getRenderWidth(), 1);
1069         vector<float>                                   texCoord;
1070
1071         // Setup params for reference.
1072         sampleParams.sampler                    = util::createSampler(m_testParameters.wrapS, m_testParameters.minFilter, m_testParameters.magFilter);
1073         sampleParams.sampler.compare    = m_testParameters.compareOp;
1074         sampleParams.samplerType                = SAMPLERTYPE_SHADOW;
1075         sampleParams.lodMode                    = LODMODE_EXACT;
1076         sampleParams.colorBias                  = fmtInfo.lookupBias;
1077         sampleParams.colorScale                 = fmtInfo.lookupScale;
1078         sampleParams.ref                                = curCase.ref;
1079
1080         log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;
1081
1082         // Compute texture coordinates.
1083         log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
1084         computeQuadTexCoord1D(texCoord, curCase.minCoord, curCase.maxCoord);
1085
1086         m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
1087
1088         {
1089                 const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1090                 tcu::LodPrecision                       lodPrecision;
1091                 tcu::TexComparePrecision        texComparePrecision;
1092
1093                 lodPrecision.derivateBits                       = 18;
1094                 lodPrecision.lodBits                            = 6;
1095                 texComparePrecision.coordBits           = tcu::IVec3(20,0,0);
1096                 texComparePrecision.uvwBits                     = tcu::IVec3(7,0,0);
1097                 texComparePrecision.pcfBits                     = 5;
1098                 texComparePrecision.referenceBits       = 16;
1099                 texComparePrecision.resultBits          = pixelFormat.redBits-1;
1100
1101 #ifdef CTS_USES_VULKANSC
1102                 if (m_context.getTestContext().getCommandLine().isSubProcess())
1103 #endif // CTS_USES_VULKANSC
1104                 {
1105                         const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1106                                                                                                                           &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1107
1108                         if (!isHighQuality)
1109                         {
1110                                 m_context.getTestContext().getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
1111
1112                                 lodPrecision.lodBits                    = 4;
1113                                 texComparePrecision.uvwBits             = tcu::IVec3(4,0,0);
1114                                 texComparePrecision.pcfBits             = 0;
1115
1116                                 const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1117                                                                                                                  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1118
1119                                 if (!isOk)
1120                                 {
1121                                         m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
1122                                         return tcu::TestStatus::fail("Image verification failed");
1123                                 }
1124                         }
1125                 }
1126         }
1127
1128         m_caseNdx += 1;
1129         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1130 }
1131
1132 struct Texture1DArrayShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public Texture1DArrayTestCaseParameters
1133 {
1134 };
1135
1136 void checkTextureSupport (Context& context, const Texture1DArrayShadowTestCaseParameters& testParameters)
1137 {
1138 #ifndef CTS_USES_VULKANSC
1139         const VkFormatProperties3 formatProperties = context.getFormatProperties(testParameters.format);
1140         if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
1141                 TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
1142 #else
1143         DE_UNREF(context);
1144         if (!isDepthFormat(testParameters.format))
1145                 TCU_THROW(NotSupportedError, "Format cannot be used as depth format");
1146 #endif // CTS_USES_VULKANSC
1147 }
1148
1149 class Texture1DArrayShadowTestInstance : public TestInstance
1150 {
1151 public:
1152         typedef Texture1DArrayShadowTestCaseParameters  ParameterType;
1153                                                                                                         Texture1DArrayShadowTestInstance                (Context& context, const ParameterType& testParameters);
1154                                                                                                         ~Texture1DArrayShadowTestInstance               (void);
1155
1156         virtual tcu::TestStatus                                                 iterate                                                                 (void);
1157
1158 private:
1159                                                                                                         Texture1DArrayShadowTestInstance                (const Texture1DArrayShadowTestInstance& other) = delete;
1160         Texture1DArrayShadowTestInstance&                               operator=                                                               (const Texture1DArrayShadowTestInstance& other) = delete;
1161
1162         struct FilterCase
1163         {
1164                 int                                                     textureIndex;
1165                 tcu::Vec2                                       minCoord;
1166                 tcu::Vec2                                       maxCoord;
1167                 float                                           ref;
1168
1169                 FilterCase (void)
1170                         : textureIndex  (-1)
1171                         , ref                   (0.0f)
1172                 {
1173                 }
1174
1175                 FilterCase (const int tex_, float ref_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
1176                         : textureIndex  (tex_)
1177                         , minCoord              (minCoord_)
1178                         , maxCoord              (maxCoord_)
1179                         , ref                   (ref_)
1180                 {
1181                 }
1182         };
1183
1184         const ParameterType&                            m_testParameters;
1185         std::vector<TestTexture1DArraySp>       m_textures;
1186         std::vector<FilterCase>                         m_cases;
1187
1188         TextureRenderer                                         m_renderer;
1189
1190         int                                                                     m_caseNdx;
1191 };
1192
1193 Texture1DArrayShadowTestInstance::Texture1DArrayShadowTestInstance (Context& context, const ParameterType& testParameters)
1194         : TestInstance                  (context)
1195         , m_testParameters              (testParameters)
1196         , m_renderer                    (context, testParameters.sampleCount, TEX1D_VIEWPORT_WIDTH, 1)
1197         , m_caseNdx                             (0)
1198 {
1199         const int                                               numLevels       = deLog2Floor32(m_testParameters.width) + 1;
1200         const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
1201         const tcu::Vec4                                 cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
1202         const tcu::Vec4                                 cBias           = fmtInfo.valueMin;
1203
1204         // Create 2 textures.
1205         m_textures.reserve(2);
1206         for (int ndx = 0; ndx < 2; ndx++)
1207         {
1208                 m_textures.push_back(TestTexture1DArraySp(new pipeline::TestTexture1DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.numLayers)));
1209         }
1210
1211         // Fill first gradient texture.
1212         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1213         {
1214                 const tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
1215                 const tcu::Vec4 gMax = tcu::Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
1216
1217                 tcu::fillWithComponentGradients(m_textures[0]->getTexture().getLevel(levelNdx), gMin, gMax);
1218         }
1219
1220         // Fill second with grid texture.
1221         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1222         {
1223                 const deUint32  step    = 0x00ffffff / numLevels;
1224                 const deUint32  rgb             = step*levelNdx;
1225                 const deUint32  colorA  = 0xff000000 | rgb;
1226                 const deUint32  colorB  = 0xff000000 | ~rgb;
1227
1228                 tcu::fillWithGrid(m_textures[1]->getTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1229         }
1230
1231         // Upload.
1232         for (std::vector<TestTexture1DArraySp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
1233         {
1234                 m_renderer.add1DArrayTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
1235         }
1236
1237         // Compute cases.
1238         {
1239                 const bool      compareModeSet          = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL);
1240                 const float     refInRangeUpper         = compareModeSet ? 1.0f : 0.5f;
1241                 const float     refInRangeLower         = compareModeSet ? 0.0f : 0.5f;
1242                 const float     refOutOfBoundsUpper     = 1.1f;         // !< lookup function should clamp values to [0, 1] range
1243                 const float     refOutOfBoundsLower     = -0.1f;
1244
1245                 const struct
1246                 {
1247                         const int       texNdx;
1248                         const float     ref;
1249                         const float     lodX;
1250                         const float     oX;
1251                 }
1252                 cases[] =
1253                 {
1254                         { 0,    refInRangeUpper,                1.6f,   -1.0f,  },
1255                         { 0,    refInRangeLower,                -2.0f,  -0.2f,  },
1256                         { 1,    refInRangeUpper,                0.14f,  -1.5f,  },
1257                         { 1,    refInRangeLower,                -0.92f, 0.4f,   },
1258                         { 1,    refOutOfBoundsUpper,    -0.49f, 0.45f,  },
1259                         { 1,    refOutOfBoundsLower,    -0.85f, 0.25f,  },
1260                 };
1261
1262                 const float     minLayer        = -0.5f;
1263                 const float     maxLayer        = (float)m_testParameters.numLayers;
1264
1265                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1266                 {
1267                         const int       tex             = cases[caseNdx].texNdx > 0 ? 1 : 0;
1268                         const float     ref             = cases[caseNdx].ref;
1269                         const float     lodX    = cases[caseNdx].lodX;
1270                         const float     oX              = cases[caseNdx].oX;
1271                         const float     sX              = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[tex]->getTexture().getWidth());
1272
1273                         m_cases.push_back(FilterCase(tex, ref, tcu::Vec2(oX, minLayer), tcu::Vec2(oX+sX, maxLayer)));
1274                 }
1275         }
1276 }
1277
1278 Texture1DArrayShadowTestInstance::~Texture1DArrayShadowTestInstance (void)
1279 {
1280 }
1281
1282 tcu::TestStatus Texture1DArrayShadowTestInstance::iterate (void)
1283 {
1284         tcu::TestLog&                                           log                             = m_context.getTestContext().getLog();
1285         const FilterCase&                                       curCase                 = m_cases[m_caseNdx];
1286         const pipeline::TestTexture1DArray&     texture                 = m_renderer.get1DArrayTexture(curCase.textureIndex);
1287
1288         ReferenceParams                                         sampleParams    (TEXTURETYPE_1D_ARRAY);
1289         tcu::Surface                                            rendered                (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
1290         const tcu::ScopedLogSection                     section                 (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
1291
1292         const float                                                     texCoord[]              =
1293         {
1294                 curCase.minCoord.x(), curCase.minCoord.y(),
1295                 curCase.minCoord.x(), (curCase.minCoord.y() + curCase.maxCoord.y()) / 2.0f,
1296                 curCase.maxCoord.x(), (curCase.minCoord.y() + curCase.maxCoord.y()) / 2.0f,
1297                 curCase.maxCoord.x(), curCase.maxCoord.y()
1298         };
1299
1300         // Setup params for reference.
1301         sampleParams.sampler                    = util::createSampler(m_testParameters.wrapS, m_testParameters.minFilter, m_testParameters.magFilter);
1302         sampleParams.sampler.compare    = m_testParameters.compareOp;
1303         sampleParams.samplerType                = SAMPLERTYPE_SHADOW;
1304         sampleParams.lodMode                    = LODMODE_EXACT;
1305         sampleParams.ref                                = curCase.ref;
1306
1307         log     << TestLog::Message
1308                 << "Compare reference value = " << sampleParams.ref << "\n"
1309                 << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord
1310                 << TestLog::EndMessage;
1311
1312         m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
1313
1314         {
1315                 const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1316                 tcu::LodPrecision                       lodPrecision;
1317                 tcu::TexComparePrecision        texComparePrecision;
1318
1319                 lodPrecision.derivateBits                       = 18;
1320                 lodPrecision.lodBits                            = 6;
1321                 texComparePrecision.coordBits           = tcu::IVec3(20,20,20);
1322                 texComparePrecision.uvwBits                     = tcu::IVec3(7,7,7);
1323                 texComparePrecision.pcfBits                     = 5;
1324                 texComparePrecision.referenceBits       = 16;
1325                 texComparePrecision.resultBits          = pixelFormat.redBits-1;
1326
1327 #ifdef CTS_USES_VULKANSC
1328                 if (m_context.getTestContext().getCommandLine().isSubProcess())
1329 #endif // CTS_USES_VULKANSC
1330                 {
1331                         const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1332                                                                                                                           &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1333
1334                         if (!isHighQuality)
1335                         {
1336                                 log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
1337
1338                                 lodPrecision.lodBits                    = 4;
1339                                 texComparePrecision.uvwBits             = tcu::IVec3(4,4,4);
1340                                 texComparePrecision.pcfBits             = 0;
1341
1342                                 const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1343                                                                                                                  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1344
1345                                 if (!isOk)
1346                                 {
1347                                         log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
1348                                         return tcu::TestStatus::fail("Image verification failed");
1349                                 }
1350                         }
1351                 }
1352         }
1353
1354         m_caseNdx += 1;
1355         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1356 }
1357
1358 struct TextureCubeArrayShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public TextureCubeArrayTestCaseParameters
1359 {
1360 };
1361
1362 void checkTextureSupport (Context& context, const TextureCubeArrayShadowTestCaseParameters& testParameters)
1363 {
1364 #ifndef CTS_USES_VULKANSC
1365         const VkFormatProperties3 formatProperties = context.getFormatProperties(testParameters.format);
1366         if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
1367                 TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
1368         if (!testParameters.seamless)
1369                 context.requireDeviceFunctionality("VK_EXT_non_seamless_cube_map");
1370 #else
1371         DE_UNREF(context);
1372         if (!isDepthFormat(testParameters.format))
1373                 TCU_THROW(NotSupportedError, "Format cannot be used as depth format");
1374 #endif // CTS_USES_VULKANSC
1375 }
1376
1377 class TextureCubeArrayShadowTestInstance : public TestInstance
1378 {
1379 public:
1380         typedef TextureCubeArrayShadowTestCaseParameters        ParameterType;
1381                                                                                                                 TextureCubeArrayShadowTestInstance      (Context& context, const ParameterType& testParameters);
1382                                                                                                                 ~TextureCubeArrayShadowTestInstance     (void);
1383
1384         virtual tcu::TestStatus                                                         iterate                                                         (void);
1385
1386 private:
1387                                                                                                                 TextureCubeArrayShadowTestInstance      (const TextureCubeArrayShadowTestInstance& other);
1388         TextureCubeArrayShadowTestInstance&                                     operator=                                                       (const TextureCubeArrayShadowTestInstance& other);
1389
1390         struct FilterCase
1391         {
1392                 int                                             textureIndex;
1393                 tcu::Vec2                               bottomLeft;
1394                 tcu::Vec2                               topRight;
1395                 float                                   ref;
1396
1397                 FilterCase (void)
1398                         : textureIndex  (-1)
1399                         , ref                   (0.0f)
1400                 {
1401                 }
1402
1403                 FilterCase (const int tex_, const float ref_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
1404                         : textureIndex  (tex_)
1405                         , bottomLeft    (bottomLeft_)
1406                         , topRight              (topRight_)
1407                         , ref                   (ref_)
1408                 {
1409                 }
1410         };
1411
1412         const ParameterType&                    m_testParameters;
1413         vector<TestTextureCubeArraySp>  m_textures;
1414         std::vector<FilterCase>                 m_cases;
1415
1416         TextureRenderer                                 m_renderer;
1417         int                                                             m_caseNdx;
1418 };
1419
1420 TextureCubeArrayShadowTestInstance::TextureCubeArrayShadowTestInstance (Context& context, const ParameterType& testParameters)
1421         : TestInstance                  (context)
1422         , m_testParameters              (testParameters)
1423         , m_renderer                    (context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
1424         , m_caseNdx                             (0)
1425 {
1426         const int                                               numLevels       = deLog2Floor32(m_testParameters.size)+1;
1427         const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
1428         const tcu::Vec4                                 cBias           = fmtInfo.valueMin;
1429         const tcu::Vec4                                 cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
1430
1431         // Create textures.
1432
1433         m_textures.reserve(2);
1434         for (int ndx = 0; ndx < 2; ndx++)
1435         {
1436                 m_textures.push_back(TestTextureCubeArraySp(new pipeline::TestTextureCubeArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.size, m_testParameters.numLayers)));
1437         }
1438
1439         // Fill first with gradient texture.
1440         static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
1441         {
1442                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
1443                 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
1444                 { tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
1445                 { tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
1446                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
1447                 { tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
1448         };
1449
1450         for (int layerFace = 0; layerFace < m_textures[0]->getArraySize(); layerFace++)
1451         {
1452                 const int               face            = layerFace % 6;
1453                 const int               layer           = layerFace / 6;
1454                 const tcu::Vec4 gradient0       = gradients[face][0] / float(layer + 1);
1455                 const tcu::Vec4 gradient1       = gradients[face][1] / float(layer + 1);
1456
1457                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1458                 {
1459                         tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, layerFace), gradient0*cScale + cBias, gradient1*cScale + cBias);
1460                 }
1461         }
1462
1463         // Fill second with grid texture.
1464         for (int layerFace = 0; layerFace < m_textures[1]->getArraySize(); layerFace++)
1465         {
1466                 const int       face            = layerFace % 6;
1467                 const int       layer           = layerFace / 6;
1468                 const int       cellSize        = 4 + layer;
1469
1470                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1471                 {
1472                         const deUint32  step    = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
1473                         const deUint32  rgb             = step*levelNdx*face;
1474                         const deUint32  colorA  = 0xff000000 | rgb;
1475                         const deUint32  colorB  = 0xff000000 | ~rgb;
1476
1477                         tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, layerFace), cellSize, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1478                 }
1479         }
1480
1481         // Upload.
1482         for (vector<TestTextureCubeArraySp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
1483         {
1484                 m_renderer.addCubeArrayTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
1485         }
1486
1487         // Compute cases
1488         {
1489                 const bool      compareModeSet          = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL);
1490                 const float refInRangeUpper             = compareModeSet ? 1.0f : 0.5f;
1491                 const float refInRangeLower             = compareModeSet ? 0.0f : 0.5f;
1492                 const float refOutOfBoundsUpper = 1.1f;
1493                 const float refOutOfBoundsLower = -0.1f;
1494
1495                 m_cases.push_back(FilterCase(0, refInRangeUpper,                tcu::Vec2(-1.25f, -1.2f),       tcu::Vec2(1.2f, 1.25f)));       // minification
1496                 m_cases.push_back(FilterCase(0, refInRangeLower,                tcu::Vec2(0.8f, 0.8f),          tcu::Vec2(1.25f, 1.20f)));      // magnification
1497                 m_cases.push_back(FilterCase(1, refInRangeUpper,                tcu::Vec2(-1.19f, -1.3f),       tcu::Vec2(1.1f, 1.35f)));       // minification
1498                 m_cases.push_back(FilterCase(1, refInRangeLower,                tcu::Vec2(-1.2f, -1.1f),        tcu::Vec2(-0.8f, -0.8f)));      // magnification
1499                 m_cases.push_back(FilterCase(1, refOutOfBoundsUpper,    tcu::Vec2(-0.61f, -0.1f),       tcu::Vec2(0.9f, 1.18f)));       // reference value clamp, upper
1500                 m_cases.push_back(FilterCase(1, refOutOfBoundsLower,    tcu::Vec2(-0.75f, 1.0f),        tcu::Vec2(0.05f, 0.75f)));      // reference value clamp, lower
1501         }
1502 }
1503
1504 TextureCubeArrayShadowTestInstance::~TextureCubeArrayShadowTestInstance (void)
1505 {
1506 }
1507
1508 tcu::TestStatus TextureCubeArrayShadowTestInstance::iterate (void)
1509 {
1510
1511         tcu::TestLog&                                                   log                             = m_context.getTestContext().getLog();
1512         const tcu::ScopedLogSection                             iterSection             (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
1513         const FilterCase&                                               curCase                 = m_cases[m_caseNdx];
1514         const pipeline::TestTextureCubeArray&   texture                 = m_renderer.getCubeArrayTexture(curCase.textureIndex);
1515
1516         ReferenceParams                                                 sampleParams    (TEXTURETYPE_CUBE_ARRAY);
1517
1518         // Params for reference computation.
1519         sampleParams.sampler                                    = util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
1520         sampleParams.sampler.seamlessCubeMap    = m_testParameters.seamless;
1521         sampleParams.sampler.compare                    = m_testParameters.compareOp;
1522         sampleParams.samplerType                                = SAMPLERTYPE_SHADOW;
1523         sampleParams.lodMode                                    = LODMODE_EXACT;
1524         sampleParams.ref                                                = curCase.ref;
1525
1526         log     << TestLog::Message
1527                 << "Compare reference value = " << sampleParams.ref << "\n"
1528                 << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight
1529                 << TestLog::EndMessage;
1530
1531         for (int layerFace = 0; layerFace < m_textures[curCase.textureIndex]->getArraySize(); layerFace++)
1532         {
1533                 const tcu::CubeFace             face            = tcu::CubeFace(layerFace % 6);
1534                 const int                               layer           = layerFace / 6;
1535                 const float                             minLayer        = -0.5f + float(layer);
1536                 const float                             maxLayer        = (float)m_testParameters.numLayers;
1537                 tcu::Surface                    result          (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
1538                 vector<float>                   texCoord;
1539
1540                 computeQuadTexCoordCubeArray(texCoord, face, curCase.bottomLeft, curCase.topRight, tcu::Vec2(minLayer, maxLayer));
1541
1542                 log << TestLog::Message << "Face " << getFaceDesc(face) << " at layer " << layer << TestLog::EndMessage;
1543
1544                 // \todo Log texture coordinates.
1545
1546                 m_renderer.renderQuad(result, curCase.textureIndex, &texCoord[0], sampleParams);
1547
1548                 {
1549                         const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1550                         tcu::LodPrecision                       lodPrecision;
1551                         tcu::TexComparePrecision        texComparePrecision;
1552
1553                         lodPrecision.derivateBits                       = 10;
1554                         lodPrecision.lodBits                            = 5;
1555                         texComparePrecision.coordBits           = tcu::IVec3(10,10,10);
1556                         texComparePrecision.uvwBits                     = tcu::IVec3(6,6,0);
1557                         texComparePrecision.pcfBits                     = 5;
1558                         texComparePrecision.referenceBits       = 16;
1559                         texComparePrecision.resultBits          = pixelFormat.redBits-1;
1560
1561 #ifdef CTS_USES_VULKANSC
1562                         if (m_context.getTestContext().getCommandLine().isSubProcess())
1563 #endif // CTS_USES_VULKANSC
1564                         {
1565                                 const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
1566                                                                                                                           &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1567
1568                                 if (!isHighQuality)
1569                                 {
1570                                         log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
1571
1572                                         lodPrecision.lodBits                    = 4;
1573                                         texComparePrecision.uvwBits             = tcu::IVec3(4,4,0);
1574                                         texComparePrecision.pcfBits             = 0;
1575
1576                                         const bool isOk = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
1577                                                                                                                          &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1578
1579                                         if (!isOk)
1580                                         {
1581                                                 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
1582                                                 return tcu::TestStatus::fail("Image verification failed");
1583                                         }
1584                                 }
1585                         }
1586                 }
1587         }
1588
1589         m_caseNdx += 1;
1590         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1591 }
1592 } // anonymous
1593
1594 void populateTextureShadowTests (tcu::TestCaseGroup* textureShadowTests)
1595 {
1596         tcu::TestContext&                               testCtx                         = textureShadowTests->getTestContext();
1597
1598         static const struct
1599         {
1600                 const char*                                                             name;
1601                 const TextureBinding::ImageBackingMode  backingMode;
1602         } backingModes[] =
1603         {
1604                 { "",                   TextureBinding::IMAGE_BACKING_MODE_REGULAR      },
1605 #ifndef CTS_USES_VULKANSC
1606                 { "sparse_",    TextureBinding::IMAGE_BACKING_MODE_SPARSE       }
1607 #endif // CTS_USES_VULKANSC
1608         };
1609
1610         static const struct
1611         {
1612                 const char*                                                             name;
1613                 const VkFormat                                                  format;
1614                 const VkImageAspectFlags                                aspect;
1615         } formats[] =
1616         {
1617                 { "d16_unorm",                          VK_FORMAT_D16_UNORM,                    VK_IMAGE_ASPECT_DEPTH_BIT       },
1618                 { "x8_d24_unorm_pack32",        VK_FORMAT_X8_D24_UNORM_PACK32,  VK_IMAGE_ASPECT_DEPTH_BIT       },
1619                 { "d32_sfloat",                         VK_FORMAT_D32_SFLOAT,                   VK_IMAGE_ASPECT_DEPTH_BIT       },
1620                 { "d16_unorm_s8_uint",          VK_FORMAT_D16_UNORM_S8_UINT,    VK_IMAGE_ASPECT_DEPTH_BIT       },
1621                 { "d24_unorm_s8_uint",          VK_FORMAT_D24_UNORM_S8_UINT,    VK_IMAGE_ASPECT_DEPTH_BIT       },
1622                 { "d32_sfloat_s8_uint",         VK_FORMAT_D32_SFLOAT_S8_UINT,   VK_IMAGE_ASPECT_DEPTH_BIT       },
1623                 { "r16_unorm",                          VK_FORMAT_R16_UNORM,                    VK_IMAGE_ASPECT_COLOR_BIT       },
1624                 { "r32_sfloat",                         VK_FORMAT_R32_SFLOAT,                   VK_IMAGE_ASPECT_COLOR_BIT       }
1625         };
1626
1627         static const struct
1628         {
1629                 const char*                                                             name;
1630                 const Sampler::FilterMode                               minFilter;
1631                 const Sampler::FilterMode                               magFilter;
1632         } filters[] =
1633         {
1634                 { "nearest",                            Sampler::NEAREST,                                       Sampler::NEAREST        },
1635                 { "linear",                                     Sampler::LINEAR,                                        Sampler::LINEAR         },
1636                 { "nearest_mipmap_nearest",     Sampler::NEAREST_MIPMAP_NEAREST,        Sampler::LINEAR         },
1637                 { "linear_mipmap_nearest",      Sampler::LINEAR_MIPMAP_NEAREST,         Sampler::LINEAR         },
1638                 { "nearest_mipmap_linear",      Sampler::NEAREST_MIPMAP_LINEAR,         Sampler::LINEAR         },
1639                 { "linear_mipmap_linear",       Sampler::LINEAR_MIPMAP_LINEAR,          Sampler::LINEAR         }
1640         };
1641
1642         static const struct
1643         {
1644                 const char*                                                             name;
1645                 const Sampler::CompareMode                              op;
1646         } compareOp[] =
1647         {
1648                 { "less_or_equal",              Sampler::COMPAREMODE_LESS_OR_EQUAL              },
1649                 { "greater_or_equal",   Sampler::COMPAREMODE_GREATER_OR_EQUAL   },
1650                 { "less",                               Sampler::COMPAREMODE_LESS                               },
1651                 { "greater",                    Sampler::COMPAREMODE_GREATER                    },
1652                 { "equal",                              Sampler::COMPAREMODE_EQUAL                              },
1653                 { "not_equal",                  Sampler::COMPAREMODE_NOT_EQUAL                  },
1654                 { "always",                             Sampler::COMPAREMODE_ALWAYS                             },
1655                 { "never",                              Sampler::COMPAREMODE_NEVER                              }
1656         };
1657
1658         static const struct
1659         {
1660                 const char*                                                             name;
1661                 deBool                                                                  seamless;
1662         } seamModes[] =
1663         {
1664                 {"",                            true},
1665 #ifndef CTS_USES_VULKANSC
1666                 {"non_seamless_",       false}
1667 #endif // CTS_USES_VULKANSC
1668         };
1669
1670         // 2D cases.
1671         {
1672                 de::MovePtr<tcu::TestCaseGroup> group2D (new tcu::TestCaseGroup(testCtx, "2d", "2D texture shadow lookup tests"));
1673
1674                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1675                 {
1676                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1677
1678                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1679                         {
1680                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1681                                 {
1682                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1683                                         {
1684                                                 const string                                            name    = string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1685                                                 Texture2DShadowTestCaseParameters       testParameters;
1686
1687                                                 testParameters.minFilter        = filters[filterNdx].minFilter;
1688                                                 testParameters.magFilter        = filters[filterNdx].magFilter;
1689                                                 testParameters.format           = formats[formatNdx].format;
1690                                                 testParameters.backingMode      = backingModes[backingNdx].backingMode;
1691                                                 testParameters.compareOp        = compareOp[compareNdx].op;
1692                                                 testParameters.wrapS            = Sampler::REPEAT_GL;
1693                                                 testParameters.wrapT            = Sampler::REPEAT_GL;
1694                                                 testParameters.width            = 32;
1695                                                 testParameters.height           = 64;
1696                                                 testParameters.aspectMask       = formats[formatNdx].aspect;
1697                                                 testParameters.programs.push_back(PROGRAM_2D_SHADOW);
1698
1699                                                 filterGroup->addChild(new TextureTestCase<Texture2DShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1700                                         }
1701                                 }
1702                         }
1703
1704                         group2D->addChild(filterGroup.release());
1705                 }
1706
1707                 textureShadowTests->addChild(group2D.release());
1708         }
1709
1710         // Cubemap cases.
1711         {
1712                 de::MovePtr<tcu::TestCaseGroup> groupCube       (new tcu::TestCaseGroup(testCtx, "cube", "Cube map texture shadow lookup tests"));
1713
1714                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1715                 {
1716                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1717
1718                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1719                         {
1720                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1721                                 {
1722                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1723                                         {
1724                                                 for (int seamNdx = 0; seamNdx < DE_LENGTH_OF_ARRAY(seamModes); seamNdx++)
1725                                                 {
1726                                                         const string                                                    name    = string(backingModes[backingNdx].name) + seamModes[seamNdx].name + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1727                                                         TextureCubeShadowTestCaseParameters             testParameters;
1728
1729                                                         testParameters.minFilter        = filters[filterNdx].minFilter;
1730                                                         testParameters.magFilter        = filters[filterNdx].magFilter;
1731                                                         testParameters.format           = formats[formatNdx].format;
1732                                                         testParameters.backingMode      = backingModes[backingNdx].backingMode;
1733                                                         testParameters.seamless         = seamModes[seamNdx].seamless;
1734                                                         testParameters.compareOp        = compareOp[compareNdx].op;
1735                                                         testParameters.wrapS            = Sampler::REPEAT_GL;
1736                                                         testParameters.wrapT            = Sampler::REPEAT_GL;
1737                                                         testParameters.size                     = 32;
1738                                                         testParameters.aspectMask       = formats[formatNdx].aspect;
1739
1740                                                         testParameters.programs.push_back(PROGRAM_CUBE_SHADOW);
1741
1742                                                         filterGroup->addChild(new TextureTestCase<TextureCubeShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1743                                                 }
1744                                         }
1745                                 }
1746                         }
1747
1748                         groupCube->addChild(filterGroup.release());
1749                 }
1750
1751                 textureShadowTests->addChild(groupCube.release());
1752         }
1753
1754         // 2D array cases.
1755         {
1756                 de::MovePtr<tcu::TestCaseGroup> group2DArray    (new tcu::TestCaseGroup(testCtx, "2d_array", "2D texture array shadow lookup tests"));
1757
1758                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1759                 {
1760                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1761
1762                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1763                         {
1764                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1765                                 {
1766                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1767                                         {
1768                                                 const string                                                    name    = string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1769                                                 Texture2DArrayShadowTestCaseParameters  testParameters;
1770
1771                                                 testParameters.minFilter        = filters[filterNdx].minFilter;
1772                                                 testParameters.magFilter        = filters[filterNdx].magFilter;
1773                                                 testParameters.format           = formats[formatNdx].format;
1774                                                 testParameters.backingMode      = backingModes[backingNdx].backingMode;
1775                                                 testParameters.compareOp        = compareOp[compareNdx].op;
1776                                                 testParameters.wrapS            = Sampler::REPEAT_GL;
1777                                                 testParameters.wrapT            = Sampler::REPEAT_GL;
1778                                                 testParameters.width            = 32;
1779                                                 testParameters.height           = 64;
1780                                                 testParameters.numLayers        = 8;
1781                                                 testParameters.aspectMask       = formats[formatNdx].aspect;
1782
1783                                                 testParameters.programs.push_back(PROGRAM_2D_ARRAY_SHADOW);
1784
1785                                                 filterGroup->addChild(new TextureTestCase<Texture2DArrayShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1786                                         }
1787                                 }
1788                         }
1789
1790                         group2DArray->addChild(filterGroup.release());
1791                 }
1792
1793                 textureShadowTests->addChild(group2DArray.release());
1794         }
1795
1796         // 1D cases.
1797         {
1798                 de::MovePtr<tcu::TestCaseGroup> group1D (new tcu::TestCaseGroup(testCtx, "1d", "1D texture shadow lookup tests"));
1799
1800                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1801                 {
1802                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1803
1804                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1805                         {
1806                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1807                                 {
1808                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1809                                         {
1810                                                 const string                                            name                    = string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1811                                                 Texture1DShadowTestCaseParameters       testParameters;
1812
1813                                                 testParameters.minFilter        = filters[filterNdx].minFilter;
1814                                                 testParameters.magFilter        = filters[filterNdx].magFilter;
1815                                                 testParameters.format           = formats[formatNdx].format;
1816                                                 testParameters.backingMode      = backingModes[backingNdx].backingMode;
1817                                                 testParameters.compareOp        = compareOp[compareNdx].op;
1818                                                 testParameters.wrapS            = Sampler::REPEAT_GL;
1819                                                 testParameters.width            = 32;
1820                                                 testParameters.aspectMask       = formats[formatNdx].aspect;
1821                                                 testParameters.programs.push_back(PROGRAM_1D_SHADOW);
1822
1823                                                 filterGroup->addChild(new TextureTestCase<Texture1DShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1824                                         }
1825                                 }
1826                         }
1827
1828                         group1D->addChild(filterGroup.release());
1829                 }
1830
1831                 textureShadowTests->addChild(group1D.release());
1832         }
1833
1834         // 1D array cases.
1835         {
1836                 de::MovePtr<tcu::TestCaseGroup> group1DArray    (new tcu::TestCaseGroup(testCtx, "1d_array", "1D texture array shadow lookup tests"));
1837
1838                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1839                 {
1840                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1841
1842                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1843                         {
1844                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1845                                 {
1846                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1847                                         {
1848                                                 const string                                                    name                    = string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1849                                                 Texture1DArrayShadowTestCaseParameters  testParameters;
1850
1851                                                 testParameters.minFilter        = filters[filterNdx].minFilter;
1852                                                 testParameters.magFilter        = filters[filterNdx].magFilter;
1853                                                 testParameters.format           = formats[formatNdx].format;
1854                                                 testParameters.backingMode      = backingModes[backingNdx].backingMode;
1855                                                 testParameters.compareOp        = compareOp[compareNdx].op;
1856                                                 testParameters.wrapS            = Sampler::REPEAT_GL;
1857                                                 testParameters.width            = 32;
1858                                                 testParameters.numLayers        = 8;
1859                                                 testParameters.aspectMask       = formats[formatNdx].aspect;
1860
1861                                                 testParameters.programs.push_back(PROGRAM_1D_ARRAY_SHADOW);
1862
1863                                                 filterGroup->addChild(new TextureTestCase<Texture1DArrayShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1864                                         }
1865                                 }
1866                         }
1867
1868                         group1DArray->addChild(filterGroup.release());
1869                 }
1870
1871                 textureShadowTests->addChild(group1DArray.release());
1872         }
1873
1874         // Cubemap Array cases.
1875         {
1876                 de::MovePtr<tcu::TestCaseGroup> groupCubeArray  (new tcu::TestCaseGroup(testCtx, "cube_array", "Cube map texture shadow lookup tests"));
1877
1878                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1879                 {
1880                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1881
1882                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1883                         {
1884                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1885                                 {
1886                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1887                                         {
1888                                                 for (int seamNdx = 0; seamNdx < DE_LENGTH_OF_ARRAY(seamModes); seamNdx++)
1889                                                 {
1890                                                         const string                                                            name    = string(backingModes[backingNdx].name) + seamModes[seamNdx].name + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1891                                                         TextureCubeArrayShadowTestCaseParameters        testParameters;
1892
1893                                                         testParameters.minFilter        = filters[filterNdx].minFilter;
1894                                                         testParameters.magFilter        = filters[filterNdx].magFilter;
1895                                                         testParameters.format           = formats[formatNdx].format;
1896                                                         testParameters.backingMode      = backingModes[backingNdx].backingMode;
1897                                                         testParameters.compareOp        = compareOp[compareNdx].op;
1898                                                         testParameters.seamless         = seamModes[seamNdx].seamless;
1899                                                         testParameters.wrapS            = Sampler::REPEAT_GL;
1900                                                         testParameters.wrapT            = Sampler::REPEAT_GL;
1901                                                         testParameters.size                     = 32;
1902                                                         testParameters.numLayers        = 4 * 6;
1903                                                         testParameters.aspectMask       = formats[formatNdx].aspect;
1904
1905                                                         testParameters.programs.push_back(PROGRAM_CUBE_ARRAY_SHADOW);
1906
1907                                                         filterGroup->addChild(new TextureTestCase<TextureCubeArrayShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1908                                                 }
1909                                         }
1910                                 }
1911                         }
1912
1913                         groupCubeArray->addChild(filterGroup.release());
1914                 }
1915
1916                 textureShadowTests->addChild(groupCubeArray.release());
1917         }
1918 #ifndef CTS_USES_VULKANSC
1919         // Texel replacement tests.
1920         {
1921                 de::MovePtr<tcu::TestCaseGroup> groupTexelReplacement   (new tcu::TestCaseGroup(testCtx, "texel_replacement", "Texel replacement texture shadow lookup tests"));
1922
1923                 cts_amber::AmberTestCase*               testCaseLod                             = cts_amber::createAmberTestCase(testCtx, "d32_sfloat", "", "texture/shadow/texel_replacement", "d32_sfloat.amber");
1924
1925                 groupTexelReplacement->addChild(testCaseLod);
1926                 textureShadowTests->addChild(groupTexelReplacement.release());
1927         }
1928 #endif // CTS_USES_VULKANSC
1929 }
1930
1931 tcu::TestCaseGroup* createTextureShadowTests (tcu::TestContext& testCtx)
1932 {
1933         return createTestGroup(testCtx, "shadow", "Texture shadow tests.", populateTextureShadowTests);
1934 }
1935
1936 } // texture
1937 } // vkt