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