1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 Google Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief GPU image sample verification
22 *//*--------------------------------------------------------------------*/
24 #include "vktSampleVerifier.hpp"
25 #include "vktSampleVerifierUtil.hpp"
28 #include "tcuFloat.hpp"
29 #include "tcuTextureUtil.hpp"
30 #include "vkImageUtil.hpp"
47 int calcUnnormalizedDim (const ImgDim dim)
49 if (dim == IMG_DIM_1D)
53 else if (dim == IMG_DIM_2D || dim == IMG_DIM_CUBE)
65 SampleVerifier::SampleVerifier (const ImageViewParameters& imParams,
66 const SamplerParameters& samplerParams,
67 const SampleLookupSettings& sampleLookupSettings,
70 const std::vector<de::SharedPtr<tcu::FloatFormat>>& conversionPrecision,
71 const std::vector<de::SharedPtr<tcu::FloatFormat>>& filteringPrecision,
72 const std::vector<tcu::ConstPixelBufferAccess>& levels)
73 : m_imParams (imParams)
74 , m_samplerParams (samplerParams)
75 , m_sampleLookupSettings (sampleLookupSettings)
76 , m_coordBits (coordBits)
77 , m_mipmapBits (mipmapBits)
78 , m_conversionPrecision (conversionPrecision)
79 , m_filteringPrecision (filteringPrecision)
80 , m_unnormalizedDim (calcUnnormalizedDim(imParams.dim))
86 bool SampleVerifier::coordOutOfRange (const IVec3& coord, int compNdx, int level) const
88 DE_ASSERT(compNdx >= 0 && compNdx < 3);
90 return coord[compNdx] < 0 || coord[compNdx] >= m_levels[level].getSize()[compNdx];
93 void SampleVerifier::fetchTexelWrapped (const IVec3& coord,
97 Vec4& resultMax) const
99 const void* pixelPtr = DE_NULL;
101 if (m_imParams.dim == IMG_DIM_1D)
103 pixelPtr = m_levels[level].getPixelPtr(coord[0], layer, 0);
105 else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
107 pixelPtr = m_levels[level].getPixelPtr(coord[0], coord[1], layer);
111 pixelPtr = m_levels[level].getPixelPtr(coord[0], coord[1], coord[2]);
114 convertFormat(pixelPtr, mapVkFormat(m_imParams.format), m_conversionPrecision, resultMin, resultMax);
116 #if defined(DE_DEBUG)
117 // Make sure tcuTexture agrees
118 const tcu::ConstPixelBufferAccess& levelAccess = m_levels[level];
119 const tcu::Vec4 refPix = (m_imParams.dim == IMG_DIM_1D) ? levelAccess.getPixel(coord[0], layer, 0)
120 : (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE) ? levelAccess.getPixel(coord[0], coord[1], layer)
121 : levelAccess.getPixel(coord[0], coord[1], coord[2]);
123 for (int c = 0; c < 4; c++)
124 DE_ASSERT(de::inRange(refPix[c], resultMin[c], resultMax[c]));
128 void SampleVerifier::fetchTexel (const IVec3& coordIn,
133 Vec4& resultMax) const
135 IVec3 coord = coordIn;
137 VkSamplerAddressMode wrappingModes[] =
139 m_samplerParams.wrappingModeU,
140 m_samplerParams.wrappingModeV,
141 m_samplerParams.wrappingModeW
144 const bool isSrgb = isSrgbFormat(m_imParams.format);
146 // Wrapping operations
149 if (m_imParams.dim == IMG_DIM_CUBE && filter == VK_FILTER_LINEAR)
151 // If the image is a cubemap and we are using linear filtering, we do edge or corner wrapping
153 const int arrayLayer = layer / 6;
154 int arrayFace = layer % 6;
156 if (coordOutOfRange(coord, 0, level) != coordOutOfRange(coord, 1, level))
163 wrapCubemapEdge(coord.swizzle(0, 1),
164 m_levels[level].getSize().swizzle(0, 1),
169 coord.xy() = newCoord;
170 layer = arrayLayer * 6 + newFace;
172 else if (coordOutOfRange(coord, 0, level) && coordOutOfRange(coord, 1, level))
176 int faces[3] = {arrayFace, 0, 0};
177 IVec2 cornerCoords[3];
179 wrapCubemapCorner(coord.swizzle(0, 1),
180 m_levels[level].getSize().swizzle(0, 1),
188 // \todo [2016-08-01 collinbaker] Call into fetchTexelWrapped instead
190 Vec4 cornerTexels[3];
192 for (int ndx = 0; ndx < 3; ++ndx)
194 int cornerLayer = faces[ndx] + arrayLayer * 6;
198 cornerTexels[ndx] += sRGBToLinear(m_levels[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer));
202 cornerTexels[ndx] += m_levels[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer);
206 for (int compNdx = 0; compNdx < 4; ++compNdx)
208 float compMin = cornerTexels[0][compNdx];
209 float compMax = cornerTexels[0][compNdx];
211 for (int ndx = 1; ndx < 3; ++ndx)
213 const float comp = cornerTexels[ndx][compNdx];
215 compMin = de::min(comp, compMin);
216 compMax = de::max(comp, compMax);
219 resultMin[compNdx] = compMin;
220 resultMax[compNdx] = compMax;
227 // If no wrapping is necessary, just do nothing
232 // Otherwise, we do normal wrapping
234 if (m_imParams.dim == IMG_DIM_CUBE)
236 wrappingModes[0] = wrappingModes[1] = wrappingModes[2] = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
239 for (int compNdx = 0; compNdx < 3; ++compNdx)
241 const int size = m_levels[level].getSize()[compNdx];
243 coord[compNdx] = wrapTexelCoord(coord[compNdx], size, wrappingModes[compNdx]);
247 if (coordOutOfRange(coord, 0, level) ||
248 coordOutOfRange(coord, 1, level) ||
249 coordOutOfRange(coord, 2, level))
251 // If after wrapping coordinates are still out of range, perform texel replacement
253 switch (m_samplerParams.borderColor)
255 case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
257 resultMin = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
258 resultMax = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
261 case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
263 resultMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
264 resultMax = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
267 case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
269 resultMin = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
270 resultMax = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
275 // \\ [2016-07-07 collinbaker] Handle
276 // VK_BORDER_COLOR_INT_* borders
277 DE_FATAL("Not implemented");
284 // Otherwise, actually fetch a texel
286 fetchTexelWrapped(coord, layer, level, resultMin, resultMax);
290 void SampleVerifier::getFilteredSample1D (const IVec3& texelBase,
295 Vec4& resultMax) const
300 for (int i = 0; i < 2; ++i)
302 fetchTexel(texelBase + IVec3(i, 0, 0), layer, level, VK_FILTER_LINEAR, texelsMin[i], texelsMax[i]);
305 for (int compNdx = 0; compNdx < 4; ++compNdx)
307 Interval resultInterval(0.0);
309 for (int i = 0; i < 2; ++i)
311 const Interval weightInterval = m_filteringPrecision[compNdx]->roundOut(Interval(i == 0 ? 1.0f - weight : weight), false);
312 const Interval texelInterval (false, texelsMin[i][compNdx], texelsMax[i][compNdx]);
314 resultInterval = m_filteringPrecision[compNdx]->roundOut(resultInterval + weightInterval * texelInterval, false);
317 resultMin[compNdx] = (float)resultInterval.lo();
318 resultMax[compNdx] = (float)resultInterval.hi();
322 void SampleVerifier::getFilteredSample2D (const IVec3& texelBase,
327 Vec4& resultMax) const
332 for (int i = 0; i < 2; ++i)
334 for (int j = 0; j < 2; ++j)
336 fetchTexel(texelBase + IVec3(i, j, 0), layer, level, VK_FILTER_LINEAR, texelsMin[2 * j + i], texelsMax[2 * j + i]);
340 for (int compNdx = 0; compNdx < 4; ++compNdx)
342 Interval resultInterval(0.0);
344 for (int i = 0; i < 2; ++i)
346 const Interval iWeightInterval = m_filteringPrecision[compNdx]->roundOut(Interval(i == 0 ? 1.0f - weights[1] : weights[1]), false);
348 for (int j = 0; j < 2; ++j)
350 const Interval jWeightInterval = m_filteringPrecision[compNdx]->roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[0] : weights[0]), false);
351 const Interval texelInterval(false, texelsMin[2 * i + j][compNdx], texelsMax[2 * i + j][compNdx]);
353 resultInterval = m_filteringPrecision[compNdx]->roundOut(resultInterval + jWeightInterval * texelInterval, false);
357 resultMin[compNdx] = (float)resultInterval.lo();
358 resultMax[compNdx] = (float)resultInterval.hi();
362 void SampleVerifier::getFilteredSample3D (const IVec3& texelBase,
367 Vec4& resultMax) const
372 for (int i = 0; i < 2; ++i)
374 for (int j = 0; j < 2; ++j)
376 for (int k = 0; k < 2; ++k)
378 fetchTexel(texelBase + IVec3(i, j, k), layer, level, VK_FILTER_LINEAR, texelsMin[4 * k + 2 * j + i], texelsMax[4 * k + 2 * j + i]);
383 for (int compNdx = 0; compNdx < 4; ++compNdx)
385 Interval resultInterval(0.0);
387 for (int i = 0; i < 2; ++i)
389 const Interval iWeightInterval = m_filteringPrecision[compNdx]->roundOut(Interval(i == 0 ? 1.0f - weights[2] : weights[2]), false);
391 for (int j = 0; j < 2; ++j)
393 const Interval jWeightInterval = m_filteringPrecision[compNdx]->roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[1] : weights[1]), false);
395 for (int k = 0; k < 2; ++k)
397 const Interval kWeightInterval = m_filteringPrecision[compNdx]->roundOut(jWeightInterval * Interval(k == 0 ? 1.0f - weights[0] : weights[0]), false);
399 const Interval texelInterval(false, texelsMin[4 * i + 2 * j + k][compNdx], texelsMax[4 * i + 2 * j + k][compNdx]);
401 resultInterval = m_filteringPrecision[compNdx]->roundOut(resultInterval + kWeightInterval * texelInterval, false);
406 resultMin[compNdx] = (float)resultInterval.lo();
407 resultMax[compNdx] = (float)resultInterval.hi();
411 void SampleVerifier::getFilteredSample (const IVec3& texelBase,
416 Vec4& resultMax) const
418 DE_ASSERT(layer < m_imParams.arrayLayers);
419 DE_ASSERT(level < m_imParams.levels);
421 if (m_imParams.dim == IMG_DIM_1D)
423 getFilteredSample1D(texelBase, weights.x(), layer, level, resultMin, resultMax);
425 else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
427 getFilteredSample2D(texelBase, weights.swizzle(0, 1), layer, level, resultMin, resultMax);
431 getFilteredSample3D(texelBase, weights, layer, level, resultMin, resultMax);
435 void SampleVerifier::getMipmapStepBounds (const Vec2& lodFracBounds,
437 deInt32& stepMax) const
439 DE_ASSERT(m_mipmapBits < 32);
440 const int mipmapSteps = ((int)1) << m_mipmapBits;
442 stepMin = deFloorFloatToInt32(lodFracBounds[0] * (float)mipmapSteps);
443 stepMax = deCeilFloatToInt32 (lodFracBounds[1] * (float)mipmapSteps);
445 stepMin = de::max(stepMin, (deInt32)0);
446 stepMax = de::min(stepMax, (deInt32)mipmapSteps);
449 bool SampleVerifier::verifySampleFiltered (const Vec4& result,
450 const IVec3& baseTexelHiIn,
451 const IVec3& baseTexelLoIn,
452 const IVec3& texelGridOffsetHiIn,
453 const IVec3& texelGridOffsetLoIn,
456 const Vec2& lodFracBounds,
458 VkSamplerMipmapMode mipmapFilter,
459 std::ostream& report) const
461 DE_ASSERT(layer < m_imParams.arrayLayers);
462 DE_ASSERT(levelHi < m_imParams.levels);
464 const int coordSteps = 1 << m_coordBits;
465 const int lodSteps = 1 << m_mipmapBits;
466 const int levelLo = (levelHi < m_imParams.levels - 1) ? levelHi + 1 : levelHi;
468 IVec3 baseTexelHi = baseTexelHiIn;
469 IVec3 baseTexelLo = baseTexelLoIn;
470 IVec3 texelGridOffsetHi = texelGridOffsetHiIn;
471 IVec3 texelGridOffsetLo = texelGridOffsetLoIn;
472 deInt32 lodStepsMin = 0;
473 deInt32 lodStepsMax = 0;
475 getMipmapStepBounds(lodFracBounds, lodStepsMin, lodStepsMax);
477 report << "Testing at base texel " << baseTexelHi << ", " << baseTexelLo << " offset " << texelGridOffsetHi << ", " << texelGridOffsetLo << "\n";
479 Vec4 idealSampleHiMin;
480 Vec4 idealSampleHiMax;
481 Vec4 idealSampleLoMin;
482 Vec4 idealSampleLoMax;
484 // Get ideal samples at steps at each mipmap level
486 if (filter == VK_FILTER_LINEAR)
488 // Adjust texel grid coordinates for linear filtering
489 wrapTexelGridCoordLinear(baseTexelHi, texelGridOffsetHi, m_coordBits, m_imParams.dim);
491 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
493 wrapTexelGridCoordLinear(baseTexelLo, texelGridOffsetLo, m_coordBits, m_imParams.dim);
496 const Vec3 roundedWeightsHi = texelGridOffsetHi.asFloat() / (float)coordSteps;
497 const Vec3 roundedWeightsLo = texelGridOffsetLo.asFloat() / (float)coordSteps;
499 report << "Computed weights: " << roundedWeightsHi << ", " << roundedWeightsLo << "\n";
501 getFilteredSample(baseTexelHi, roundedWeightsHi, layer, levelHi, idealSampleHiMin, idealSampleHiMax);
503 report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
505 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
507 getFilteredSample(baseTexelLo, roundedWeightsLo, layer, levelLo, idealSampleLoMin, idealSampleLoMax);
509 report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
514 fetchTexel(baseTexelHi, layer, levelHi, VK_FILTER_NEAREST, idealSampleHiMin, idealSampleHiMax);
516 report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
518 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
520 fetchTexel(baseTexelLo, layer, levelLo, VK_FILTER_NEAREST, idealSampleLoMin, idealSampleLoMax);
522 report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
526 // Test ideal samples based on mipmap filtering mode
528 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
530 for (deInt32 lodStep = lodStepsMin; lodStep <= lodStepsMax; ++lodStep)
532 float weight = (float)lodStep / (float)lodSteps;
534 report << "Testing at mipmap weight " << weight << "\n";
539 for (int compNdx = 0; compNdx < 4; ++compNdx)
541 const Interval idealSampleLo(false, idealSampleLoMin[compNdx], idealSampleLoMax[compNdx]);
542 const Interval idealSampleHi(false, idealSampleHiMin[compNdx], idealSampleHiMax[compNdx]);
544 const Interval idealSample
545 = m_filteringPrecision[compNdx]->roundOut(Interval(weight) * idealSampleLo + Interval(1.0f - weight) * idealSampleHi, false);
547 idealSampleMin[compNdx] = (float)idealSample.lo();
548 idealSampleMax[compNdx] = (float)idealSample.hi();
551 report << "Ideal sample: " << idealSampleMin << " through " << idealSampleMax << "\n";
553 if (isInRange(result, idealSampleMin, idealSampleMax))
559 report << "Failed comparison\n";
565 if (isInRange(result, idealSampleHiMin, idealSampleHiMax))
571 report << "Failed comparison\n";
578 bool SampleVerifier::verifySampleTexelGridCoords (const SampleArguments& args,
580 const IVec3& gridCoordHi,
581 const IVec3& gridCoordLo,
582 const Vec2& lodBounds,
584 VkSamplerMipmapMode mipmapFilter,
585 std::ostream& report) const
587 const int layer = m_imParams.isArrayed ? (int)deRoundEven(args.layer) : 0U;
588 const IVec3 gridCoord[2] = {gridCoordHi, gridCoordLo};
591 IVec3 texelGridOffset[2];
593 for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
595 calcTexelBaseOffset(gridCoord[levelNdx], m_coordBits, baseTexel[levelNdx], texelGridOffset[levelNdx]);
598 const bool canBeMinified = lodBounds[1] > 0.0f;
599 const bool canBeMagnified = lodBounds[0] <= 0.0f;
603 report << "Trying magnification...\n";
605 if (m_samplerParams.magFilter == VK_FILTER_NEAREST)
607 report << "Testing against nearest texel at " << baseTexel[0] << "\n";
612 fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
614 if (isInRange(result, idealMin, idealMax))
620 report << "Failed against " << idealMin << " through " << idealMax << "\n";
625 if (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, Vec2(0.0f, 0.0f), VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, report))
632 report << "Trying minification...\n";
634 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
636 const Vec2 lodFracBounds = lodBounds - Vec2((float)level);
638 if (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, lodFracBounds, m_samplerParams.minFilter, VK_SAMPLER_MIPMAP_MODE_LINEAR, report))
641 else if (m_samplerParams.minFilter == VK_FILTER_LINEAR)
643 if (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, Vec2(0.0f, 0.0f), VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, report))
648 report << "Testing against nearest texel at " << baseTexel[0] << "\n";
653 fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
655 if (isInRange(result, idealMin, idealMax))
661 report << "Failed against " << idealMin << " through " << idealMax << "\n";
669 bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments& args,
672 const Vec2& lodBounds,
674 std::ostream& report) const
676 DE_ASSERT(level < m_imParams.levels);
678 VkSamplerMipmapMode mipmapFilter = m_samplerParams.mipmapFilter;
680 if (level == m_imParams.levels - 1)
682 mipmapFilter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
685 Vec3 unnormalizedCoordMin[2];
686 Vec3 unnormalizedCoordMax[2];
687 IVec3 gridCoordMin[2];
688 IVec3 gridCoordMax[2];
690 const FloatFormat coordFormat(-32, 32, 16, true);
692 calcUnnormalizedCoordRange(coord,
693 m_levels[level].getSize(),
695 unnormalizedCoordMin[0],
696 unnormalizedCoordMax[0]);
698 calcTexelGridCoordRange(unnormalizedCoordMin[0],
699 unnormalizedCoordMax[0],
704 report << "Level " << level << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[0] << ", " << unnormalizedCoordMax[0] << "]\n";
705 report << "Level " << level << " computed texel grid coordinate range: [" << gridCoordMin[0] << ", " << gridCoordMax[0] << "]\n";
707 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
709 calcUnnormalizedCoordRange(coord,
710 m_levels[level+1].getSize(),
712 unnormalizedCoordMin[1],
713 unnormalizedCoordMax[1]);
715 calcTexelGridCoordRange(unnormalizedCoordMin[1],
716 unnormalizedCoordMax[1],
722 report << "Level " << level+1 << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[1] << " - " << unnormalizedCoordMax[1] << "]\n";
723 report << "Level " << level+1 << " computed texel grid coordinate range: [" << gridCoordMin[1] << " - " << gridCoordMax[1] << "]\n";
727 unnormalizedCoordMin[1] = unnormalizedCoordMax[1] = Vec3(0.0f);
728 gridCoordMin[1] = gridCoordMax[1] = IVec3(0);
733 IVec3 gridCoord[2] = {gridCoordMin[0], gridCoordMin[1]};
737 if (verifySampleTexelGridCoords(args, result, gridCoord[0], gridCoord[1], lodBounds, level, mipmapFilter, report))
740 // Get next grid coordinate to test at
742 // Represents whether the increment at a position wraps and should "carry" to the next place
745 for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
747 for (int compNdx = 0; compNdx < 3; ++compNdx)
751 deInt32& comp = gridCoord[levelNdx][compNdx];
754 if (comp > gridCoordMax[levelNdx][compNdx])
756 comp = gridCoordMin[levelNdx][compNdx];
772 bool SampleVerifier::verifySampleCubemapFace (const SampleArguments& args,
778 std::ostream& report) const
780 // Will use this parameter once cubemapping is implemented completely
785 if (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
787 float lodBias = m_samplerParams.lodBias;
789 if (m_sampleLookupSettings.hasLodBias)
790 lodBias += args.lodBias;
792 lodBounds = calcLodBounds(dPdx.swizzle(0, 1, 2),
793 dPdy.swizzle(0, 1, 2),
796 m_samplerParams.minLod,
797 m_samplerParams.maxLod);
801 lodBounds[0] = lodBounds[1] = args.lod;
804 DE_ASSERT(lodBounds[0] <= lodBounds[1]);
806 const UVec2 levelBounds = calcLevelBounds(lodBounds, m_imParams.levels, m_samplerParams.mipmapFilter);
808 for (deUint32 level = levelBounds[0]; level <= levelBounds[1]; ++level)
810 report << "Testing at mipmap level " << level << "...\n";
812 const Vec2 levelLodBounds = calcLevelLodBounds(lodBounds, level);
814 if (verifySampleMipmapLevel(args, result, coord, levelLodBounds, level, report))
819 report << "Done testing mipmap level " << level << ".\n\n";
825 bool SampleVerifier::verifySampleImpl (const SampleArguments& args,
827 std::ostream& report) const
829 // \todo [2016-07-11 collinbaker] Handle depth and stencil formats
830 // \todo [2016-07-06 collinbaker] Handle dRef
831 DE_ASSERT(m_samplerParams.isCompare == false);
833 Vec4 coord = args.coord;
836 if (m_imParams.dim == IMG_DIM_1D)
840 else if (m_imParams.dim == IMG_DIM_2D)
844 else if (m_imParams.dim == IMG_DIM_3D || m_imParams.dim == IMG_DIM_CUBE)
849 // 15.6.1 Project operation
851 if (m_sampleLookupSettings.isProjective)
853 DE_ASSERT(args.coord[coordSize] != 0.0f);
854 const float proj = coord[coordSize];
856 coord = coord / proj;
859 const Vec4 dPdx = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdx : Vec4(0);
860 const Vec4 dPdy = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdy : Vec4(0);
862 // 15.6.3 Cube Map Face Selection and Transformations
864 if (m_imParams.dim == IMG_DIM_CUBE)
866 const Vec3 r = coord.swizzle(0, 1, 2);
867 const Vec3 drdx = dPdx.swizzle(0, 1, 2);
868 const Vec3 drdy = dPdy.swizzle(0, 1, 2);
870 int faceBitmap = calcCandidateCubemapFaces(r);
872 // We must test every possible disambiguation order
874 for (int faceNdx = 0; faceNdx < 6; ++faceNdx)
876 const bool isPossible = ((faceBitmap & (1U << faceNdx)) != 0);
887 calcCubemapFaceCoords(r, drdx, drdy, faceNdx, coordFace, dPdxFace, dPdyFace);
889 if (verifySampleCubemapFace(args,
891 Vec4(coordFace[0], coordFace[1], 0.0f, 0.0f),
892 Vec4(dPdxFace[0], dPdxFace[1], 0.0f, 0.0f),
893 Vec4(dPdyFace[0], dPdyFace[1], 0.0f, 0.0f),
905 return verifySampleCubemapFace(args, result, coord, dPdx, dPdy, 0, report);
909 bool SampleVerifier::verifySampleReport (const SampleArguments& args,
911 std::string& report) const
913 std::ostringstream reportStream;
915 const bool isValid = verifySampleImpl(args, result, reportStream);
917 report = reportStream.str();
922 bool SampleVerifier::verifySample (const SampleArguments& args,
923 const Vec4& result) const
925 // Create unopened ofstream to simulate "null" ostream
926 std::ofstream nullStream;
928 return verifySampleImpl(args, result, nullStream);