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