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 tcu::FloatFormat& conversionPrecision,
71 const 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 Interval resultIntervals[4];
307 for (int ndx = 0; ndx < 4; ++ndx)
309 resultIntervals[ndx] = Interval(0.0);
312 for (int i = 0; i < 2; ++i)
314 const Interval weightInterval = m_filteringPrecision.roundOut(Interval(i == 0 ? 1.0f - weight : weight), false);
316 for (int compNdx = 0; compNdx < 4; ++compNdx)
318 const Interval texelInterval(false, texelsMin[i][compNdx], texelsMax[i][compNdx]);
320 resultIntervals[compNdx] = m_filteringPrecision.roundOut(resultIntervals[compNdx] + weightInterval * texelInterval, false);
324 for (int compNdx = 0; compNdx < 4; ++compNdx)
326 resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
327 resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
332 void SampleVerifier::getFilteredSample2D (const IVec3& texelBase,
337 Vec4& resultMax) const
342 for (int i = 0; i < 2; ++i)
344 for (int j = 0; j < 2; ++j)
346 fetchTexel(texelBase + IVec3(i, j, 0), layer, level, VK_FILTER_LINEAR, texelsMin[2 * j + i], texelsMax[2 * j + i]);
350 Interval resultIntervals[4];
352 for (int ndx = 0; ndx < 4; ++ndx)
354 resultIntervals[ndx] = Interval(0.0);
357 for (int i = 0; i < 2; ++i)
359 const Interval iWeightInterval = m_filteringPrecision.roundOut(Interval(i == 0 ? 1.0f - weights[1] : weights[1]), false);
361 for (int j = 0; j < 2; ++j)
363 const Interval jWeightInterval = m_filteringPrecision.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[0] : weights[0]), false);
365 for (int compNdx = 0; compNdx < 4; ++compNdx)
367 const Interval texelInterval(false, texelsMin[2 * i + j][compNdx], texelsMax[2 * i + j][compNdx]);
369 resultIntervals[compNdx] = m_filteringPrecision.roundOut(resultIntervals[compNdx] + jWeightInterval * texelInterval, false);
374 for (int compNdx = 0; compNdx < 4; ++compNdx)
376 resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
377 resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
381 void SampleVerifier::getFilteredSample3D (const IVec3& texelBase,
386 Vec4& resultMax) const
391 for (int i = 0; i < 2; ++i)
393 for (int j = 0; j < 2; ++j)
395 for (int k = 0; k < 2; ++k)
397 fetchTexel(texelBase + IVec3(i, j, k), layer, level, VK_FILTER_LINEAR, texelsMin[4 * k + 2 * j + i], texelsMax[4 * k + 2 * j + i]);
402 Interval resultIntervals[4];
404 for (int ndx = 0; ndx < 4; ++ndx)
406 resultIntervals[ndx] = Interval(0.0);
409 for (int i = 0; i < 2; ++i)
411 const Interval iWeightInterval = m_filteringPrecision.roundOut(Interval(i == 0 ? 1.0f - weights[2] : weights[2]), false);
413 for (int j = 0; j < 2; ++j)
415 const Interval jWeightInterval = m_filteringPrecision.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[1] : weights[1]), false);
417 for (int k = 0; k < 2; ++k)
419 const Interval kWeightInterval = m_filteringPrecision.roundOut(jWeightInterval * Interval(k == 0 ? 1.0f - weights[0] : weights[0]), false);
421 for (int compNdx = 0; compNdx < 4; ++compNdx)
423 const Interval texelInterval(false, texelsMin[4 * i + 2 * j + k][compNdx], texelsMax[4 * i + 2 * j + k][compNdx]);
425 resultIntervals[compNdx] = m_filteringPrecision.roundOut(resultIntervals[compNdx] + kWeightInterval * texelInterval, false);
431 for (int compNdx = 0; compNdx < 4; ++compNdx)
433 resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
434 resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
438 void SampleVerifier::getFilteredSample (const IVec3& texelBase,
443 Vec4& resultMax) const
445 DE_ASSERT(layer < m_imParams.arrayLayers);
446 DE_ASSERT(level < m_imParams.levels);
448 if (m_imParams.dim == IMG_DIM_1D)
450 getFilteredSample1D(texelBase, weights.x(), layer, level, resultMin, resultMax);
452 else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
454 getFilteredSample2D(texelBase, weights.swizzle(0, 1), layer, level, resultMin, resultMax);
458 getFilteredSample3D(texelBase, weights, layer, level, resultMin, resultMax);
462 void SampleVerifier::getMipmapStepBounds (const Vec2& lodFracBounds,
464 deInt32& stepMax) const
466 DE_ASSERT(m_mipmapBits < 32);
467 const int mipmapSteps = ((int)1) << m_mipmapBits;
469 stepMin = deFloorFloatToInt32(lodFracBounds[0] * (float)mipmapSteps);
470 stepMax = deCeilFloatToInt32 (lodFracBounds[1] * (float)mipmapSteps);
472 stepMin = de::max(stepMin, (deInt32)0);
473 stepMax = de::min(stepMax, (deInt32)mipmapSteps);
476 bool SampleVerifier::verifySampleFiltered (const Vec4& result,
477 const IVec3& baseTexelHiIn,
478 const IVec3& baseTexelLoIn,
479 const IVec3& texelGridOffsetHiIn,
480 const IVec3& texelGridOffsetLoIn,
483 const Vec2& lodFracBounds,
485 VkSamplerMipmapMode mipmapFilter,
486 std::ostream& report) const
488 DE_ASSERT(layer < m_imParams.arrayLayers);
489 DE_ASSERT(levelHi < m_imParams.levels);
491 const int coordSteps = 1 << m_coordBits;
492 const int lodSteps = 1 << m_mipmapBits;
493 const int levelLo = (levelHi < m_imParams.levels - 1) ? levelHi + 1 : levelHi;
495 IVec3 baseTexelHi = baseTexelHiIn;
496 IVec3 baseTexelLo = baseTexelLoIn;
497 IVec3 texelGridOffsetHi = texelGridOffsetHiIn;
498 IVec3 texelGridOffsetLo = texelGridOffsetLoIn;
499 deInt32 lodStepsMin = 0;
500 deInt32 lodStepsMax = 0;
502 getMipmapStepBounds(lodFracBounds, lodStepsMin, lodStepsMax);
504 report << "Testing at base texel " << baseTexelHi << ", " << baseTexelLo << " offset " << texelGridOffsetHi << ", " << texelGridOffsetLo << "\n";
506 Vec4 idealSampleHiMin;
507 Vec4 idealSampleHiMax;
508 Vec4 idealSampleLoMin;
509 Vec4 idealSampleLoMax;
511 // Get ideal samples at steps at each mipmap level
513 if (filter == VK_FILTER_LINEAR)
515 // Adjust texel grid coordinates for linear filtering
516 wrapTexelGridCoordLinear(baseTexelHi, texelGridOffsetHi, m_coordBits, m_imParams.dim);
518 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
520 wrapTexelGridCoordLinear(baseTexelLo, texelGridOffsetLo, m_coordBits, m_imParams.dim);
523 const Vec3 roundedWeightsHi = texelGridOffsetHi.asFloat() / (float)coordSteps;
524 const Vec3 roundedWeightsLo = texelGridOffsetLo.asFloat() / (float)coordSteps;
526 report << "Computed weights: " << roundedWeightsHi << ", " << roundedWeightsLo << "\n";
528 getFilteredSample(baseTexelHi, roundedWeightsHi, layer, levelHi, idealSampleHiMin, idealSampleHiMax);
530 report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
532 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
534 getFilteredSample(baseTexelLo, roundedWeightsLo, layer, levelLo, idealSampleLoMin, idealSampleLoMax);
536 report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
541 fetchTexel(baseTexelHi, layer, levelHi, VK_FILTER_NEAREST, idealSampleHiMin, idealSampleHiMax);
543 report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
545 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
547 fetchTexel(baseTexelLo, layer, levelLo, VK_FILTER_NEAREST, idealSampleLoMin, idealSampleLoMax);
549 report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
553 // Test ideal samples based on mipmap filtering mode
555 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
557 for (deInt32 lodStep = lodStepsMin; lodStep <= lodStepsMax; ++lodStep)
559 float weight = (float)lodStep / (float)lodSteps;
561 report << "Testing at mipmap weight " << weight << "\n";
566 for (int compNdx = 0; compNdx < 4; ++compNdx)
568 const Interval idealSampleLo(false, idealSampleLoMin[compNdx], idealSampleLoMax[compNdx]);
569 const Interval idealSampleHi(false, idealSampleHiMin[compNdx], idealSampleHiMax[compNdx]);
571 const Interval idealSample
572 = m_filteringPrecision.roundOut(Interval(weight) * idealSampleLo + Interval(1.0f - weight) * idealSampleHi, false);
574 idealSampleMin[compNdx] = (float)idealSample.lo();
575 idealSampleMax[compNdx] = (float)idealSample.hi();
578 report << "Ideal sample: " << idealSampleMin << " through " << idealSampleMax << "\n";
580 if (isInRange(result, idealSampleMin, idealSampleMax))
586 report << "Failed comparison\n";
592 if (isInRange(result, idealSampleHiMin, idealSampleHiMax))
598 report << "Failed comparison\n";
605 bool SampleVerifier::verifySampleTexelGridCoords (const SampleArguments& args,
607 const IVec3& gridCoordHi,
608 const IVec3& gridCoordLo,
609 const Vec2& lodBounds,
611 VkSamplerMipmapMode mipmapFilter,
612 std::ostream& report) const
614 const int layer = m_imParams.isArrayed ? (int)deRoundEven(args.layer) : 0U;
615 const IVec3 gridCoord[2] = {gridCoordHi, gridCoordLo};
618 IVec3 texelGridOffset[2];
620 for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
622 calcTexelBaseOffset(gridCoord[levelNdx], m_coordBits, baseTexel[levelNdx], texelGridOffset[levelNdx]);
625 const bool canBeMinified = lodBounds[1] > 0.0f;
626 const bool canBeMagnified = lodBounds[0] <= 0.0f;
630 report << "Trying magnification...\n";
632 if (m_samplerParams.magFilter == VK_FILTER_NEAREST)
634 report << "Testing against nearest texel at " << baseTexel[0] << "\n";
639 fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
641 if (isInRange(result, idealMin, idealMax))
647 report << "Failed against " << idealMin << " through " << idealMax << "\n";
652 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))
659 report << "Trying minification...\n";
661 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
663 const Vec2 lodFracBounds = lodBounds - Vec2((float)level);
665 if (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, lodFracBounds, m_samplerParams.minFilter, VK_SAMPLER_MIPMAP_MODE_LINEAR, report))
668 else if (m_samplerParams.minFilter == VK_FILTER_LINEAR)
670 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))
675 report << "Testing against nearest texel at " << baseTexel[0] << "\n";
680 fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
682 if (isInRange(result, idealMin, idealMax))
688 report << "Failed against " << idealMin << " through " << idealMax << "\n";
696 bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments& args,
699 const Vec2& lodBounds,
701 std::ostream& report) const
703 DE_ASSERT(level < m_imParams.levels);
705 VkSamplerMipmapMode mipmapFilter = m_samplerParams.mipmapFilter;
707 if (level == m_imParams.levels - 1)
709 mipmapFilter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
712 Vec3 unnormalizedCoordMin[2];
713 Vec3 unnormalizedCoordMax[2];
714 IVec3 gridCoordMin[2];
715 IVec3 gridCoordMax[2];
717 const FloatFormat coordFormat(-32, 32, 16, true);
719 calcUnnormalizedCoordRange(coord,
720 m_levels[level].getSize(),
722 unnormalizedCoordMin[0],
723 unnormalizedCoordMax[0]);
725 calcTexelGridCoordRange(unnormalizedCoordMin[0],
726 unnormalizedCoordMax[0],
731 report << "Level " << level << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[0] << ", " << unnormalizedCoordMax[0] << "]\n";
732 report << "Level " << level << " computed texel grid coordinate range: [" << gridCoordMin[0] << ", " << gridCoordMax[0] << "]\n";
734 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
736 calcUnnormalizedCoordRange(coord,
737 m_levels[level+1].getSize(),
739 unnormalizedCoordMin[1],
740 unnormalizedCoordMax[1]);
742 calcTexelGridCoordRange(unnormalizedCoordMin[1],
743 unnormalizedCoordMax[1],
749 report << "Level " << level+1 << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[1] << " - " << unnormalizedCoordMax[1] << "]\n";
750 report << "Level " << level+1 << " computed texel grid coordinate range: [" << gridCoordMin[1] << " - " << gridCoordMax[1] << "]\n";
754 unnormalizedCoordMin[1] = unnormalizedCoordMax[1] = Vec3(0.0f);
755 gridCoordMin[1] = gridCoordMax[1] = IVec3(0);
760 IVec3 gridCoord[2] = {gridCoordMin[0], gridCoordMin[1]};
764 if (verifySampleTexelGridCoords(args, result, gridCoord[0], gridCoord[1], lodBounds, level, mipmapFilter, report))
767 // Get next grid coordinate to test at
769 // Represents whether the increment at a position wraps and should "carry" to the next place
772 for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
774 for (int compNdx = 0; compNdx < 3; ++compNdx)
778 deInt32& comp = gridCoord[levelNdx][compNdx];
781 if (comp > gridCoordMax[levelNdx][compNdx])
783 comp = gridCoordMin[levelNdx][compNdx];
799 bool SampleVerifier::verifySampleCubemapFace (const SampleArguments& args,
805 std::ostream& report) const
807 // Will use this parameter once cubemapping is implemented completely
812 if (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
814 float lodBias = m_samplerParams.lodBias;
816 if (m_sampleLookupSettings.hasLodBias)
817 lodBias += args.lodBias;
819 lodBounds = calcLodBounds(dPdx.swizzle(0, 1, 2),
820 dPdy.swizzle(0, 1, 2),
823 m_samplerParams.minLod,
824 m_samplerParams.maxLod);
828 lodBounds[0] = lodBounds[1] = args.lod;
831 DE_ASSERT(lodBounds[0] <= lodBounds[1]);
833 const UVec2 levelBounds = calcLevelBounds(lodBounds, m_imParams.levels, m_samplerParams.mipmapFilter);
835 for (deUint32 level = levelBounds[0]; level <= levelBounds[1]; ++level)
837 report << "Testing at mipmap level " << level << "...\n";
839 const Vec2 levelLodBounds = calcLevelLodBounds(lodBounds, level);
841 if (verifySampleMipmapLevel(args, result, coord, levelLodBounds, level, report))
846 report << "Done testing mipmap level " << level << ".\n\n";
852 bool SampleVerifier::verifySampleImpl (const SampleArguments& args,
854 std::ostream& report) const
856 // \todo [2016-07-11 collinbaker] Handle depth and stencil formats
857 // \todo [2016-07-06 collinbaker] Handle dRef
858 DE_ASSERT(m_samplerParams.isCompare == false);
860 Vec4 coord = args.coord;
863 if (m_imParams.dim == IMG_DIM_1D)
867 else if (m_imParams.dim == IMG_DIM_2D)
871 else if (m_imParams.dim == IMG_DIM_3D || m_imParams.dim == IMG_DIM_CUBE)
876 // 15.6.1 Project operation
878 if (m_sampleLookupSettings.isProjective)
880 DE_ASSERT(args.coord[coordSize] != 0.0f);
881 const float proj = coord[coordSize];
883 coord = coord / proj;
886 const Vec4 dPdx = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdx : Vec4(0);
887 const Vec4 dPdy = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdy : Vec4(0);
889 // 15.6.3 Cube Map Face Selection and Transformations
891 if (m_imParams.dim == IMG_DIM_CUBE)
893 const Vec3 r = coord.swizzle(0, 1, 2);
894 const Vec3 drdx = dPdx.swizzle(0, 1, 2);
895 const Vec3 drdy = dPdy.swizzle(0, 1, 2);
897 int faceBitmap = calcCandidateCubemapFaces(r);
899 // We must test every possible disambiguation order
901 for (int faceNdx = 0; faceNdx < 6; ++faceNdx)
903 const bool isPossible = ((faceBitmap & (1U << faceNdx)) != 0);
914 calcCubemapFaceCoords(r, drdx, drdy, faceNdx, coordFace, dPdxFace, dPdyFace);
916 if (verifySampleCubemapFace(args,
918 Vec4(coordFace[0], coordFace[1], 0.0f, 0.0f),
919 Vec4(dPdxFace[0], dPdxFace[1], 0.0f, 0.0f),
920 Vec4(dPdyFace[0], dPdyFace[1], 0.0f, 0.0f),
932 return verifySampleCubemapFace(args, result, coord, dPdx, dPdy, 0, report);
936 bool SampleVerifier::verifySampleReport (const SampleArguments& args,
938 std::string& report) const
940 std::ostringstream reportStream;
942 const bool isValid = verifySampleImpl(args, result, reportStream);
944 report = reportStream.str();
949 bool SampleVerifier::verifySample (const SampleArguments& args,
950 const Vec4& result) const
952 // Create unopened ofstream to simulate "null" ostream
953 std::ofstream nullStream;
955 return verifySampleImpl(args, result, nullStream);