Add testing for sparse D/S/DS images.
[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
28 #include "deMath.h"
29 #include "deString.h"
30 #include "deStringUtil.hpp"
31 #include "gluPixelTransfer.hpp"
32 #include "gluTextureTestUtil.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuImageIO.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuTexCompareVerifier.hpp"
38 #include "tcuTexVerifierUtil.hpp"
39 #include "tcuTexture.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vktTestGroupUtil.hpp"
44 #include "vktTextureTestUtil.hpp"
45
46 using namespace vk;
47
48 namespace vkt
49 {
50 namespace texture
51 {
52 namespace
53 {
54
55 using std::vector;
56 using std::string;
57 using tcu::TestLog;
58 using tcu::Sampler;
59 using namespace texture::util;
60 using namespace glu::TextureTestUtil;
61
62 enum
63 {
64         TEXCUBE_VIEWPORT_SIZE   = 28,
65         TEX2D_VIEWPORT_WIDTH    = 64,
66         TEX2D_VIEWPORT_HEIGHT   = 64
67 };
68
69 struct TextureShadowCommonTestCaseParameters
70 {
71                                                                                 TextureShadowCommonTestCaseParameters   (void);
72         Sampler::CompareMode                            compareOp;
73         TextureBinding::ImageBackingMode        backingMode;
74 };
75
76 TextureShadowCommonTestCaseParameters::TextureShadowCommonTestCaseParameters (void)
77         : compareOp                                                     (Sampler::COMPAREMODE_EQUAL)
78         , backingMode                                           (TextureBinding::IMAGE_BACKING_MODE_REGULAR)
79 {
80 }
81
82 struct Texture2DShadowTestCaseParameters : public Texture2DTestCaseParameters, public TextureShadowCommonTestCaseParameters
83 {
84 };
85
86 bool isFloatingPointDepthFormat (const tcu::TextureFormat& format)
87 {
88         // Only two depth and depth-stencil formats are floating point
89         return  (format.order == tcu::TextureFormat::D && format.type == tcu::TextureFormat::FLOAT) ||
90                         (format.order == tcu::TextureFormat::DS && format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV);
91 }
92
93 void clampFloatingPointTexture (const tcu::PixelBufferAccess& access)
94 {
95         DE_ASSERT(isFloatingPointDepthFormat(access.getFormat()));
96
97         for (int z = 0; z < access.getDepth(); ++z)
98         for (int y = 0; y < access.getHeight(); ++y)
99         for (int x = 0; x < access.getWidth(); ++x)
100                 access.setPixDepth(de::clamp(access.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
101 }
102
103 void clampFloatingPointTexture (tcu::Texture2D& target)
104 {
105         for (int level = 0; level < target.getNumLevels(); ++level)
106                 if (!target.isLevelEmpty(level))
107                         clampFloatingPointTexture(target.getLevel(level));
108 }
109
110 static void clampFloatingPointTexture (tcu::Texture2DArray& target)
111 {
112         for (int level = 0; level < target.getNumLevels(); ++level)
113                 if (!target.isLevelEmpty(level))
114                         clampFloatingPointTexture(target.getLevel(level));
115 }
116
117 void clampFloatingPointTexture (tcu::TextureCube& target)
118 {
119         for (int level = 0; level < target.getNumLevels(); ++level)
120                 for (int face = tcu::CUBEFACE_NEGATIVE_X; face < tcu::CUBEFACE_LAST; ++face)
121                         clampFloatingPointTexture(target.getLevelFace(level, (tcu::CubeFace)face));
122 }
123
124 tcu::PixelFormat getPixelFormat(tcu::TextureFormat texFormat)
125 {
126         const tcu::IVec4                        formatBitDepth          = tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(texFormat, Sampler::MODE_DEPTH));
127         return tcu::PixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
128 }
129
130 template<typename TextureType>
131 bool verifyTexCompareResult (tcu::TestContext&                                          testCtx,
132                                                          const tcu::ConstPixelBufferAccess&             result,
133                                                          const TextureType&                                             src,
134                                                          const float*                                                   texCoord,
135                                                          const ReferenceParams&                                 sampleParams,
136                                                          const tcu::TexComparePrecision&                comparePrec,
137                                                          const tcu::LodPrecision&                               lodPrec,
138                                                          const tcu::PixelFormat&                                pixelFormat)
139 {
140         tcu::TestLog&   log                                     = testCtx.getLog();
141         tcu::Surface    reference                       (result.getWidth(), result.getHeight());
142         tcu::Surface    errorMask                       (result.getWidth(), result.getHeight());
143         const tcu::Vec3 nonShadowThreshold      = tcu::computeFixedPointThreshold(getBitsVec(pixelFormat)-1).swizzle(1,2,3);
144         int                             numFailedPixels;
145
146         // sampleTexture() expects source image to be the same state as it would be in a GL implementation, that is
147         // the floating point depth values should be in [0, 1] range as data is clamped during texture upload. Since
148         // we don't have a separate "uploading" phase and just reuse the buffer we used for GL-upload, do the clamping
149         // here if necessary.
150
151         if (isFloatingPointDepthFormat(src.getFormat()))
152         {
153                 TextureType clampedSource(src);
154
155                 clampFloatingPointTexture(clampedSource);
156
157                 // sample clamped values
158
159                 sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), clampedSource, texCoord, sampleParams);
160                 numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), clampedSource, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold);
161         }
162         else
163         {
164                 // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
165
166                 sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
167                 numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold);
168         }
169
170         if (numFailedPixels > 0)
171                 log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
172
173         log << TestLog::ImageSet("VerifyResult", "Verification result")
174                 << TestLog::Image("Rendered", "Rendered image", result);
175
176         if (numFailedPixels > 0)
177         {
178                 log << TestLog::Image("Reference", "Ideal reference image", reference)
179                         << TestLog::Image("ErrorMask", "Error mask", errorMask);
180         }
181
182         log << TestLog::EndImageSet;
183
184         return numFailedPixels == 0;
185 }
186
187 class Texture2DShadowTestInstance : public TestInstance
188 {
189 public:
190         typedef Texture2DShadowTestCaseParameters       ParameterType;
191                                                                                                 Texture2DShadowTestInstance             (Context& context, const ParameterType& testParameters);
192                                                                                                 ~Texture2DShadowTestInstance    (void);
193
194         virtual tcu::TestStatus                                         iterate                                                 (void);
195
196 private:
197                                                                                                 Texture2DShadowTestInstance             (const Texture2DShadowTestInstance& other);
198         Texture2DShadowTestInstance&                            operator=                                               (const Texture2DShadowTestInstance& other);
199
200         struct FilterCase
201         {
202                 int                     textureIndex;
203
204                 tcu::Vec2       minCoord;
205                 tcu::Vec2       maxCoord;
206                 float           ref;
207
208                 FilterCase      (void)
209                         : textureIndex(-1)
210                         , ref           (0.0f)
211                 {
212                 }
213
214                 FilterCase      (int tex_, const float ref_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
215                         : textureIndex  (tex_)
216                         , minCoord              (minCoord_)
217                         , maxCoord              (maxCoord_)
218                         , ref                   (ref_)
219                 {
220                 }
221         };
222
223         const ParameterType&                    m_testParameters;
224         std::vector<TestTexture2DSp>    m_textures;
225         std::vector<FilterCase>                 m_cases;
226
227         TextureRenderer                                 m_renderer;
228
229         int                                                             m_caseNdx;
230 };
231
232 Texture2DShadowTestInstance::Texture2DShadowTestInstance (Context& context, const ParameterType& testParameters)
233         : TestInstance                  (context)
234         , m_testParameters              (testParameters)
235         , m_renderer                    (context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
236         , m_caseNdx                             (0)
237 {
238         // Create 2 textures.
239         m_textures.reserve(2);
240         for (int ndx = 0; ndx < 2; ndx++)
241         {
242                 m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
243         }
244
245         const int       numLevels       = m_textures[0]->getNumLevels();
246
247         // Fill first gradient texture.
248         for (int levelNdx = 0; levelNdx < numLevels; ++levelNdx)
249         {
250                 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));
251         }
252
253         // Fill second with grid texture.
254         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
255         {
256                 const deUint32  step    = 0x00ffffff / numLevels;
257                 const deUint32  rgb             = step*levelNdx;
258                 const deUint32  colorA  = 0xff000000 | rgb;
259                 const deUint32  colorB  = 0xff000000 | ~rgb;
260
261                 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec(), tcu::RGBA(colorB).toVec());
262         }
263
264         // Upload.
265         for (std::vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
266         {
267                 m_renderer.add2DTexture(*i, m_testParameters.backingMode);
268         }
269
270         // Compute cases.
271         {
272                 const float refInRangeUpper             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
273                 const float refInRangeLower             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
274                 const float refOutOfBoundsUpper = 1.1f;         // !< lookup function should clamp values to [0, 1] range
275                 const float refOutOfBoundsLower = -0.1f;
276
277                 const struct
278                 {
279                         const int       texNdx;
280                         const float     ref;
281                         const float     lodX;
282                         const float     lodY;
283                         const float     oX;
284                         const float     oY;
285                 } cases[] =
286                 {
287                         { 0,    refInRangeUpper,                1.6f,   2.9f,   -1.0f,  -2.7f   },
288                         { 0,    refInRangeLower,                -2.0f,  -1.35f, -0.2f,  0.7f    },
289                         { 1,    refInRangeUpper,                0.14f,  0.275f, -1.5f,  -1.1f   },
290                         { 1,    refInRangeLower,                -0.92f, -2.64f, 0.4f,   -0.1f   },
291                         { 1,    refOutOfBoundsUpper,    -0.39f, -0.52f, 0.65f,  0.87f   },
292                         { 1,    refOutOfBoundsLower,    -1.55f, 0.65f,  0.35f,  0.91f   },
293                 };
294
295                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
296                 {
297                         const int       texNdx  = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
298                         const float ref         = cases[caseNdx].ref;
299                         const float     lodX    = cases[caseNdx].lodX;
300                         const float     lodY    = cases[caseNdx].lodY;
301                         const float     oX              = cases[caseNdx].oX;
302                         const float     oY              = cases[caseNdx].oY;
303                         const float     sX              = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
304                         const float     sY              = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[texNdx]->getTexture().getHeight());
305
306                         m_cases.push_back(FilterCase(texNdx, ref, tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY)));
307                 }
308         }
309
310         m_caseNdx = 0;
311 }
312
313 Texture2DShadowTestInstance::~Texture2DShadowTestInstance (void)
314 {
315         m_textures.clear();
316         m_cases.clear();
317 }
318
319 tcu::TestStatus Texture2DShadowTestInstance::iterate (void)
320 {
321         tcu::TestLog&                                   log                             = m_context.getTestContext().getLog();
322         const pipeline::TestTexture2D&  texture                 = m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
323         const tcu::TextureFormat                texFmt                  = texture.getTextureFormat();
324         const tcu::TextureFormatInfo    fmtInfo                 = tcu::getTextureFormatInfo(texFmt);
325         const tcu::ScopedLogSection             section                 (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
326
327         const FilterCase&                               curCase                 = m_cases[m_caseNdx];
328         ReferenceParams                                 sampleParams    (TEXTURETYPE_2D);
329         tcu::Surface                                    rendered                (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
330         vector<float>                                   texCoord;
331
332         // Setup params for reference.
333         sampleParams.sampler                    = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
334         sampleParams.sampler.compare    = m_testParameters.compareOp;
335         sampleParams.samplerType                = SAMPLERTYPE_SHADOW;
336         sampleParams.lodMode                    = LODMODE_EXACT;
337         sampleParams.colorBias                  = fmtInfo.lookupBias;
338         sampleParams.colorScale                 = fmtInfo.lookupScale;
339         sampleParams.ref                                = curCase.ref;
340
341         log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;
342
343         // Compute texture coordinates.
344         log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
345         computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
346
347         m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
348
349         {
350                 const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
351                 tcu::LodPrecision                       lodPrecision;
352                 tcu::TexComparePrecision        texComparePrecision;
353
354                 lodPrecision.derivateBits                       = 18;
355                 lodPrecision.lodBits                            = 6;
356                 texComparePrecision.coordBits           = tcu::IVec3(20,20,0);
357                 texComparePrecision.uvwBits                     = tcu::IVec3(7,7,0);
358                 texComparePrecision.pcfBits                     = 5;
359                 texComparePrecision.referenceBits       = 16;
360                 texComparePrecision.resultBits          = pixelFormat.redBits-1;
361
362                 const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
363                                                                                                                   &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
364
365                 if (!isHighQuality)
366                 {
367                         m_context.getTestContext().getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
368
369                         lodPrecision.lodBits                    = 4;
370                         texComparePrecision.uvwBits             = tcu::IVec3(4,4,0);
371                         texComparePrecision.pcfBits             = 0;
372
373                         const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
374                                                                                                          &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
375
376                         if (!isOk)
377                         {
378                                 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
379                                 return tcu::TestStatus::fail("Image verification failed");
380                         }
381                 }
382         }
383
384         m_caseNdx += 1;
385         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
386 }
387
388 struct TextureCubeShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public TextureCubeTestCaseParameters
389 {
390 };
391
392 class TextureCubeShadowTestInstance : public TestInstance
393 {
394 public:
395         typedef TextureCubeShadowTestCaseParameters ParameterType;
396                                                                                                 TextureCubeShadowTestInstance           (Context& context, const ParameterType& testParameters);
397                                                                                                 ~TextureCubeShadowTestInstance          (void);
398
399         virtual tcu::TestStatus                                         iterate                                                         (void);
400
401 private:
402                                                                                                 TextureCubeShadowTestInstance           (const TextureCubeShadowTestInstance& other);
403         TextureCubeShadowTestInstance&                          operator=                                                       (const TextureCubeShadowTestInstance& other);
404
405         struct FilterCase
406         {
407                 int                                             textureIndex;
408                 tcu::Vec2                               bottomLeft;
409                 tcu::Vec2                               topRight;
410                 float                                   ref;
411
412                 FilterCase (void)
413                         : textureIndex  (-1)
414                         , ref                   (0.0f)
415                 {
416                 }
417
418                 FilterCase (const int tex_, const float ref_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
419                         : textureIndex  (tex_)
420                         , bottomLeft    (bottomLeft_)
421                         , topRight              (topRight_)
422                         , ref                   (ref_)
423                 {
424                 }
425         };
426
427         const ParameterType&            m_testParameters;
428         vector<TestTextureCubeSp>       m_textures;
429         std::vector<FilterCase>         m_cases;
430
431         TextureRenderer                         m_renderer;
432         int                                                     m_caseNdx;
433 };
434
435 TextureCubeShadowTestInstance::TextureCubeShadowTestInstance (Context& context, const ParameterType& testParameters)
436         : TestInstance                  (context)
437         , m_testParameters              (testParameters)
438         , m_renderer                    (context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
439         , m_caseNdx                             (0)
440 {
441         const int                                               numLevels       = deLog2Floor32(m_testParameters.size)+1;
442         const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
443         const tcu::Vec4                                 cBias           = fmtInfo.valueMin;
444         const tcu::Vec4                                 cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
445
446         // Create textures.
447
448         m_textures.reserve(2);
449         for (int ndx = 0; ndx < 2; ndx++)
450         {
451                 m_textures.push_back(TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
452         }
453
454         // Fill first with gradient texture.
455         static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
456         {
457                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
458                 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
459                 { tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
460                 { tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
461                 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
462                 { tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
463         };
464         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
465         {
466                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
467                 {
468                         tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
469                 }
470         }
471
472         // Fill second with grid texture.
473         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
474         {
475                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
476                 {
477                         const deUint32  step    = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
478                         const deUint32  rgb             = step*levelNdx*face;
479                         const deUint32  colorA  = 0xff000000 | rgb;
480                         const deUint32  colorB  = 0xff000000 | ~rgb;
481
482                         tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
483                 }
484         }
485
486         // Upload.
487         for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
488         {
489                 m_renderer.addCubeTexture(*i, m_testParameters.backingMode);
490         }
491
492         // Compute cases
493         {
494                 const float refInRangeUpper             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
495                 const float refInRangeLower             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
496                 const float refOutOfBoundsUpper = 1.1f;
497                 const float refOutOfBoundsLower = -0.1f;
498
499                 m_cases.push_back(FilterCase(0, refInRangeUpper,                tcu::Vec2(-1.25f, -1.2f),       tcu::Vec2(1.2f, 1.25f)));       // minification
500                 m_cases.push_back(FilterCase(0, refInRangeLower,                tcu::Vec2(0.8f, 0.8f),          tcu::Vec2(1.25f, 1.20f)));      // magnification
501                 m_cases.push_back(FilterCase(1, refInRangeUpper,                tcu::Vec2(-1.19f, -1.3f),       tcu::Vec2(1.1f, 1.35f)));       // minification
502                 m_cases.push_back(FilterCase(1, refInRangeLower,                tcu::Vec2(-1.2f, -1.1f),        tcu::Vec2(-0.8f, -0.8f)));      // magnification
503                 m_cases.push_back(FilterCase(1, refOutOfBoundsUpper,    tcu::Vec2(-0.61f, -0.1f),       tcu::Vec2(0.9f, 1.18f)));       // reference value clamp, upper
504                 m_cases.push_back(FilterCase(1, refOutOfBoundsLower,    tcu::Vec2(-0.75f, 1.0f),        tcu::Vec2(0.05f, 0.75f)));      // reference value clamp, lower
505         }
506 }
507
508 TextureCubeShadowTestInstance::~TextureCubeShadowTestInstance   (void)
509 {
510 }
511
512 static const char* getFaceDesc (const tcu::CubeFace face)
513 {
514         switch (face)
515         {
516                 case tcu::CUBEFACE_NEGATIVE_X:  return "-X";
517                 case tcu::CUBEFACE_POSITIVE_X:  return "+X";
518                 case tcu::CUBEFACE_NEGATIVE_Y:  return "-Y";
519                 case tcu::CUBEFACE_POSITIVE_Y:  return "+Y";
520                 case tcu::CUBEFACE_NEGATIVE_Z:  return "-Z";
521                 case tcu::CUBEFACE_POSITIVE_Z:  return "+Z";
522                 default:
523                         DE_ASSERT(false);
524                         return DE_NULL;
525         }
526 }
527
528 tcu::TestStatus TextureCubeShadowTestInstance::iterate (void)
529 {
530
531         tcu::TestLog&                                           log                             = m_context.getTestContext().getLog();
532         const tcu::ScopedLogSection                     iterSection             (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
533         const FilterCase&                                       curCase                 = m_cases[m_caseNdx];
534         const pipeline::TestTextureCube&        texture                 = m_renderer.getCubeTexture(curCase.textureIndex);
535
536         ReferenceParams                                         sampleParams    (TEXTURETYPE_CUBE);
537
538         // Params for reference computation.
539         sampleParams.sampler                                    = util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
540         sampleParams.sampler.seamlessCubeMap    = true;
541         sampleParams.sampler.compare                    = m_testParameters.compareOp;
542         sampleParams.samplerType                                = SAMPLERTYPE_SHADOW;
543         sampleParams.lodMode                                    = LODMODE_EXACT;
544         sampleParams.ref                                                = curCase.ref;
545
546         log     << TestLog::Message
547                 << "Compare reference value = " << sampleParams.ref << "\n"
548                 << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight
549                 << TestLog::EndMessage;
550
551         for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
552         {
553                 const tcu::CubeFace             face            = tcu::CubeFace(faceNdx);
554                 tcu::Surface                    result          (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
555                 vector<float>                   texCoord;
556
557                 computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
558
559                 log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
560
561                 // \todo Log texture coordinates.
562
563                 m_renderer.renderQuad(result, curCase.textureIndex, &texCoord[0], sampleParams);
564
565                 {
566                         const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
567                         tcu::LodPrecision                       lodPrecision;
568                         tcu::TexComparePrecision        texComparePrecision;
569
570                         lodPrecision.derivateBits                       = 10;
571                         lodPrecision.lodBits                            = 5;
572                         texComparePrecision.coordBits           = tcu::IVec3(10,10,10);
573                         texComparePrecision.uvwBits                     = tcu::IVec3(6,6,0);
574                         texComparePrecision.pcfBits                     = 5;
575                         texComparePrecision.referenceBits       = 16;
576                         texComparePrecision.resultBits          = pixelFormat.redBits-1;
577
578                         const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
579                                                                                                                           &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
580
581                         if (!isHighQuality)
582                         {
583                                 log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
584
585                                 lodPrecision.lodBits                    = 4;
586                                 texComparePrecision.uvwBits             = tcu::IVec3(4,4,0);
587                                 texComparePrecision.pcfBits             = 0;
588
589                                 const bool isOk = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
590                                                                                                                  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
591
592                                 if (!isOk)
593                                 {
594                                         log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
595                                         return tcu::TestStatus::fail("Image verification failed");
596                                 }
597                         }
598                 }
599         }
600
601         m_caseNdx += 1;
602         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
603 }
604
605 struct Texture2DArrayShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public Texture2DArrayTestCaseParameters
606 {
607 };
608
609 class Texture2DArrayShadowTestInstance : public TestInstance
610 {
611 public:
612         typedef Texture2DArrayShadowTestCaseParameters  ParameterType;
613                                                                                                         Texture2DArrayShadowTestInstance                (Context& context, const ParameterType& testParameters);
614                                                                                                         ~Texture2DArrayShadowTestInstance               (void);
615
616         virtual tcu::TestStatus                                                 iterate                                                                 (void);
617
618 private:
619                                                                                                         Texture2DArrayShadowTestInstance                (const Texture2DArrayShadowTestInstance& other);
620         Texture2DArrayShadowTestInstance&                               operator=                                                               (const Texture2DArrayShadowTestInstance& other);
621
622         struct FilterCase
623         {
624                 int                                                     textureIndex;
625                 tcu::Vec3                                       minCoord;
626                 tcu::Vec3                                       maxCoord;
627                 float                                           ref;
628
629                 FilterCase (void)
630                         : textureIndex  (-1)
631                         , ref                   (0.0f)
632                 {
633                 }
634
635                 FilterCase (const int tex_, float ref_, const tcu::Vec3& minCoord_, const tcu::Vec3& maxCoord_)
636                         : textureIndex  (tex_)
637                         , minCoord              (minCoord_)
638                         , maxCoord              (maxCoord_)
639                         , ref                   (ref_)
640                 {
641                 }
642         };
643
644         const ParameterType&                            m_testParameters;
645         std::vector<TestTexture2DArraySp>       m_textures;
646         std::vector<FilterCase>                         m_cases;
647
648         TextureRenderer                                         m_renderer;
649
650         int                                                                     m_caseNdx;
651 };
652
653 Texture2DArrayShadowTestInstance::Texture2DArrayShadowTestInstance (Context& context, const ParameterType& testParameters)
654         : TestInstance                  (context)
655         , m_testParameters              (testParameters)
656         , m_renderer                    (context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
657         , m_caseNdx                             (0)
658 {
659         const int                                               numLevels       = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height))+1;
660         const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
661         const tcu::Vec4                                 cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
662         const tcu::Vec4                                 cBias           = fmtInfo.valueMin;
663
664         // Create 2 textures.
665         m_textures.reserve(2);
666         for (int ndx = 0; ndx < 2; ndx++)
667         {
668                 m_textures.push_back(TestTexture2DArraySp(new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.numLayers)));
669         }
670
671         // Fill first gradient texture.
672         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
673         {
674                 const tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
675                 const tcu::Vec4 gMax = tcu::Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
676
677                 tcu::fillWithComponentGradients(m_textures[0]->getTexture().getLevel(levelNdx), gMin, gMax);
678         }
679
680         // Fill second with grid texture.
681         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
682         {
683                 const deUint32  step    = 0x00ffffff / numLevels;
684                 const deUint32  rgb             = step*levelNdx;
685                 const deUint32  colorA  = 0xff000000 | rgb;
686                 const deUint32  colorB  = 0xff000000 | ~rgb;
687
688                 tcu::fillWithGrid(m_textures[1]->getTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
689         }
690
691         // Upload.
692         for (std::vector<TestTexture2DArraySp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
693         {
694                 m_renderer.add2DArrayTexture(*i, m_testParameters.backingMode);
695         }
696
697         // Compute cases.
698         {
699                 const float refInRangeUpper             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
700                 const float refInRangeLower             = (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
701                 const float refOutOfBoundsUpper = 1.1f;         // !< lookup function should clamp values to [0, 1] range
702                 const float refOutOfBoundsLower = -0.1f;
703
704                 const struct
705                 {
706                         const int       texNdx;
707                         const float     ref;
708                         const float     lodX;
709                         const float     lodY;
710                         const float     oX;
711                         const float     oY;
712                 } cases[] =
713                 {
714                         { 0,    refInRangeUpper,                1.6f,   2.9f,   -1.0f,  -2.7f   },
715                         { 0,    refInRangeLower,                -2.0f,  -1.35f, -0.2f,  0.7f    },
716                         { 1,    refInRangeUpper,                0.14f,  0.275f, -1.5f,  -1.1f   },
717                         { 1,    refInRangeLower,                -0.92f, -2.64f, 0.4f,   -0.1f   },
718                         { 1,    refOutOfBoundsUpper,    -0.49f, -0.22f, 0.45f,  0.97f   },
719                         { 1,    refOutOfBoundsLower,    -0.85f, 0.75f,  0.25f,  0.61f   },
720                 };
721
722                 const float     minLayer        = -0.5f;
723                 const float     maxLayer        = (float)m_testParameters.numLayers;
724
725                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
726                 {
727                         const int       tex             = cases[caseNdx].texNdx > 0 ? 1 : 0;
728                         const float     ref             = cases[caseNdx].ref;
729                         const float     lodX    = cases[caseNdx].lodX;
730                         const float     lodY    = cases[caseNdx].lodY;
731                         const float     oX              = cases[caseNdx].oX;
732                         const float     oY              = cases[caseNdx].oY;
733                         const float     sX              = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[tex]->getTexture().getWidth());
734                         const float     sY              = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[tex]->getTexture().getHeight());
735
736                         m_cases.push_back(FilterCase(tex, ref, tcu::Vec3(oX, oY, minLayer), tcu::Vec3(oX+sX, oY+sY, maxLayer)));
737                 }
738         }
739 }
740
741 Texture2DArrayShadowTestInstance::~Texture2DArrayShadowTestInstance (void)
742 {
743 }
744
745 tcu::TestStatus Texture2DArrayShadowTestInstance::iterate (void)
746 {
747         tcu::TestLog&                                           log                             = m_context.getTestContext().getLog();
748         const FilterCase&                                       curCase                 = m_cases[m_caseNdx];
749         const pipeline::TestTexture2DArray&     texture                 = m_renderer.get2DArrayTexture(curCase.textureIndex);
750
751         ReferenceParams                                         sampleParams    (TEXTURETYPE_2D_ARRAY);
752         tcu::Surface                                            rendered                (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
753         const tcu::ScopedLogSection                     section                 (log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
754
755         const float                                                     texCoord[]              =
756         {
757                 curCase.minCoord.x(), curCase.minCoord.y(), curCase.minCoord.z(),
758                 curCase.minCoord.x(), curCase.maxCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f,
759                 curCase.maxCoord.x(), curCase.minCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f,
760                 curCase.maxCoord.x(), curCase.maxCoord.y(), curCase.maxCoord.z()
761         };
762
763         // Setup params for reference.
764         sampleParams.sampler                    = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
765         sampleParams.sampler.compare    = m_testParameters.compareOp;
766         sampleParams.samplerType                = SAMPLERTYPE_SHADOW;
767         sampleParams.lodMode                    = LODMODE_EXACT;
768         sampleParams.ref                                = curCase.ref;
769
770         log     << TestLog::Message
771                 << "Compare reference value = " << sampleParams.ref << "\n"
772                 << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord
773                 << TestLog::EndMessage;
774
775         m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
776
777         {
778                 const tcu::PixelFormat          pixelFormat                     = getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
779                 tcu::LodPrecision                       lodPrecision;
780                 tcu::TexComparePrecision        texComparePrecision;
781
782                 lodPrecision.derivateBits                       = 18;
783                 lodPrecision.lodBits                            = 6;
784                 texComparePrecision.coordBits           = tcu::IVec3(20,20,20);
785                 texComparePrecision.uvwBits                     = tcu::IVec3(7,7,7);
786                 texComparePrecision.pcfBits                     = 5;
787                 texComparePrecision.referenceBits       = 16;
788                 texComparePrecision.resultBits          = pixelFormat.redBits-1;
789
790                 const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
791                                                                                                                   &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
792
793                 if (!isHighQuality)
794                 {
795                         log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
796
797                         lodPrecision.lodBits                    = 4;
798                         texComparePrecision.uvwBits             = tcu::IVec3(4,4,4);
799                         texComparePrecision.pcfBits             = 0;
800
801                         const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
802                                                                                                          &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
803
804                         if (!isOk)
805                         {
806                                 log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
807                                 return tcu::TestStatus::fail("Image verification failed");
808                         }
809                 }
810         }
811
812         m_caseNdx += 1;
813         return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
814 }
815
816 void populateTextureShadowTests (tcu::TestCaseGroup* textureShadowTests)
817 {
818         tcu::TestContext&                               testCtx                         = textureShadowTests->getTestContext();
819
820         static const struct
821         {
822                 const char*                                                             name;
823                 const TextureBinding::ImageBackingMode  backingMode;
824         } backingModes[] =
825         {
826                 { "",                   TextureBinding::IMAGE_BACKING_MODE_REGULAR      },
827                 { "sparse_",    TextureBinding::IMAGE_BACKING_MODE_SPARSE       }
828         };
829
830         static const struct
831         {
832                 const char*                                                             name;
833                 const VkFormat                                                  format;
834         } formats[] =
835         {
836                 { "d16_unorm",                          VK_FORMAT_D16_UNORM                             },
837                 { "x8_d24_unorm_pack32",        VK_FORMAT_X8_D24_UNORM_PACK32   },
838                 { "d32_sfloat",                         VK_FORMAT_D32_SFLOAT                    },
839                 { "d16_unorm_s8_uint",          VK_FORMAT_D16_UNORM_S8_UINT             },
840                 { "d24_unorm_s8_uint",          VK_FORMAT_D24_UNORM_S8_UINT             },
841                 { "d32_sfloat_s8_uint",         VK_FORMAT_D32_SFLOAT_S8_UINT    }
842         };
843
844         static const struct
845         {
846                 const char*                                                             name;
847                 const Sampler::FilterMode                               minFilter;
848                 const Sampler::FilterMode                               magFilter;
849         } filters[] =
850         {
851                 { "nearest",                            Sampler::NEAREST,                                       Sampler::NEAREST        },
852                 { "linear",                                     Sampler::LINEAR,                                        Sampler::LINEAR         },
853                 { "nearest_mipmap_nearest",     Sampler::NEAREST_MIPMAP_NEAREST,        Sampler::LINEAR         },
854                 { "linear_mipmap_nearest",      Sampler::LINEAR_MIPMAP_NEAREST,         Sampler::LINEAR         },
855                 { "nearest_mipmap_linear",      Sampler::NEAREST_MIPMAP_LINEAR,         Sampler::LINEAR         },
856                 { "linear_mipmap_linear",       Sampler::LINEAR_MIPMAP_LINEAR,          Sampler::LINEAR         }
857         };
858
859         static const struct
860         {
861                 const char*                                                             name;
862                 const Sampler::CompareMode                              op;
863         } compareOp[] =
864         {
865                 { "less_or_equal",              Sampler::COMPAREMODE_LESS_OR_EQUAL              },
866                 { "greater_or_equal",   Sampler::COMPAREMODE_GREATER_OR_EQUAL   },
867                 { "less",                               Sampler::COMPAREMODE_LESS                               },
868                 { "greater",                    Sampler::COMPAREMODE_GREATER                    },
869                 { "equal",                              Sampler::COMPAREMODE_EQUAL                              },
870                 { "not_equal",                  Sampler::COMPAREMODE_NOT_EQUAL                  },
871                 { "always",                             Sampler::COMPAREMODE_ALWAYS                             },
872                 { "never",                              Sampler::COMPAREMODE_NEVER                              }
873         };
874
875         // 2D cases.
876         {
877                 de::MovePtr<tcu::TestCaseGroup> group2D (new tcu::TestCaseGroup(testCtx, "2d", "2D texture shadow lookup tests"));
878
879                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
880                 {
881                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
882
883                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
884                         {
885                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
886                                 {
887                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
888                                         {
889                                                 const string                                            name    = string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
890                                                 Texture2DShadowTestCaseParameters       testParameters;
891
892                                                 testParameters.minFilter        = filters[filterNdx].minFilter;
893                                                 testParameters.magFilter        = filters[filterNdx].magFilter;
894                                                 testParameters.format           = formats[formatNdx].format;
895                                                 testParameters.backingMode      = backingModes[backingNdx].backingMode;
896                                                 testParameters.compareOp        = compareOp[compareNdx].op;
897                                                 testParameters.wrapS            = Sampler::REPEAT_GL;
898                                                 testParameters.wrapT            = Sampler::REPEAT_GL;
899                                                 testParameters.width            = 32;
900                                                 testParameters.height           = 64;
901
902                                                 testParameters.programs.push_back(PROGRAM_2D_SHADOW);
903
904                                                 filterGroup->addChild(new TextureTestCase<Texture2DShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
905                                         }
906                                 }
907                         }
908
909                         group2D->addChild(filterGroup.release());
910                 }
911
912                 textureShadowTests->addChild(group2D.release());
913         }
914
915         // Cubemap cases.
916         {
917                 de::MovePtr<tcu::TestCaseGroup> groupCube       (new tcu::TestCaseGroup(testCtx, "cube", "Cube map texture shadow lookup tests"));
918
919                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
920                 {
921                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
922
923                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
924                         {
925                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
926                                 {
927                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
928                                         {
929                                                 const string                                                    name    = string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
930                                                 TextureCubeShadowTestCaseParameters             testParameters;
931
932                                                 testParameters.minFilter        = filters[filterNdx].minFilter;
933                                                 testParameters.magFilter        = filters[filterNdx].magFilter;
934                                                 testParameters.format           = formats[formatNdx].format;
935                                                 testParameters.backingMode      = backingModes[backingNdx].backingMode;
936                                                 testParameters.compareOp        = compareOp[compareNdx].op;
937                                                 testParameters.wrapS            = Sampler::REPEAT_GL;
938                                                 testParameters.wrapT            = Sampler::REPEAT_GL;
939                                                 testParameters.size                     = 32;
940
941                                                 testParameters.programs.push_back(PROGRAM_CUBE_SHADOW);
942
943                                                 filterGroup->addChild(new TextureTestCase<TextureCubeShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
944                                         }
945                                 }
946                         }
947
948                         groupCube->addChild(filterGroup.release());
949                 }
950
951                 textureShadowTests->addChild(groupCube.release());
952         }
953
954         // 2D array cases.
955         {
956                 de::MovePtr<tcu::TestCaseGroup> group2DArray    (new tcu::TestCaseGroup(testCtx, "2d_array", "2D texture array shadow lookup tests"));
957
958                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
959                 {
960                         de::MovePtr<tcu::TestCaseGroup> filterGroup     (new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
961
962                         for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
963                         {
964                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
965                                 {
966                                         for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
967                                         {
968                                                 const string                                                    name    = string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
969                                                 Texture2DArrayShadowTestCaseParameters  testParameters;
970
971                                                 testParameters.minFilter        = filters[filterNdx].minFilter;
972                                                 testParameters.magFilter        = filters[filterNdx].magFilter;
973                                                 testParameters.format           = formats[formatNdx].format;
974                                                 testParameters.backingMode      = backingModes[backingNdx].backingMode;
975                                                 testParameters.compareOp        = compareOp[compareNdx].op;
976                                                 testParameters.wrapS            = Sampler::REPEAT_GL;
977                                                 testParameters.wrapT            = Sampler::REPEAT_GL;
978                                                 testParameters.width            = 32;
979                                                 testParameters.height           = 64;
980                                                 testParameters.numLayers        = 8;
981
982                                                 testParameters.programs.push_back(PROGRAM_2D_ARRAY_SHADOW);
983
984                                                 filterGroup->addChild(new TextureTestCase<Texture2DArrayShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
985                                         }
986                                 }
987                         }
988
989                         group2DArray->addChild(filterGroup.release());
990                 }
991
992                 textureShadowTests->addChild(group2DArray.release());
993         }
994 }
995
996 } // anonymous
997
998 tcu::TestCaseGroup* createTextureShadowTests (tcu::TestContext& testCtx)
999 {
1000         return createTestGroup(testCtx, "shadow", "Texture shadow tests.", populateTextureShadowTests);
1001 }
1002
1003 } // texture
1004 } // vkt