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"
37 namespace texture_filtering
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<tcu::ConstPixelBufferAccess>& pba)
71 // \todo [2016-07-29 collinbaker] Get rid of magic numbers
72 : m_internalFormat (-14, 15, 10, true) // fp16 format
73 , m_imParams (imParams)
74 , m_samplerParams (samplerParams)
75 , m_sampleLookupSettings (sampleLookupSettings)
76 , m_coordBits (coordBits)
77 , m_mipmapBits (mipmapBits)
78 , m_unnormalizedDim (calcUnnormalizedDim(imParams.dim))
84 bool SampleVerifier::coordOutOfRange (const IVec3& coord, int compNdx, int level) const
86 DE_ASSERT(compNdx >= 0 && compNdx < 3);
88 return coord[compNdx] < 0 || coord[compNdx] >= m_pba[level].getSize()[compNdx];
91 void SampleVerifier::fetchTexelWrapped (const IVec3& coord,
95 Vec4& resultMax) const
97 const void* pixelPtr = DE_NULL;
99 if (m_imParams.dim == IMG_DIM_1D)
101 pixelPtr = m_pba[level].getPixelPtr(coord[0], layer, 0);
103 else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
105 pixelPtr = m_pba[level].getPixelPtr(coord[0], coord[1], layer);
109 pixelPtr = m_pba[level].getPixelPtr(coord[0], coord[1], coord[2]);
112 convertFormat(pixelPtr, mapVkFormat(m_imParams.format), m_internalFormat, resultMin, resultMax);
115 void SampleVerifier::fetchTexel (const IVec3& coordIn,
120 Vec4& resultMax) const
122 IVec3 coord = coordIn;
124 VkSamplerAddressMode wrappingModes[] =
126 m_samplerParams.wrappingModeU,
127 m_samplerParams.wrappingModeV,
128 m_samplerParams.wrappingModeW
131 const bool isSrgb = isSrgbFormat(m_imParams.format);
133 // Wrapping operations
136 if (m_imParams.dim == IMG_DIM_CUBE && filter == VK_FILTER_LINEAR)
138 // If the image is a cubemap and we are using linear filtering, we do edge or corner wrapping
140 const int arrayLayer = layer / 6;
141 int arrayFace = layer % 6;
143 if (coordOutOfRange(coord, 0, level) != coordOutOfRange(coord, 1, level))
150 wrapCubemapEdge(coord.swizzle(0, 1),
151 m_pba[level].getSize().swizzle(0, 1),
156 coord.xy() = newCoord;
157 layer = arrayLayer * 6 + newFace;
159 else if (coordOutOfRange(coord, 0, level) && coordOutOfRange(coord, 1, level))
163 int faces[3] = {arrayFace, 0, 0};
164 IVec2 cornerCoords[3];
166 wrapCubemapCorner(coord.swizzle(0, 1),
167 m_pba[level].getSize().swizzle(0, 1),
175 // \todo [2016-08-01 collinbaker] Call into fetchTexelWrapped instead
177 Vec4 cornerTexels[3];
179 for (int ndx = 0; ndx < 3; ++ndx)
181 int cornerLayer = faces[ndx] + arrayLayer * 6;
185 cornerTexels[ndx] += sRGBToLinear(m_pba[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer));
189 cornerTexels[ndx] += m_pba[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer);
193 for (int compNdx = 0; compNdx < 4; ++compNdx)
195 float compMin = cornerTexels[0][compNdx];
196 float compMax = cornerTexels[0][compNdx];
198 for (int ndx = 1; ndx < 3; ++ndx)
200 const float comp = cornerTexels[ndx][compNdx];
202 compMin = de::min(comp, compMin);
203 compMax = de::max(comp, compMax);
206 resultMin[compNdx] = compMin;
207 resultMax[compNdx] = compMax;
214 // If no wrapping is necessary, just do nothing
219 // Otherwise, we do normal wrapping
221 if (m_imParams.dim == IMG_DIM_CUBE)
223 wrappingModes[0] = wrappingModes[1] = wrappingModes[2] = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
226 for (int compNdx = 0; compNdx < 3; ++compNdx)
228 const int size = m_pba[level].getSize()[compNdx];
230 coord[compNdx] = wrapTexelCoord(coord[compNdx], size, wrappingModes[compNdx]);
234 if (coordOutOfRange(coord, 0, level) ||
235 coordOutOfRange(coord, 1, level) ||
236 coordOutOfRange(coord, 2, level))
238 // If after wrapping coordinates are still out of range, perform texel replacement
240 switch (m_samplerParams.borderColor)
242 case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
244 resultMin = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
245 resultMax = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
248 case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
250 resultMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
251 resultMax = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
254 case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
256 resultMin = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
257 resultMax = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
262 // \\ [2016-07-07 collinbaker] Handle
263 // VK_BORDER_COLOR_INT_* borders
264 DE_FATAL("Not implemented");
271 // Otherwise, actually fetch a texel
273 fetchTexelWrapped(coord, layer, level, resultMin, resultMax);
277 void SampleVerifier::getFilteredSample1D (const IVec3& texelBase,
282 Vec4& resultMax) const
287 for (int i = 0; i < 2; ++i)
289 fetchTexel(texelBase + IVec3(i, 0, 0), layer, level, VK_FILTER_LINEAR, texelsMin[i], texelsMax[i]);
292 Interval resultIntervals[4];
294 for (int ndx = 0; ndx < 4; ++ndx)
296 resultIntervals[ndx] = Interval(0.0);
299 for (int i = 0; i < 2; ++i)
301 const Interval weightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weight : weight), false);
303 for (int compNdx = 0; compNdx < 4; ++compNdx)
305 const Interval texelInterval(false, texelsMin[i][compNdx], texelsMax[i][compNdx]);
307 resultIntervals[compNdx] = m_internalFormat.roundOut(resultIntervals[compNdx] + weightInterval * texelInterval, false);
311 for (int compNdx = 0; compNdx < 4; ++compNdx)
313 resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
314 resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
319 void SampleVerifier::getFilteredSample2D (const IVec3& texelBase,
324 Vec4& resultMax) const
329 for (int i = 0; i < 2; ++i)
331 for (int j = 0; j < 2; ++j)
333 fetchTexel(texelBase + IVec3(i, j, 0), layer, level, VK_FILTER_LINEAR, texelsMin[2 * j + i], texelsMax[2 * j + i]);
337 Interval resultIntervals[4];
339 for (int ndx = 0; ndx < 4; ++ndx)
341 resultIntervals[ndx] = Interval(0.0);
344 for (int i = 0; i < 2; ++i)
346 const Interval iWeightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weights[1] : weights[1]), false);
348 for (int j = 0; j < 2; ++j)
350 const Interval jWeightInterval = m_internalFormat.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[0] : weights[0]), false);
352 for (int compNdx = 0; compNdx < 4; ++compNdx)
354 const Interval texelInterval(false, texelsMin[2 * i + j][compNdx], texelsMax[2 * i + j][compNdx]);
356 resultIntervals[compNdx] = m_internalFormat.roundOut(resultIntervals[compNdx] + jWeightInterval * texelInterval, false);
361 for (int compNdx = 0; compNdx < 4; ++compNdx)
363 resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
364 resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
368 void SampleVerifier::getFilteredSample3D (const IVec3& texelBase,
373 Vec4& resultMax) const
378 for (int i = 0; i < 2; ++i)
380 for (int j = 0; j < 2; ++j)
382 for (int k = 0; k < 2; ++k)
384 fetchTexel(texelBase + IVec3(i, j, k), layer, level, VK_FILTER_LINEAR, texelsMin[4 * k + 2 * j + i], texelsMax[4 * k + 2 * j + i]);
389 Interval resultIntervals[4];
391 for (int ndx = 0; ndx < 4; ++ndx)
393 resultIntervals[ndx] = Interval(0.0);
396 for (int i = 0; i < 2; ++i)
398 const Interval iWeightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weights[2] : weights[2]), false);
400 for (int j = 0; j < 2; ++j)
402 const Interval jWeightInterval = m_internalFormat.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[1] : weights[1]), false);
404 for (int k = 0; k < 2; ++k)
406 const Interval kWeightInterval = m_internalFormat.roundOut(jWeightInterval * Interval(k == 0 ? 1.0f - weights[0] : weights[0]), false);
408 for (int compNdx = 0; compNdx < 4; ++compNdx)
410 const Interval texelInterval(false, texelsMin[4 * i + 2 * j + k][compNdx], texelsMax[4 * i + 2 * j + k][compNdx]);
412 resultIntervals[compNdx] = m_internalFormat.roundOut(resultIntervals[compNdx] + kWeightInterval * texelInterval, false);
418 for (int compNdx = 0; compNdx < 4; ++compNdx)
420 resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
421 resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
425 void SampleVerifier::getFilteredSample (const IVec3& texelBase,
430 Vec4& resultMax) const
432 DE_ASSERT(layer < m_imParams.arrayLayers);
433 DE_ASSERT(level < m_imParams.levels);
435 if (m_imParams.dim == IMG_DIM_1D)
437 getFilteredSample1D(texelBase, weights.x(), layer, level, resultMin, resultMax);
439 else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
441 getFilteredSample2D(texelBase, weights.swizzle(0, 1), layer, level, resultMin, resultMax);
445 getFilteredSample3D(texelBase, weights, layer, level, resultMin, resultMax);
449 void SampleVerifier::getMipmapStepBounds (const Vec2& lodFracBounds,
451 deInt32& stepMax) const
453 DE_ASSERT(m_mipmapBits < 32);
454 const int mipmapSteps = ((int)1) << m_mipmapBits;
456 stepMin = deFloorFloatToInt32(lodFracBounds[0] * (float)mipmapSteps);
457 stepMax = deCeilFloatToInt32 (lodFracBounds[1] * (float)mipmapSteps);
459 stepMin = de::max(stepMin, (deInt32)0);
460 stepMax = de::min(stepMax, (deInt32)mipmapSteps);
463 bool SampleVerifier::verifySampleFiltered (const Vec4& result,
464 const IVec3& baseTexelHiIn,
465 const IVec3& baseTexelLoIn,
466 const IVec3& texelGridOffsetHiIn,
467 const IVec3& texelGridOffsetLoIn,
470 const Vec2& lodFracBounds,
472 VkSamplerMipmapMode mipmapFilter,
473 std::ostream& report) const
475 DE_ASSERT(layer < m_imParams.arrayLayers);
476 DE_ASSERT(levelHi < m_imParams.levels);
478 const int coordSteps = 1 << m_coordBits;
479 const int lodSteps = 1 << m_mipmapBits;
480 const int levelLo = (levelHi < m_imParams.levels - 1) ? levelHi + 1 : levelHi;
482 IVec3 baseTexelHi = baseTexelHiIn;
483 IVec3 baseTexelLo = baseTexelLoIn;
484 IVec3 texelGridOffsetHi = texelGridOffsetHiIn;
485 IVec3 texelGridOffsetLo = texelGridOffsetLoIn;
486 deInt32 lodStepsMin = 0;
487 deInt32 lodStepsMax = 0;
489 getMipmapStepBounds(lodFracBounds, lodStepsMin, lodStepsMax);
491 report << "Testing at base texel " << baseTexelHi << ", " << baseTexelLo << " offset " << texelGridOffsetHi << ", " << texelGridOffsetLo << "\n";
493 Vec4 idealSampleHiMin;
494 Vec4 idealSampleHiMax;
495 Vec4 idealSampleLoMin;
496 Vec4 idealSampleLoMax;
498 // Get ideal samples at steps at each mipmap level
500 if (filter == VK_FILTER_LINEAR)
502 // Adjust texel grid coordinates for linear filtering
503 wrapTexelGridCoordLinear(baseTexelHi, texelGridOffsetHi, m_coordBits, m_imParams.dim);
505 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
507 wrapTexelGridCoordLinear(baseTexelLo, texelGridOffsetLo, m_coordBits, m_imParams.dim);
510 const Vec3 roundedWeightsHi = texelGridOffsetHi.asFloat() / (float)coordSteps;
511 const Vec3 roundedWeightsLo = texelGridOffsetLo.asFloat() / (float)coordSteps;
513 report << "Computed weights: " << roundedWeightsHi << ", " << roundedWeightsLo << "\n";
515 getFilteredSample(baseTexelHi, roundedWeightsHi, layer, levelHi, idealSampleHiMin, idealSampleHiMax);
517 report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
519 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
521 getFilteredSample(baseTexelLo, roundedWeightsLo, layer, levelLo, idealSampleLoMin, idealSampleLoMax);
523 report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
528 fetchTexel(baseTexelHi, layer, levelHi, VK_FILTER_NEAREST, idealSampleHiMin, idealSampleHiMax);
530 report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
532 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
534 fetchTexel(baseTexelLo, layer, levelLo, VK_FILTER_NEAREST, idealSampleLoMin, idealSampleLoMax);
536 report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
540 // Test ideal samples based on mipmap filtering mode
542 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
544 for (deInt32 lodStep = lodStepsMin; lodStep <= lodStepsMax; ++lodStep)
546 float weight = (float)lodStep / (float)lodSteps;
548 report << "Testing at mipmap weight " << weight << "\n";
553 for (int compNdx = 0; compNdx < 4; ++compNdx)
555 const Interval idealSampleLo(false, idealSampleLoMin[compNdx], idealSampleLoMax[compNdx]);
556 const Interval idealSampleHi(false, idealSampleHiMin[compNdx], idealSampleHiMax[compNdx]);
558 const Interval idealSample
559 = m_internalFormat.roundOut(Interval(weight) * idealSampleLo + Interval(1.0f - weight) * idealSampleHi, false);
561 idealSampleMin[compNdx] = (float)idealSample.lo();
562 idealSampleMax[compNdx] = (float)idealSample.hi();
565 report << "Ideal sample: " << idealSampleMin << " through " << idealSampleMax << "\n";
567 if (isInRange(result, idealSampleMin, idealSampleMax))
573 report << "Failed comparison\n";
579 if (isInRange(result, idealSampleHiMin, idealSampleHiMax))
585 report << "Failed comparison\n";
592 bool SampleVerifier::verifySampleTexelGridCoords (const SampleArguments& args,
594 const IVec3& gridCoordHi,
595 const IVec3& gridCoordLo,
596 const Vec2& lodBounds,
598 VkSamplerMipmapMode mipmapFilter,
599 std::ostream& report) const
601 const int layer = m_imParams.isArrayed ? (int)deRoundEven(args.layer) : 0U;
602 const IVec3 gridCoord[2] = {gridCoordHi, gridCoordLo};
605 IVec3 texelGridOffset[2];
607 for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
609 calcTexelBaseOffset(gridCoord[levelNdx], m_coordBits, baseTexel[levelNdx], texelGridOffset[levelNdx]);
612 const bool canBeMinified = lodBounds[1] > 0.0f;
613 const bool canBeMagnified = lodBounds[0] <= 0.0f;
617 report << "Trying magnification...\n";
619 if (m_samplerParams.magFilter == VK_FILTER_NEAREST)
621 report << "Testing against nearest texel at " << baseTexel[0] << "\n";
626 fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
628 if (isInRange(result, idealMin, idealMax))
634 report << "Failed against " << idealMin << " through " << idealMax << "\n";
639 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))
646 report << "Trying minification...\n";
648 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
650 const Vec2 lodFracBounds = lodBounds - Vec2((float)level);
652 if (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, lodFracBounds, m_samplerParams.minFilter, VK_SAMPLER_MIPMAP_MODE_LINEAR, report))
655 else if (m_samplerParams.minFilter == VK_FILTER_LINEAR)
657 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))
662 report << "Testing against nearest texel at " << baseTexel[0] << "\n";
667 fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
669 if (isInRange(result, idealMin, idealMax))
675 report << "Failed against " << idealMin << " through " << idealMax << "\n";
683 bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments& args,
686 const Vec2& lodBounds,
688 std::ostream& report) const
690 DE_ASSERT(level < m_imParams.levels);
692 VkSamplerMipmapMode mipmapFilter = m_samplerParams.mipmapFilter;
694 if (level == m_imParams.levels - 1)
696 mipmapFilter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
699 Vec3 unnormalizedCoordMin[2];
700 Vec3 unnormalizedCoordMax[2];
701 IVec3 gridCoordMin[2];
702 IVec3 gridCoordMax[2];
704 const FloatFormat coordFormat(-32, 32, 16, true);
706 calcUnnormalizedCoordRange(coord,
707 m_pba[level].getSize(),
709 unnormalizedCoordMin[0],
710 unnormalizedCoordMax[0]);
712 calcTexelGridCoordRange(unnormalizedCoordMin[0],
713 unnormalizedCoordMax[0],
718 report << "Level " << level << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[0] << ", " << unnormalizedCoordMax[0] << "]\n";
719 report << "Level " << level << " computed texel grid coordinate range: [" << gridCoordMin[0] << ", " << gridCoordMax[0] << "]\n";
721 if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
723 calcUnnormalizedCoordRange(coord,
724 m_pba[level+1].getSize(),
726 unnormalizedCoordMin[1],
727 unnormalizedCoordMax[1]);
729 calcTexelGridCoordRange(unnormalizedCoordMin[1],
730 unnormalizedCoordMax[1],
736 report << "Level " << level+1 << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[1] << " - " << unnormalizedCoordMax[1] << "]\n";
737 report << "Level " << level+1 << " computed texel grid coordinate range: [" << gridCoordMin[1] << " - " << gridCoordMax[1] << "]\n";
741 unnormalizedCoordMin[1] = unnormalizedCoordMax[1] = Vec3(0.0f);
742 gridCoordMin[1] = gridCoordMax[1] = IVec3(0);
747 IVec3 gridCoord[2] = {gridCoordMin[0], gridCoordMin[1]};
751 if (verifySampleTexelGridCoords(args, result, gridCoord[0], gridCoord[1], lodBounds, level, mipmapFilter, report))
754 // Get next grid coordinate to test at
756 // Represents whether the increment at a position wraps and should "carry" to the next place
759 for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
761 for (int compNdx = 0; compNdx < 3; ++compNdx)
765 deInt32& comp = gridCoord[levelNdx][compNdx];
768 if (comp > gridCoordMax[levelNdx][compNdx])
770 comp = gridCoordMin[levelNdx][compNdx];
786 bool SampleVerifier::verifySampleCubemapFace (const SampleArguments& args,
792 std::ostream& report) const
794 // Will use this parameter once cubemapping is implemented completely
799 if (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
801 float lodBias = m_samplerParams.lodBias;
803 if (m_sampleLookupSettings.hasLodBias)
804 lodBias += args.lodBias;
806 lodBounds = calcLodBounds(dPdx.swizzle(0, 1, 2),
807 dPdy.swizzle(0, 1, 2),
810 m_samplerParams.minLod,
811 m_samplerParams.maxLod);
815 lodBounds[0] = lodBounds[1] = args.lod;
818 DE_ASSERT(lodBounds[0] <= lodBounds[1]);
820 const UVec2 levelBounds = calcLevelBounds(lodBounds, m_imParams.levels, m_samplerParams.mipmapFilter);
822 for (deUint32 level = levelBounds[0]; level <= levelBounds[1]; ++level)
824 report << "Testing at mipmap level " << level << "...\n";
826 const Vec2 levelLodBounds = calcLevelLodBounds(lodBounds, level);
828 if (verifySampleMipmapLevel(args, result, coord, levelLodBounds, level, report))
833 report << "Done testing mipmap level " << level << ".\n\n";
839 bool SampleVerifier::verifySampleImpl (const SampleArguments& args,
841 std::ostream& report) const
843 // \todo [2016-07-11 collinbaker] Handle depth and stencil formats
844 // \todo [2016-07-06 collinbaker] Handle dRef
845 DE_ASSERT(m_samplerParams.isCompare == false);
847 Vec4 coord = args.coord;
850 if (m_imParams.dim == IMG_DIM_1D)
854 else if (m_imParams.dim == IMG_DIM_2D)
858 else if (m_imParams.dim == IMG_DIM_3D || m_imParams.dim == IMG_DIM_CUBE)
863 // 15.6.1 Project operation
865 if (m_sampleLookupSettings.isProjective)
867 DE_ASSERT(args.coord[coordSize] != 0.0f);
868 const float proj = coord[coordSize];
870 coord = coord / proj;
873 const Vec4 dPdx = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdx : Vec4(0);
874 const Vec4 dPdy = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdy : Vec4(0);
876 // 15.6.3 Cube Map Face Selection and Transformations
878 if (m_imParams.dim == IMG_DIM_CUBE)
880 const Vec3 r = coord.swizzle(0, 1, 2);
881 const Vec3 drdx = dPdx.swizzle(0, 1, 2);
882 const Vec3 drdy = dPdy.swizzle(0, 1, 2);
884 int faceBitmap = calcCandidateCubemapFaces(r);
886 // We must test every possible disambiguation order
888 for (int faceNdx = 0; faceNdx < 6; ++faceNdx)
890 const bool isPossible = faceBitmap & (1U << faceNdx);
901 calcCubemapFaceCoords(r, drdx, drdy, faceNdx, coordFace, dPdxFace, dPdyFace);
903 if (verifySampleCubemapFace(args,
905 Vec4(coordFace[0], coordFace[1], 0.0f, 0.0f),
906 Vec4(dPdxFace[0], dPdxFace[1], 0.0f, 0.0f),
907 Vec4(dPdyFace[0], dPdyFace[1], 0.0f, 0.0f),
919 return verifySampleCubemapFace(args, result, coord, dPdx, dPdy, 0, report);
923 bool SampleVerifier::verifySampleReport (const SampleArguments& args,
925 std::string& report) const
927 std::ostringstream reportStream;
929 const bool isValid = verifySampleImpl(args, result, reportStream);
931 report = reportStream.str();
936 bool SampleVerifier::verifySample (const SampleArguments& args,
937 const Vec4& result) const
939 // Create unopened ofstream to simulate "null" ostream
940 std::ofstream nullStream;
942 return verifySampleImpl(args, result, nullStream);
945 } // texture_filtering