13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL (ES) Module 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief rasterization test utils. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsRasterizationTestUtil.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp" 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp" 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp" 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h" 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "rrRasterizer.hpp" 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <limits> 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gls 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace RasterizationTestUtil 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool lineLineIntersect (const tcu::Vector<deInt64, 2>& line0Beg, const tcu::Vector<deInt64, 2>& line0End, const tcu::Vector<deInt64, 2>& line1Beg, const tcu::Vector<deInt64, 2>& line1End) 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef tcu::Vector<deInt64, 2> I64Vec2; 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Lines do not intersect if the other line's endpoints are on the same side 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // otherwise, the do intersect 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Test line 0 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 line = line0End - line0Beg; 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 v0 = line1Beg - line0Beg; 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 v1 = line1End - line0Beg; 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct0 = (line.x() * v0.y() - line.y() * v0.x()); 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct1 = (line.x() * v1.y() - line.y() * v1.x()); 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // check signs 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((crossProduct0 < 0 && crossProduct1 < 0) || 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (crossProduct0 > 0 && crossProduct1 > 0)) 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Test line 1 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 line = line1End - line1Beg; 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 v0 = line0Beg - line1Beg; 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 v1 = line0End - line1Beg; 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct0 = (line.x() * v0.y() - line.y() * v0.x()); 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct1 = (line.x() * v1.y() - line.y() * v1.x()); 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // check signs 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((crossProduct0 < 0 && crossProduct1 < 0) || 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (crossProduct0 > 0 && crossProduct1 > 0)) 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool isTriangleClockwise (const tcu::Vec4& p0, const tcu::Vec4& p1, const tcu::Vec4& p2) 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 u (p1.x() / p1.w() - p0.x() / p0.w(), p1.y() / p1.w() - p0.y() / p0.w()); 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 v (p2.x() / p2.w() - p0.x() / p0.w(), p2.y() / p2.w() - p0.y() / p0.w()); 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float crossProduct = (u.x() * v.y() - u.y() * v.x()); 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return crossProduct > 0.0f; 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareColors (const tcu::RGBA& colorA, const tcu::RGBA& colorB, int redBits, int greenBits, int blueBits) 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int thresholdRed = 1 << (8 - redBits); 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int thresholdGreen = 1 << (8 - greenBits); 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int thresholdBlue = 1 << (8 - blueBits); 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return deAbs32(colorA.getRed() - colorB.getRed()) <= thresholdRed && 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deAbs32(colorA.getGreen() - colorB.getGreen()) <= thresholdGreen && 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deAbs32(colorA.getBlue() - colorB.getBlue()) <= thresholdBlue; 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool pixelNearLineSegment (const tcu::IVec2& pixel, const tcu::Vec2& p0, const tcu::Vec2& p1) 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 pixelCenterPosition = tcu::Vec2(pixel.x() + 0.5f, pixel.y() + 0.5f); 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // "Near" = Distance from the line to the pixel is less than 2 * pixel_max_radius. (pixel_max_radius = sqrt(2) / 2) 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float maxPixelDistance = 1.414f; 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float maxPixelDistanceSquared = 2.0f; 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Near the line 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 line = p1 - p0; 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 v = pixelCenterPosition - p0; 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float crossProduct = (line.x() * v.y() - line.y() * v.x()); 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // distance to line: (line x v) / |line| 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // |(line x v) / |line|| > maxPixelDistance 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // ==> (line x v)^2 / |line|^2 > maxPixelDistance^2 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // ==> (line x v)^2 > maxPixelDistance^2 * |line|^2 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (crossProduct * crossProduct > maxPixelDistanceSquared * tcu::lengthSquared(line)) 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Between the endpoints 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // distance from line endpoint 1 to pixel is less than line length + maxPixelDistance 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float maxDistance = tcu::length(p1 - p0) + maxPixelDistance; 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (tcu::length(pixelCenterPosition - p0) > maxDistance) 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (tcu::length(pixelCenterPosition - p1) > maxDistance) 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool pixelOnlyOnASharedEdge (const tcu::IVec2& pixel, const TriangleSceneSpec::SceneTriangle& triangle, const tcu::IVec2& viewportSize) 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (triangle.sharedEdge[0] || triangle.sharedEdge[1] || triangle.sharedEdge[2]) 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 triangleNormalizedDeviceSpace[3] = 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(triangle.positions[0].x() / triangle.positions[0].w(), triangle.positions[0].y() / triangle.positions[0].w()), 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(triangle.positions[1].x() / triangle.positions[1].w(), triangle.positions[1].y() / triangle.positions[1].w()), 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(triangle.positions[2].x() / triangle.positions[2].w(), triangle.positions[2].y() / triangle.positions[2].w()), 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 triangleScreenSpace[3] = 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (triangleNormalizedDeviceSpace[0] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (triangleNormalizedDeviceSpace[1] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (triangleNormalizedDeviceSpace[2] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool pixelOnEdge0 = pixelNearLineSegment(pixel, triangleScreenSpace[0], triangleScreenSpace[1]); 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool pixelOnEdge1 = pixelNearLineSegment(pixel, triangleScreenSpace[1], triangleScreenSpace[2]); 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool pixelOnEdge2 = pixelNearLineSegment(pixel, triangleScreenSpace[2], triangleScreenSpace[0]); 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If the pixel is on a multiple edges return false 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (pixelOnEdge0 && !pixelOnEdge1 && !pixelOnEdge2) 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return triangle.sharedEdge[0]; 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!pixelOnEdge0 && pixelOnEdge1 && !pixelOnEdge2) 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return triangle.sharedEdge[1]; 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!pixelOnEdge0 && !pixelOnEdge1 && pixelOnEdge2) 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return triangle.sharedEdge[2]; 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat triangleArea (const tcu::Vec2& s0, const tcu::Vec2& s1, const tcu::Vec2& s2) 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 u (s1.x() - s0.x(), s1.y() - s0.y()); 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 v (s2.x() - s0.x(), s2.y() - s0.y()); 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float crossProduct = (u.x() * v.y() - u.y() * v.x()); 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return crossProduct / 2.0f; 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::IVec4 getTriangleAABB (const TriangleSceneSpec::SceneTriangle& triangle, const tcu::IVec2& viewportSize) 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 normalizedDeviceSpace[3] = 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(triangle.positions[0].x() / triangle.positions[0].w(), triangle.positions[0].y() / triangle.positions[0].w()), 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(triangle.positions[1].x() / triangle.positions[1].w(), triangle.positions[1].y() / triangle.positions[1].w()), 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(triangle.positions[2].x() / triangle.positions[2].w(), triangle.positions[2].y() / triangle.positions[2].w()), 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 screenSpace[3] = 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (normalizedDeviceSpace[0] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (normalizedDeviceSpace[1] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (normalizedDeviceSpace[2] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::IVec4 aabb; 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry aabb.x() = (int)deFloatFloor(de::min(de::min(screenSpace[0].x(), screenSpace[1].x()), screenSpace[2].x())); 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry aabb.y() = (int)deFloatFloor(de::min(de::min(screenSpace[0].y(), screenSpace[1].y()), screenSpace[2].y())); 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry aabb.z() = (int)deFloatCeil (de::max(de::max(screenSpace[0].x(), screenSpace[1].x()), screenSpace[2].x())); 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry aabb.w() = (int)deFloatCeil (de::max(de::max(screenSpace[0].y(), screenSpace[1].y()), screenSpace[2].y())); 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return aabb; 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat getExponentEpsilonFromULP (int valueExponent, deUint32 ulp) 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(ulp < (1u<<10)); 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // assume mediump precision, using ulp as ulps in a 10 bit mantissa 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::Float32::construct(+1, valueExponent, (1u<<23) + (ulp << (23 - 10))).asFloat() - tcu::Float32::construct(+1, valueExponent, (1u<<23)).asFloat(); 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat getValueEpsilonFromULP (float value, deUint32 ulp) 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(value != std::numeric_limits<float>::infinity() && value != -std::numeric_limits<float>::infinity()); 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int exponent = tcu::Float32(value).exponent(); 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getExponentEpsilonFromULP(exponent, ulp); 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat getMaxValueWithinError (float value, deUint32 ulp) 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (value == std::numeric_limits<float>::infinity() || value == -std::numeric_limits<float>::infinity()) 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return value; 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return value + getValueEpsilonFromULP(value, ulp); 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat getMinValueWithinError (float value, deUint32 ulp) 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (value == std::numeric_limits<float>::infinity() || value == -std::numeric_limits<float>::infinity()) 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return value; 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return value - getValueEpsilonFromULP(value, ulp); 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat getMinFlushToZero (float value) 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // flush to zero if that decreases the value 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // assume mediump precision 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (value > 0.0f && value < tcu::Float32::construct(+1, -14, 1u<<23).asFloat()) 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 0.0f; 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return value; 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat getMaxFlushToZero (float value) 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // flush to zero if that increases the value 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // assume mediump precision 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (value < 0.0f && value > tcu::Float32::construct(-1, -14, 1u<<23).asFloat()) 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 0.0f; 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return value; 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::IVec3 convertRGB8ToNativeFormat (const tcu::RGBA& color, const RasterizationArguments& args) 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::IVec3 pixelNativeColor; 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int channelNdx = 0; channelNdx < 3; ++channelNdx) 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int channelBitCount = (channelNdx == 0) ? (args.redBits) : (channelNdx == 1) ? (args.greenBits) : (args.blueBits); 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int channelPixelValue = (channelNdx == 0) ? (color.getRed()) : (channelNdx == 1) ? (color.getGreen()) : (color.getBlue()); 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (channelBitCount <= 8) 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor[channelNdx] = channelPixelValue >> (8 - channelBitCount); 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (channelBitCount == 8) 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor[channelNdx] = channelPixelValue; 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // just in case someone comes up with 8+ bits framebuffers pixel formats. But as 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // we can only read in rgba8, we have to guess the trailing bits. Guessing 0. 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor[channelNdx] = channelPixelValue << (channelBitCount - 8); 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return pixelNativeColor; 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*! 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Returns the maximum value of x / y, where x c [minDividend, maxDividend] 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * and y c [minDivisor, maxDivisor] 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat maximalRangeDivision (float minDividend, float maxDividend, float minDivisor, float maxDivisor) 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minDividend <= maxDividend); 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minDivisor <= maxDivisor); 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // special cases 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (minDividend == 0.0f && maxDividend == 0.0f) 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 0.0f; 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (minDivisor <= 0.0f && maxDivisor >= 0.0f) 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return std::numeric_limits<float>::infinity(); 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return de::max(de::max(minDividend / minDivisor, minDividend / maxDivisor), de::max(maxDividend / minDivisor, maxDividend / maxDivisor)); 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*! 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Returns the minimum value of x / y, where x c [minDividend, maxDividend] 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * and y c [minDivisor, maxDivisor] 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat minimalRangeDivision (float minDividend, float maxDividend, float minDivisor, float maxDivisor) 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minDividend <= maxDividend); 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minDivisor <= maxDivisor); 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // special cases 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (minDividend == 0.0f && maxDividend == 0.0f) 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return 0.0f; 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (minDivisor <= 0.0f && maxDivisor >= 0.0f) 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return -std::numeric_limits<float>::infinity(); 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return de::min(de::min(minDividend / minDivisor, minDividend / maxDivisor), de::min(maxDividend / minDivisor, maxDividend / maxDivisor)); 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrystatic bool isLineXMajor (const tcu::Vec2& lineScreenSpaceP0, const tcu::Vec2& lineScreenSpaceP1) 3202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 3212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return de::abs(lineScreenSpaceP1.x() - lineScreenSpaceP0.x()) >= de::abs(lineScreenSpaceP1.y() - lineScreenSpaceP0.y()); 3222306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 3232306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 3242306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrystatic bool isPackedSSLineXMajor (const tcu::Vec4& packedLine) 3252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 3262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 lineScreenSpaceP0 = packedLine.swizzle(0, 1); 3272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 lineScreenSpaceP1 = packedLine.swizzle(2, 3); 3282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 3292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return isLineXMajor(lineScreenSpaceP0, lineScreenSpaceP1); 3302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 3312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct InterpolationRange 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec3 max; 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec3 min; 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct LineInterpolationRange 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2 max; 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2 min; 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3443c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterpolationRange calcTriangleInterpolationWeights (const tcu::Vec4& p0, const tcu::Vec4& p1, const tcu::Vec4& p2, const tcu::Vec2& ndpixel) 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int roundError = 1; 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int barycentricError = 3; 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int divError = 8; 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 nd0 = p0.swizzle(0, 1) / p0.w(); 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 nd1 = p1.swizzle(0, 1) / p1.w(); 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 nd2 = p2.swizzle(0, 1) / p2.w(); 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ka = triangleArea(ndpixel, nd1, nd2); 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kb = triangleArea(ndpixel, nd2, nd0); 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kc = triangleArea(ndpixel, nd0, nd1); 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kaMax = getMaxFlushToZero(getMaxValueWithinError(ka, barycentricError)); 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kbMax = getMaxFlushToZero(getMaxValueWithinError(kb, barycentricError)); 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kcMax = getMaxFlushToZero(getMaxValueWithinError(kc, barycentricError)); 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kaMin = getMinFlushToZero(getMinValueWithinError(ka, barycentricError)); 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kbMin = getMinFlushToZero(getMinValueWithinError(kb, barycentricError)); 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float kcMin = getMinFlushToZero(getMinValueWithinError(kc, barycentricError)); 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(kaMin <= kaMax); 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(kbMin <= kbMax); 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(kcMin <= kcMax); 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // calculate weights: vec3(ka / p0.w, kb / p1.w, kc / p2.w) / (ka / p0.w + kb / p1.w + kc / p2.w) 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float maxPreDivisionValues[3] = 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getMaxFlushToZero(getMaxValueWithinError(getMaxFlushToZero(kaMax / p0.w()), divError)), 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getMaxFlushToZero(getMaxValueWithinError(getMaxFlushToZero(kbMax / p1.w()), divError)), 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getMaxFlushToZero(getMaxValueWithinError(getMaxFlushToZero(kcMax / p2.w()), divError)), 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float minPreDivisionValues[3] = 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getMinFlushToZero(getMinValueWithinError(getMinFlushToZero(kaMin / p0.w()), divError)), 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getMinFlushToZero(getMinValueWithinError(getMinFlushToZero(kbMin / p1.w()), divError)), 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getMinFlushToZero(getMinValueWithinError(getMinFlushToZero(kcMin / p2.w()), divError)), 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minPreDivisionValues[0] <= maxPreDivisionValues[0]); 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minPreDivisionValues[1] <= maxPreDivisionValues[1]); 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minPreDivisionValues[2] <= maxPreDivisionValues[2]); 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float maxDivisor = getMaxFlushToZero(getMaxValueWithinError(maxPreDivisionValues[0] + maxPreDivisionValues[1] + maxPreDivisionValues[2], 2*roundError)); 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float minDivisor = getMinFlushToZero(getMinValueWithinError(minPreDivisionValues[0] + minPreDivisionValues[1] + minPreDivisionValues[2], 2*roundError)); 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minDivisor <= maxDivisor); 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry InterpolationRange returnValue; 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.max.x() = getMaxFlushToZero(getMaxValueWithinError(getMaxFlushToZero(maximalRangeDivision(minPreDivisionValues[0], maxPreDivisionValues[0], minDivisor, maxDivisor)), divError)); 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.max.y() = getMaxFlushToZero(getMaxValueWithinError(getMaxFlushToZero(maximalRangeDivision(minPreDivisionValues[1], maxPreDivisionValues[1], minDivisor, maxDivisor)), divError)); 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.max.z() = getMaxFlushToZero(getMaxValueWithinError(getMaxFlushToZero(maximalRangeDivision(minPreDivisionValues[2], maxPreDivisionValues[2], minDivisor, maxDivisor)), divError)); 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.min.x() = getMinFlushToZero(getMinValueWithinError(getMinFlushToZero(minimalRangeDivision(minPreDivisionValues[0], maxPreDivisionValues[0], minDivisor, maxDivisor)), divError)); 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.min.y() = getMinFlushToZero(getMinValueWithinError(getMinFlushToZero(minimalRangeDivision(minPreDivisionValues[1], maxPreDivisionValues[1], minDivisor, maxDivisor)), divError)); 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.min.z() = getMinFlushToZero(getMinValueWithinError(getMinFlushToZero(minimalRangeDivision(minPreDivisionValues[2], maxPreDivisionValues[2], minDivisor, maxDivisor)), divError)); 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(returnValue.min.x() <= returnValue.max.x()); 3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(returnValue.min.y() <= returnValue.max.y()); 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(returnValue.min.z() <= returnValue.max.z()); 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return returnValue; 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineInterpolationRange calcLineInterpolationWeights (const tcu::Vec2& pa, float wa, const tcu::Vec2& pb, float wb, const tcu::Vec2& pr) 4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int roundError = 1; 4082306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int divError = 3; 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4102306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // calc weights: 4112306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // (1-t) / wa t / wb 4122306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // ------------------- , ------------------- 4132306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // (1-t) / wa + t / wb (1-t) / wa + t / wb 4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Allow 1 ULP 4162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float dividend = tcu::dot(pr - pa, pb - pa); 4172306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float dividendMax = getMaxValueWithinError(dividend, 1); 4182306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float dividendMin = getMinValueWithinError(dividend, 1); 4192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(dividendMin <= dividendMax); 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Assuming lengthSquared will not be implemented as sqrt(x)^2, allow 1 ULP 4222306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float divisor = tcu::lengthSquared(pb - pa); 4232306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float divisorMax = getMaxValueWithinError(divisor, 1); 4242306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float divisorMin = getMinValueWithinError(divisor, 1); 4252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(divisorMin <= divisorMax); 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Allow 3 ULP precision for division 4282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float tMax = getMaxValueWithinError(maximalRangeDivision(dividendMin, dividendMax, divisorMin, divisorMax), divError); 4292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float tMin = getMinValueWithinError(minimalRangeDivision(dividendMin, dividendMax, divisorMin, divisorMax), divError); 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(tMin <= tMax); 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveTMax = getMaxValueWithinError(maximalRangeDivision(tMin, tMax, wb, wb), divError); 4332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveTMin = getMinValueWithinError(minimalRangeDivision(tMin, tMax, wb, wb), divError); 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(perspectiveTMin <= perspectiveTMax); 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveInvTMax = getMaxValueWithinError(maximalRangeDivision((1.0f - tMax), (1.0f - tMin), wa, wa), divError); 4372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveInvTMin = getMinValueWithinError(minimalRangeDivision((1.0f - tMax), (1.0f - tMin), wa, wa), divError); 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(perspectiveInvTMin <= perspectiveInvTMax); 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveDivisorMax = getMaxValueWithinError(perspectiveTMax + perspectiveInvTMax, roundError); 4412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveDivisorMin = getMinValueWithinError(perspectiveTMin + perspectiveInvTMin, roundError); 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(perspectiveDivisorMin <= perspectiveDivisorMax); 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LineInterpolationRange returnValue; 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.max.x() = getMaxValueWithinError(maximalRangeDivision(perspectiveInvTMin, perspectiveInvTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.max.y() = getMaxValueWithinError(maximalRangeDivision(perspectiveTMin, perspectiveTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.min.x() = getMinValueWithinError(minimalRangeDivision(perspectiveInvTMin, perspectiveInvTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.min.y() = getMinValueWithinError(minimalRangeDivision(perspectiveTMin, perspectiveTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(returnValue.min.x() <= returnValue.max.x()); 4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(returnValue.min.y() <= returnValue.max.y()); 4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return returnValue; 4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineInterpolationRange calcLineInterpolationWeightsAxisProjected (const tcu::Vec2& pa, float wa, const tcu::Vec2& pb, float wb, const tcu::Vec2& pr) 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int roundError = 1; 4592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int divError = 3; 4602306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const bool isXMajor = isLineXMajor(pa, pb); 4612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int majorAxisNdx = (isXMajor) ? (0) : (1); 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4632306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // calc weights: 4642306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // (1-t) / wa t / wb 4652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // ------------------- , ------------------- 4662306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // (1-t) / wa + t / wb (1-t) / wa + t / wb 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4682306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Use axis projected (inaccurate) method, i.e. for X-major lines: 4692306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // (xd - xa) * (xb - xa) xd - xa 4702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // t = --------------------- == ------- 4712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // ( xb - xa ) ^ 2 xb - xa 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Allow 1 ULP 4742306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float dividend = (pr[majorAxisNdx] - pa[majorAxisNdx]); 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float dividendMax = getMaxValueWithinError(dividend, 1); 4762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float dividendMin = getMinValueWithinError(dividend, 1); 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(dividendMin <= dividendMax); 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4792306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Allow 1 ULP 4802306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float divisor = (pb[majorAxisNdx] - pa[majorAxisNdx]); 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float divisorMax = getMaxValueWithinError(divisor, 1); 4822306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float divisorMin = getMinValueWithinError(divisor, 1); 4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(divisorMin <= divisorMax); 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Allow 3 ULP precision for division 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float tMax = getMaxValueWithinError(maximalRangeDivision(dividendMin, dividendMax, divisorMin, divisorMax), divError); 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float tMin = getMinValueWithinError(minimalRangeDivision(dividendMin, dividendMax, divisorMin, divisorMax), divError); 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(tMin <= tMax); 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4902306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveTMax = getMaxValueWithinError(maximalRangeDivision(tMin, tMax, wb, wb), divError); 4912306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveTMin = getMinValueWithinError(minimalRangeDivision(tMin, tMax, wb, wb), divError); 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(perspectiveTMin <= perspectiveTMax); 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4942306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveInvTMax = getMaxValueWithinError(maximalRangeDivision((1.0f - tMax), (1.0f - tMin), wa, wa), divError); 4952306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveInvTMin = getMinValueWithinError(minimalRangeDivision((1.0f - tMax), (1.0f - tMin), wa, wa), divError); 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(perspectiveInvTMin <= perspectiveInvTMax); 4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveDivisorMax = getMaxValueWithinError(perspectiveTMax + perspectiveInvTMax, roundError); 4992306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float perspectiveDivisorMin = getMinValueWithinError(perspectiveTMin + perspectiveInvTMin, roundError); 5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(perspectiveDivisorMin <= perspectiveDivisorMax); 5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LineInterpolationRange returnValue; 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.max.x() = getMaxValueWithinError(maximalRangeDivision(perspectiveInvTMin, perspectiveInvTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.max.y() = getMaxValueWithinError(maximalRangeDivision(perspectiveTMin, perspectiveTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.min.x() = getMinValueWithinError(minimalRangeDivision(perspectiveInvTMin, perspectiveInvTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry returnValue.min.y() = getMinValueWithinError(minimalRangeDivision(perspectiveTMin, perspectiveTMax, perspectiveDivisorMin, perspectiveDivisorMax), divError); 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(returnValue.min.x() <= returnValue.max.x()); 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(returnValue.min.y() <= returnValue.max.y()); 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return returnValue; 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5142306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrytemplate <typename WeightEquation> 5152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineInterpolationRange calcSingleSampleLineInterpolationRangeWithWeightEquation (const tcu::Vec2& pa, 5162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry float wa, 5172306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2& pb, 5182306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry float wb, 5192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2& pixel, 5202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int subpixelBits, 5212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry WeightEquation weightEquation) 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // allow interpolation weights anywhere in the central subpixels 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float testSquareSize = (2.0f / (1UL << subpixelBits)); 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float testSquarePos = (0.5f - testSquareSize / 2); 5262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 corners[4] = 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + testSquarePos + 0.0f, pixel.y() + testSquarePos + 0.0f), 5302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + testSquarePos + 0.0f, pixel.y() + testSquarePos + testSquareSize), 5312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + testSquarePos + testSquareSize, pixel.y() + testSquarePos + testSquareSize), 5322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + testSquarePos + testSquareSize, pixel.y() + testSquarePos + 0.0f), 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // calculate interpolation as a line 5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const LineInterpolationRange weights[4] = 5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry weightEquation(pa, wa, pb, wb, corners[0]), 5392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry weightEquation(pa, wa, pb, wb, corners[1]), 5402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry weightEquation(pa, wa, pb, wb, corners[2]), 5412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry weightEquation(pa, wa, pb, wb, corners[3]), 5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 minWeights = tcu::min(tcu::min(weights[0].min, weights[1].min), tcu::min(weights[2].min, weights[3].min)); 5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 maxWeights = tcu::max(tcu::max(weights[0].max, weights[1].max), tcu::max(weights[2].max, weights[3].max)); 5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LineInterpolationRange result; 5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.min = minWeights; 5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.max = maxWeights; 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return result; 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineInterpolationRange calcSingleSampleLineInterpolationRange (const tcu::Vec2& pa, float wa, const tcu::Vec2& pb, float wb, const tcu::IVec2& pixel, int subpixelBits) 5542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 5552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return calcSingleSampleLineInterpolationRangeWithWeightEquation(pa, wa, pb, wb, pixel, subpixelBits, calcLineInterpolationWeights); 5562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 5572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 5582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineInterpolationRange calcSingleSampleLineInterpolationRangeAxisProjected (const tcu::Vec2& pa, float wa, const tcu::Vec2& pb, float wb, const tcu::IVec2& pixel, int subpixelBits) 5592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 5602306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return calcSingleSampleLineInterpolationRangeWithWeightEquation(pa, wa, pb, wb, pixel, subpixelBits, calcLineInterpolationWeightsAxisProjected); 5612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 5622306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct TriangleInterpolator 5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const TriangleSceneSpec& scene; 5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TriangleInterpolator (const TriangleSceneSpec& scene_) 5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : scene(scene_) 5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry InterpolationRange interpolate (int primitiveNdx, const tcu::IVec2 pixel, const tcu::IVec2 viewportSize, bool multisample, int subpixelBits) const 5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // allow anywhere in the pixel area in multisample 5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // allow only in the center subpixels (4 subpixels) in singlesample 5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float testSquareSize = (multisample) ? (1.0f) : (2.0f / (1UL << subpixelBits)); 5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float testSquarePos = (multisample) ? (0.0f) : (0.5f - testSquareSize / 2); 5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 corners[4] = 5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2((pixel.x() + testSquarePos + 0.0f) / viewportSize.x() * 2.0f - 1.0f, (pixel.y() + testSquarePos + 0.0f ) / viewportSize.y() * 2.0f - 1.0f), 5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2((pixel.x() + testSquarePos + 0.0f) / viewportSize.x() * 2.0f - 1.0f, (pixel.y() + testSquarePos + testSquareSize) / viewportSize.y() * 2.0f - 1.0f), 5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2((pixel.x() + testSquarePos + testSquareSize) / viewportSize.x() * 2.0f - 1.0f, (pixel.y() + testSquarePos + testSquareSize) / viewportSize.y() * 2.0f - 1.0f), 5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2((pixel.x() + testSquarePos + testSquareSize) / viewportSize.x() * 2.0f - 1.0f, (pixel.y() + testSquarePos + 0.0f ) / viewportSize.y() * 2.0f - 1.0f), 5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterpolationRange weights[4] = 5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry calcTriangleInterpolationWeights(scene.triangles[primitiveNdx].positions[0], scene.triangles[primitiveNdx].positions[1], scene.triangles[primitiveNdx].positions[2], corners[0]), 5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry calcTriangleInterpolationWeights(scene.triangles[primitiveNdx].positions[0], scene.triangles[primitiveNdx].positions[1], scene.triangles[primitiveNdx].positions[2], corners[1]), 5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry calcTriangleInterpolationWeights(scene.triangles[primitiveNdx].positions[0], scene.triangles[primitiveNdx].positions[1], scene.triangles[primitiveNdx].positions[2], corners[2]), 5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry calcTriangleInterpolationWeights(scene.triangles[primitiveNdx].positions[0], scene.triangles[primitiveNdx].positions[1], scene.triangles[primitiveNdx].positions[2], corners[3]), 5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry InterpolationRange result; 5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.min = tcu::min(tcu::min(weights[0].min, weights[1].min), tcu::min(weights[2].min, weights[3].min)); 5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.max = tcu::max(tcu::max(weights[0].max, weights[1].max), tcu::max(weights[2].max, weights[3].max)); 5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return result; 5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*! 6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Used only by verifyMultisampleLineGroupInterpolation to calculate 6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * correct line interpolations for the triangulated lines. 6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct MultisampleLineInterpolator 6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const LineSceneSpec& scene; 6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MultisampleLineInterpolator (const LineSceneSpec& scene_) 6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : scene(scene_) 6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry InterpolationRange interpolate (int primitiveNdx, const tcu::IVec2 pixel, const tcu::IVec2 viewportSize, bool multisample, int subpixelBits) const 6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(multisample); 6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(multisample); 6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(subpixelBits); 6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // in triangulation, one line emits two triangles 6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int lineNdx = primitiveNdx / 2; 6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // allow interpolation weights anywhere in the pixel 6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 corners[4] = 6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + 0.0f, pixel.y() + 0.0f), 6262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + 0.0f, pixel.y() + 1.0f), 6272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + 1.0f, pixel.y() + 1.0f), 6282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(pixel.x() + 1.0f, pixel.y() + 0.0f), 6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float wa = scene.lines[lineNdx].positions[0].w(); 6322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float wb = scene.lines[lineNdx].positions[1].w(); 6332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pa = tcu::Vec2((scene.lines[lineNdx].positions[0].x() / wa + 1.0f) * 0.5f * viewportSize.x(), 6342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (scene.lines[lineNdx].positions[0].y() / wa + 1.0f) * 0.5f * viewportSize.y()); 6352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pb = tcu::Vec2((scene.lines[lineNdx].positions[1].x() / wb + 1.0f) * 0.5f * viewportSize.x(), 6362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (scene.lines[lineNdx].positions[1].y() / wb + 1.0f) * 0.5f * viewportSize.y()); 6372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // calculate interpolation as a line 6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const LineInterpolationRange weights[4] = 6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry calcLineInterpolationWeights(pa, wa, pb, wb, corners[0]), 6422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry calcLineInterpolationWeights(pa, wa, pb, wb, corners[1]), 6432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry calcLineInterpolationWeights(pa, wa, pb, wb, corners[2]), 6442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry calcLineInterpolationWeights(pa, wa, pb, wb, corners[3]), 6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 minWeights = tcu::min(tcu::min(weights[0].min, weights[1].min), tcu::min(weights[2].min, weights[3].min)); 6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 maxWeights = tcu::max(tcu::max(weights[0].max, weights[1].max), tcu::max(weights[2].max, weights[3].max)); 6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // convert to three-component form. For all triangles, the vertex 0 is always emitted by the line starting point, and vertex 2 by the ending point 6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry InterpolationRange result; 6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.min = tcu::Vec3(minWeights.x(), 0.0f, minWeights.y()); 6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result.max = tcu::Vec3(maxWeights.x(), 0.0f, maxWeights.y()); 6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return result; 6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename Interpolator> 6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTriangleGroupInterpolationWithInterpolator (const tcu::Surface& surface, const TriangleSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log, const Interpolator& interpolator) 6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA invalidPixelColor = tcu::RGBA(255, 0, 0, 255); 6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool multisampled = (args.numSamples != 0); 6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec2 viewportSize = tcu::IVec2(surface.getWidth(), surface.getHeight()); 6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int errorFloodThreshold = 4; 6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int errorCount = 0; 6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int invalidPixels = 0; 6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int subPixelBits = args.subpixelBits; 6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Surface errorMask (surface.getWidth(), surface.getHeight()); 6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // log format 6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Verifying rasterization result. Native format is RGB" << args.redBits << args.greenBits << args.blueBits << tcu::TestLog::EndMessage; 6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (args.redBits > 8 || args.greenBits > 8 || args.blueBits > 8) 6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Warning! More than 8 bits in a color channel, this may produce false negatives." << tcu::TestLog::EndMessage; 6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // subpixel bits in in a valid range? 6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (subPixelBits < 0) 6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Invalid subpixel count (" << subPixelBits << "), assuming 0" << tcu::TestLog::EndMessage; 6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry subPixelBits = 0; 6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (subPixelBits > 16) 6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // At high subpixel bit counts we might overflow. Checking at lower bit count is ok, but is less strict 6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Subpixel count is greater than 16 (" << subPixelBits << "). Checking results using less strict 16 bit requirements. This may produce false positives." << tcu::TestLog::EndMessage; 6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry subPixelBits = 16; 6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // check pixels 6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < surface.getHeight(); ++y) 6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < surface.getWidth(); ++x) 6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA color = surface.getPixel(x, y); 6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool stackBottomFound = false; 6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int stackSize = 0; 7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec4 colorStackMin; 7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec4 colorStackMax; 7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Iterate triangle coverage front to back, find the stack of pontentially contributing fragments 7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int triNdx = (int)scene.triangles.size() - 1; triNdx >= 0; --triNdx) 7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const CoverageType coverage = calculateTriangleCoverage(scene.triangles[triNdx].positions[0], 7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry scene.triangles[triNdx].positions[1], 7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry scene.triangles[triNdx].positions[2], 7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::IVec2(x, y), 7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry viewportSize, 7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry subPixelBits, 7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry multisampled); 7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coverage == COVERAGE_FULL || coverage == COVERAGE_PARTIAL) 7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // potentially contributes to the result fragment's value 7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterpolationRange weights = interpolator.interpolate(triNdx, tcu::IVec2(x, y), viewportSize, multisampled, subPixelBits); 7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 fragmentColorMax = de::clamp(weights.max.x(), 0.0f, 1.0f) * scene.triangles[triNdx].colors[0] + 7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(weights.max.y(), 0.0f, 1.0f) * scene.triangles[triNdx].colors[1] + 7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(weights.max.z(), 0.0f, 1.0f) * scene.triangles[triNdx].colors[2]; 7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4 fragmentColorMin = de::clamp(weights.min.x(), 0.0f, 1.0f) * scene.triangles[triNdx].colors[0] + 7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(weights.min.y(), 0.0f, 1.0f) * scene.triangles[triNdx].colors[1] + 7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(weights.min.z(), 0.0f, 1.0f) * scene.triangles[triNdx].colors[2]; 7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (stackSize++ == 0) 7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // first triangle, set the values properly 7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry colorStackMin = fragmentColorMin; 7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry colorStackMax = fragmentColorMax; 7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // contributing triangle 7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry colorStackMin = tcu::min(colorStackMin, fragmentColorMin); 7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry colorStackMax = tcu::max(colorStackMax, fragmentColorMax); 7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coverage == COVERAGE_FULL) 7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // loop terminates, this is the bottommost fragment 7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry stackBottomFound = true; 7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Partial coverage == background may be visible 7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (stackSize != 0 && !stackBottomFound) 7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry stackSize++; 7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry colorStackMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); 7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Is the result image color in the valid range. 7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (stackSize == 0) 7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // No coverage, allow only background (black, value=0) 7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec3 pixelNativeColor = convertRGB8ToNativeFormat(color, args); 7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int threshold = 1; 7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (pixelNativeColor.x() > threshold || 7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.y() > threshold || 7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.z() > threshold) 7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++errorCount; 7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // don't fill the logs with too much data 7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (errorCount < errorFloodThreshold) 7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message 7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "Found an invalid pixel at (" << x << "," << y << ")\n" 7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tPixel color:\t\t" << color << "\n" 7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tExpected background color.\n" 7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndMessage; 7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++invalidPixels; 7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, invalidPixelColor); 7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(stackSize); 7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Each additional step in the stack may cause conversion error of 1 bit due to undefined rounding direction 7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int thresholdRed = stackSize - 1; 7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int thresholdGreen = stackSize - 1; 7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int thresholdBlue = stackSize - 1; 7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec3 valueRangeMin = tcu::Vec3(colorStackMin.xyz()); 7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec3 valueRangeMax = tcu::Vec3(colorStackMax.xyz()); 7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec3 formatLimit ((1 << args.redBits) - 1, (1 << args.greenBits) - 1, (1 << args.blueBits) - 1); 7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec3 colorMinF (de::clamp(valueRangeMin.x() * formatLimit.x(), 0.0f, (float)formatLimit.x()), 7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(valueRangeMin.y() * formatLimit.y(), 0.0f, (float)formatLimit.y()), 7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(valueRangeMin.z() * formatLimit.z(), 0.0f, (float)formatLimit.z())); 7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec3 colorMaxF (de::clamp(valueRangeMax.x() * formatLimit.x(), 0.0f, (float)formatLimit.x()), 7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(valueRangeMax.y() * formatLimit.y(), 0.0f, (float)formatLimit.y()), 8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::clamp(valueRangeMax.z() * formatLimit.z(), 0.0f, (float)formatLimit.z())); 8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec3 colorMin ((int)deFloatFloor(colorMinF.x()), 8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int)deFloatFloor(colorMinF.y()), 8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int)deFloatFloor(colorMinF.z())); 8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec3 colorMax ((int)deFloatCeil (colorMaxF.x()), 8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int)deFloatCeil (colorMaxF.y()), 8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int)deFloatCeil (colorMaxF.z())); 8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Convert pixel color from rgba8 to the real pixel format. Usually rgba8 or 565 8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec3 pixelNativeColor = convertRGB8ToNativeFormat(color, args); 8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Validity check 8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (pixelNativeColor.x() < colorMin.x() - thresholdRed || 8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.y() < colorMin.y() - thresholdGreen || 8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.z() < colorMin.z() - thresholdBlue || 8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.x() > colorMax.x() + thresholdRed || 8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.y() > colorMax.y() + thresholdGreen || 8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.z() > colorMax.z() + thresholdBlue) 8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++errorCount; 8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // don't fill the logs with too much data 8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (errorCount <= errorFloodThreshold) 8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message 8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "Found an invalid pixel at (" << x << "," << y << ")\n" 8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tPixel color:\t\t" << color << "\n" 8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tNative color:\t\t" << pixelNativeColor << "\n" 8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tAllowed error:\t\t" << tcu::IVec3(thresholdRed, thresholdGreen, thresholdBlue) << "\n" 8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tReference native color min: " << tcu::clamp(colorMin - tcu::IVec3(thresholdRed, thresholdGreen, thresholdBlue), tcu::IVec3(0,0,0), formatLimit) << "\n" 8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tReference native color max: " << tcu::clamp(colorMax + tcu::IVec3(thresholdRed, thresholdGreen, thresholdBlue), tcu::IVec3(0,0,0), formatLimit) << "\n" 8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tReference native float min: " << tcu::clamp(colorMinF - tcu::IVec3(thresholdRed, thresholdGreen, thresholdBlue).cast<float>(), tcu::Vec3(0.0f, 0.0f, 0.0f), formatLimit.cast<float>()) << "\n" 8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tReference native float max: " << tcu::clamp(colorMaxF + tcu::IVec3(thresholdRed, thresholdGreen, thresholdBlue).cast<float>(), tcu::Vec3(0.0f, 0.0f, 0.0f), formatLimit.cast<float>()) << "\n" 8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tFmin:\t" << tcu::clamp(valueRangeMin, tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 1.0f)) << "\n" 8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tFmax:\t" << tcu::clamp(valueRangeMax, tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 1.0f)) << "\n" 8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndMessage; 8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++invalidPixels; 8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, invalidPixelColor); 8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // don't just hide failures 8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (errorCount > errorFloodThreshold) 8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Omitted " << (errorCount-errorFloodThreshold) << " pixel error description(s)." << tcu::TestLog::EndMessage; 8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // report result 8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (invalidPixels) 8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << invalidPixels << " invalid pixel(s) found." << tcu::TestLog::EndMessage; 8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("ErrorMask", "ErrorMask", errorMask) 8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage; 8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyMultisampleLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Multisampled line == 2 triangles 8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 viewportSize = tcu::Vec2((float)surface.getWidth(), (float)surface.getHeight()); 8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float halfLineWidth = scene.lineWidth * 0.5f; 8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TriangleSceneSpec triangleScene; 8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles.resize(2 * scene.lines.size()); 8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx) 8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Transform to screen space, add pixel offsets, convert back to normalized device space, and test as triangles 8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineNormalizedDeviceSpace[2] = 8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(scene.lines[lineNdx].positions[0].x() / scene.lines[lineNdx].positions[0].w(), scene.lines[lineNdx].positions[0].y() / scene.lines[lineNdx].positions[0].w()), 8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(scene.lines[lineNdx].positions[1].x() / scene.lines[lineNdx].positions[1].w(), scene.lines[lineNdx].positions[1].y() / scene.lines[lineNdx].positions[1].w()), 8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineScreenSpace[2] = 8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (lineNormalizedDeviceSpace[0] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * viewportSize, 8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (lineNormalizedDeviceSpace[1] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * viewportSize, 8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineDir = tcu::normalize(lineScreenSpace[1] - lineScreenSpace[0]); 8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineNormalDir = tcu::Vec2(lineDir.y(), -lineDir.x()); 8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineQuadScreenSpace[4] = 8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[0] + lineNormalDir * halfLineWidth, 8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[0] - lineNormalDir * halfLineWidth, 9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[1] - lineNormalDir * halfLineWidth, 9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[1] + lineNormalDir * halfLineWidth, 9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineQuadNormalizedDeviceSpace[4] = 9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[0] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[1] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[2] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[3] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); triangleScene.triangles[lineNdx*2 + 0].sharedEdge[0] = false; 9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[1].x(), lineQuadNormalizedDeviceSpace[1].y(), 0.0f, 1.0f); triangleScene.triangles[lineNdx*2 + 0].sharedEdge[1] = false; 9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); triangleScene.triangles[lineNdx*2 + 0].sharedEdge[2] = true; 9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); triangleScene.triangles[lineNdx*2 + 1].sharedEdge[0] = true; 9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); triangleScene.triangles[lineNdx*2 + 1].sharedEdge[1] = false; 9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[3].x(), lineQuadNormalizedDeviceSpace[3].y(), 0.0f, 1.0f); triangleScene.triangles[lineNdx*2 + 1].sharedEdge[2] = false; 9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyTriangleGroupRasterization(surface, triangleScene, args, log); 9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyMultisampleLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Multisampled line == 2 triangles 9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 viewportSize = tcu::Vec2((float)surface.getWidth(), (float)surface.getHeight()); 9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float halfLineWidth = scene.lineWidth * 0.5f; 9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TriangleSceneSpec triangleScene; 9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles.resize(2 * scene.lines.size()); 9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx) 9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Transform to screen space, add pixel offsets, convert back to normalized device space, and test as triangles 9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineNormalizedDeviceSpace[2] = 9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(scene.lines[lineNdx].positions[0].x() / scene.lines[lineNdx].positions[0].w(), scene.lines[lineNdx].positions[0].y() / scene.lines[lineNdx].positions[0].w()), 9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(scene.lines[lineNdx].positions[1].x() / scene.lines[lineNdx].positions[1].w(), scene.lines[lineNdx].positions[1].y() / scene.lines[lineNdx].positions[1].w()), 9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineScreenSpace[2] = 9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (lineNormalizedDeviceSpace[0] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * viewportSize, 9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (lineNormalizedDeviceSpace[1] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * viewportSize, 9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineDir = tcu::normalize(lineScreenSpace[1] - lineScreenSpace[0]); 9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineNormalDir = tcu::Vec2(lineDir.y(), -lineDir.x()); 9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineQuadScreenSpace[4] = 9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[0] + lineNormalDir * halfLineWidth, 9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[0] - lineNormalDir * halfLineWidth, 9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[1] - lineNormalDir * halfLineWidth, 9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineScreenSpace[1] + lineNormalDir * halfLineWidth, 9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineQuadNormalizedDeviceSpace[4] = 9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[0] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[1] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[2] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineQuadScreenSpace[3] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); 9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[1].x(), lineQuadNormalizedDeviceSpace[1].y(), 0.0f, 1.0f); 9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); 9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].sharedEdge[0] = false; 9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].sharedEdge[1] = false; 9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].sharedEdge[2] = true; 9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].colors[0] = scene.lines[lineNdx].colors[0]; 9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].colors[1] = scene.lines[lineNdx].colors[0]; 9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 0].colors[2] = scene.lines[lineNdx].colors[1]; 9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); 9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); 9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[3].x(), lineQuadNormalizedDeviceSpace[3].y(), 0.0f, 1.0f); 9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].sharedEdge[0] = true; 9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].sharedEdge[1] = false; 9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].sharedEdge[2] = false; 9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].colors[0] = scene.lines[lineNdx].colors[0]; 9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].colors[1] = scene.lines[lineNdx].colors[1]; 9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[lineNdx*2 + 1].colors[2] = scene.lines[lineNdx].colors[1]; 9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyTriangleGroupInterpolationWithInterpolator(surface, triangleScene, args, log, MultisampleLineInterpolator(scene)); 9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyMultisamplePointGroupRasterization (const tcu::Surface& surface, const PointSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Multisampled point == 2 triangles 9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 viewportSize = tcu::Vec2((float)surface.getWidth(), (float)surface.getHeight()); 9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TriangleSceneSpec triangleScene; 9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles.resize(2 * scene.points.size()); 10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int pointNdx = 0; pointNdx < (int)scene.points.size(); ++pointNdx) 10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Transform to screen space, add pixel offsets, convert back to normalized device space, and test as triangles 10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 pointNormalizedDeviceSpace = tcu::Vec2(scene.points[pointNdx].position.x() / scene.points[pointNdx].position.w(), scene.points[pointNdx].position.y() / scene.points[pointNdx].position.w()); 10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 pointScreenSpace = (pointNormalizedDeviceSpace + tcu::Vec2(1.0f, 1.0f)) * 0.5f * viewportSize; 10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float offset = scene.points[pointNdx].pointSize * 0.5f; 10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 lineQuadNormalizedDeviceSpace[4] = 10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (pointScreenSpace + tcu::Vec2(-offset, -offset))/ viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (pointScreenSpace + tcu::Vec2(-offset, offset))/ viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (pointScreenSpace + tcu::Vec2( offset, offset))/ viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (pointScreenSpace + tcu::Vec2( offset, -offset))/ viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f), 10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[pointNdx*2 + 0].positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); triangleScene.triangles[pointNdx*2 + 0].sharedEdge[0] = false; 10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[pointNdx*2 + 0].positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[1].x(), lineQuadNormalizedDeviceSpace[1].y(), 0.0f, 1.0f); triangleScene.triangles[pointNdx*2 + 0].sharedEdge[1] = false; 10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[pointNdx*2 + 0].positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); triangleScene.triangles[pointNdx*2 + 0].sharedEdge[2] = true; 10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[pointNdx*2 + 1].positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); triangleScene.triangles[pointNdx*2 + 1].sharedEdge[0] = true; 10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[pointNdx*2 + 1].positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); triangleScene.triangles[pointNdx*2 + 1].sharedEdge[1] = false; 10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry triangleScene.triangles[pointNdx*2 + 1].positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[3].x(), lineQuadNormalizedDeviceSpace[3].y(), 0.0f, 1.0f); triangleScene.triangles[pointNdx*2 + 1].sharedEdge[2] = false; 10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyTriangleGroupRasterization(surface, triangleScene, args, log); 10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyryvoid genScreenSpaceLines (std::vector<tcu::Vec4>& screenspaceLines, const std::vector<LineSceneSpec::SceneLine>& lines, const tcu::IVec2& viewportSize) 10272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 10282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(screenspaceLines.size() == lines.size()); 10292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 10302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int lineNdx = 0; lineNdx < (int)lines.size(); ++lineNdx) 10312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 10322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 lineNormalizedDeviceSpace[2] = 10332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 10342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(lines[lineNdx].positions[0].x() / lines[lineNdx].positions[0].w(), lines[lineNdx].positions[0].y() / lines[lineNdx].positions[0].w()), 10352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec2(lines[lineNdx].positions[1].x() / lines[lineNdx].positions[1].w(), lines[lineNdx].positions[1].y() / lines[lineNdx].positions[1].w()), 10362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry }; 10372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec4 lineScreenSpace[2] = 10382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 10392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec4((lineNormalizedDeviceSpace[0].x() + 1.0f) * 0.5f * (float)viewportSize.x(), (lineNormalizedDeviceSpace[0].y() + 1.0f) * 0.5f * (float)viewportSize.y(), 0.0f, 1.0f), 10402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec4((lineNormalizedDeviceSpace[1].x() + 1.0f) * 0.5f * (float)viewportSize.x(), (lineNormalizedDeviceSpace[1].y() + 1.0f) * 0.5f * (float)viewportSize.y(), 0.0f, 1.0f), 10412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry }; 10422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 10432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry screenspaceLines[lineNdx] = tcu::Vec4(lineScreenSpace[0].x(), lineScreenSpace[0].y(), lineScreenSpace[1].x(), lineScreenSpace[1].y()); 10442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 10452306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 10462306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifySinglesampleLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(deFloatFrac(scene.lineWidth) != 0.5f); // rounding direction is not defined, disallow undefined cases 10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(scene.lines.size() < 255); // indices are stored as unsigned 8-bit ints 10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10522306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry bool allOK = true; 10532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry bool overdrawInReference = false; 10542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int referenceFragments = 0; 10552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int resultFragments = 0; 10562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int lineWidth = deFloorFloatToInt32(scene.lineWidth + 0.5f); 10572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry bool imageShown = false; 10582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<bool> lineIsXMajor (scene.lines.size()); 10592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<tcu::Vec4> screenspaceLines(scene.lines.size()); 10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Reference renderer produces correct fragments using the diamond-rule. Make 2D int array, each cell contains the highest index (first index = 1) of the overlapping lines or 0 if no line intersects the pixel 10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureLevel referenceLineMap(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT8), surface.getWidth(), surface.getHeight()); 10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::clear(referenceLineMap.getAccess(), tcu::IVec4(0, 0, 0, 0)); 10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry genScreenSpaceLines(screenspaceLines, scene.lines, tcu::IVec2(surface.getWidth(), surface.getHeight())); 10662306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx) 10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry rr::SingleSampleLineRasterizer rasterizer(tcu::IVec4(0, 0, surface.getWidth(), surface.getHeight())); 10702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rasterizer.init(tcu::Vec4(screenspaceLines[lineNdx][0], 10712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry screenspaceLines[lineNdx][1], 10722306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 0.0f, 10732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 1.0f), 10742306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec4(screenspaceLines[lineNdx][2], 10752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry screenspaceLines[lineNdx][3], 10762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 0.0f, 10772306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 1.0f), 10782306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry scene.lineWidth); 10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // calculate majority of later use 10812306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineIsXMajor[lineNdx] = isPackedSSLineXMajor(screenspaceLines[lineNdx]); 10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (;;) 10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxPackets = 32; 10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numRasterized = 0; 10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry rr::FragmentPacket packets[maxPackets]; 10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry rasterizer.rasterize(packets, DE_NULL, maxPackets, numRasterized); 10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int packetNdx = 0; packetNdx < numRasterized; ++packetNdx) 10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((deUint32)packets[packetNdx].coverage & (1 << fragNdx)) 10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec2 fragPos = packets[packetNdx].position + tcu::IVec2(fragNdx%2, fragNdx/2); 10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check for overdraw 11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!overdrawInReference) 11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry overdrawInReference = referenceLineMap.getAccess().getPixelInt(fragPos.x(), fragPos.y()).x() != 0; 11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Output pixel 11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry referenceLineMap.getAccess().setPixel(tcu::IVec4(lineNdx + 1, 0, 0, 0), fragPos.x(), fragPos.y()); 11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (numRasterized != maxPackets) 11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Requirement 1: The coordinates of a fragment produced by the algorithm may not deviate by more than one unit 11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Surface errorMask (surface.getWidth(), surface.getHeight()); 11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool missingFragments = false; 11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::clear(errorMask.getAccess(), tcu::IVec4(0, 255, 0, 255)); 11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Searching for deviating fragments." << tcu::TestLog::EndMessage; 11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < referenceLineMap.getHeight(); ++y) 11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < referenceLineMap.getWidth(); ++x) 11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool reference = referenceLineMap.getAccess().getPixelInt(x, y).x() != 0; 11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool result = compareColors(surface.getPixel(x, y), tcu::RGBA::white, args.redBits, args.greenBits, args.blueBits); 11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (reference) 11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++referenceFragments; 11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (result) 11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++resultFragments; 11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (reference == result) 11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Reference fragment here, matching result fragment must be nearby 11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (reference && !result) 11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool foundFragment = false; 11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (x == 0 || y == 0 || x == referenceLineMap.getWidth() - 1 || y == referenceLineMap.getHeight() -1) 11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // image boundary, missing fragment could be over the image edge 11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry foundFragment = true; 11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // find nearby fragment 11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dy = -1; dy < 2 && !foundFragment; ++dy) 11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dx = -1; dx < 2 && !foundFragment; ++dx) 11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (compareColors(surface.getPixel(x+dx, y+dy), tcu::RGBA::white, args.redBits, args.greenBits, args.blueBits)) 11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry foundFragment = true; 11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!foundFragment) 11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry missingFragments = true; 11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, tcu::RGBA::red); 11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (missingFragments) 11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Invalid deviation(s) found." << tcu::TestLog::EndMessage; 11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("ErrorMask", "ErrorMask", errorMask) 11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageShown = true; 11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry allOK = false; 11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "No invalid deviations found." << tcu::TestLog::EndMessage; 11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Requirement 2: The total number of fragments produced by the algorithm may differ from 11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // that produced by the diamond-exit rule by no more than one. 11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check is not valid if the primitives intersect or otherwise share same fragments 11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!overdrawInReference) 11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int allowedDeviation = (int)scene.lines.size() * lineWidth; // one pixel per primitive in the major direction 11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Verifying fragment counts:\n" 11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tDiamond-exit rule: " << referenceFragments << " fragments.\n" 11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tResult image: " << resultFragments << " fragments.\n" 11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tAllowing deviation of " << allowedDeviation << " fragments.\n" 11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndMessage; 11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (deAbs32(referenceFragments - resultFragments) > allowedDeviation) 11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Surface reference(surface.getWidth(), surface.getHeight()); 11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // show a helpful reference image 12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::clear(reference.getAccess(), tcu::IVec4(0, 0, 0, 255)); 12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < surface.getHeight(); ++y) 12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < surface.getWidth(); ++x) 12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (referenceLineMap.getAccess().getPixelInt(x, y).x()) 12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry reference.setPixel(x, y, tcu::RGBA::white); 12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Invalid fragment count in result image." << tcu::TestLog::EndMessage; 12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Reference", "Reference", reference) 12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry allOK = false; 12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageShown = true; 12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Fragment count is valid." << tcu::TestLog::EndMessage; 12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Overdraw in scene. Fragment count cannot be verified. Skipping fragment count checks." << tcu::TestLog::EndMessage; 12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Requirement 3: Line width must be constant 12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool invalidWidthFound = false; 12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Verifying line widths of the x-major lines." << tcu::TestLog::EndMessage; 12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 1; y < referenceLineMap.getHeight() - 1; ++y) 12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool fullyVisibleLine = false; 12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool previousPixelUndefined = false; 12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int currentLine = 0; 12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int currentWidth = 1; 12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 1; x < referenceLineMap.getWidth() - 1; ++x) 12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool result = compareColors(surface.getPixel(x, y), tcu::RGBA::white, args.redBits, args.greenBits, args.blueBits); 12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int lineID = 0; 12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Which line does this fragment belong to? 12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (result) 12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool multipleNearbyLines = false; 12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dy = -1; dy < 2; ++dy) 12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dx = -1; dx < 2; ++dx) 12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int nearbyID = referenceLineMap.getAccess().getPixelInt(x+dx, y+dy).x(); 12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (nearbyID) 12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (lineID && lineID != nearbyID) 12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry multipleNearbyLines = true; 12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineID = nearbyID; 12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (multipleNearbyLines) 12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Another line is too close, don't try to calculate width here 12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry previousPixelUndefined = true; 12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Only line with id of lineID is nearby 12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (previousPixelUndefined) 12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // The line might have been overdrawn or not 12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentLine = lineID; 12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentWidth = 1; 12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fullyVisibleLine = false; 12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry previousPixelUndefined = false; 12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (lineID == currentLine) 12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Current line continues 12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++currentWidth; 12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (lineID > currentLine) 12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Another line was drawn over or the line ends 12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentLine = lineID; 12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentWidth = 1; 12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fullyVisibleLine = true; 12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // The line ends 12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (fullyVisibleLine && !lineIsXMajor[currentLine-1]) 12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // check width 12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (currentWidth != lineWidth) 12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "\tInvalid line width at (" << x - currentWidth << ", " << y << ") - (" << x - 1 << ", " << y << "). Detected width of " << currentWidth << ", expected " << lineWidth << tcu::TestLog::EndMessage; 13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry invalidWidthFound = true; 13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentLine = lineID; 13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentWidth = 1; 13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fullyVisibleLine = false; 13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Verifying line widths of the y-major lines." << tcu::TestLog::EndMessage; 13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 1; x < referenceLineMap.getWidth() - 1; ++x) 13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool fullyVisibleLine = false; 13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool previousPixelUndefined = false; 13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int currentLine = 0; 13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int currentWidth = 1; 13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 1; y < referenceLineMap.getHeight() - 1; ++y) 13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool result = compareColors(surface.getPixel(x, y), tcu::RGBA::white, args.redBits, args.greenBits, args.blueBits); 13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int lineID = 0; 13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Which line does this fragment belong to? 13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (result) 13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool multipleNearbyLines = false; 13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dy = -1; dy < 2; ++dy) 13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dx = -1; dx < 2; ++dx) 13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int nearbyID = referenceLineMap.getAccess().getPixelInt(x+dx, y+dy).x(); 13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (nearbyID) 13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (lineID && lineID != nearbyID) 13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry multipleNearbyLines = true; 13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineID = nearbyID; 13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (multipleNearbyLines) 13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Another line is too close, don't try to calculate width here 13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry previousPixelUndefined = true; 13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Only line with id of lineID is nearby 13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (previousPixelUndefined) 13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // The line might have been overdrawn or not 13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentLine = lineID; 13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentWidth = 1; 13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fullyVisibleLine = false; 13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry previousPixelUndefined = false; 13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (lineID == currentLine) 13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Current line continues 13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++currentWidth; 13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (lineID > currentLine) 13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Another line was drawn over or the line ends 13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentLine = lineID; 13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentWidth = 1; 13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fullyVisibleLine = true; 13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // The line ends 13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (fullyVisibleLine && lineIsXMajor[currentLine-1]) 13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // check width 13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (currentWidth != lineWidth) 13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "\tInvalid line width at (" << x << ", " << y - currentWidth << ") - (" << x << ", " << y - 1 << "). Detected width of " << currentWidth << ", expected " << lineWidth << tcu::TestLog::EndMessage; 13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry invalidWidthFound = true; 13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentLine = lineID; 13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry currentWidth = 1; 13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fullyVisibleLine = false; 13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (invalidWidthFound) 13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Invalid line width found, image is not valid." << tcu::TestLog::EndMessage; 13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry allOK = false; 13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Line widths are valid." << tcu::TestLog::EndMessage; 14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //\todo [2013-10-24 jarkko]. 14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //Requirement 4. If two line segments share a common endpoint, and both segments are either 14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //x-major (both left-to-right or both right-to-left) or y-major (both bottom-totop 14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //or both top-to-bottom), then rasterizing both segments may not produce 14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //duplicate fragments, nor may any fragments be omitted so as to interrupt 14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry //continuity of the connected segments. 14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!imageShown) 14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return allOK; 14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrystruct SingleSampleNarrowLineCandidate 14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int lineNdx; 14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::IVec3 colorMin; 14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::IVec3 colorMax; 14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec3 colorMinF; 14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec3 colorMaxF; 14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec3 valueRangeMin; 14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec3 valueRangeMax; 14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyryvoid setMaskMapCoverageBitForLine (int bitNdx, const tcu::Vec2& screenSpaceP0, const tcu::Vec2& screenSpaceP1, float lineWidth, tcu::PixelBufferAccess maskMap) 14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry enum 14342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 14352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry MAX_PACKETS = 32, 14362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry }; 14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rr::SingleSampleLineRasterizer rasterizer (tcu::IVec4(0, 0, maskMap.getWidth(), maskMap.getHeight())); 14392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int numRasterized = MAX_PACKETS; 14402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rr::FragmentPacket packets[MAX_PACKETS]; 14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rasterizer.init(tcu::Vec4(screenSpaceP0.x(), screenSpaceP0.y(), 0.0f, 1.0f), 14432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec4(screenSpaceP1.x(), screenSpaceP1.y(), 0.0f, 1.0f), 14442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineWidth); 14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14462306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry while (numRasterized == MAX_PACKETS) 14472306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 14482306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rasterizer.rasterize(packets, DE_NULL, MAX_PACKETS, numRasterized); 14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14502306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int packetNdx = 0; packetNdx < numRasterized; ++packetNdx) 14512306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 14522306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 14532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 14542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if ((deUint32)packets[packetNdx].coverage & (1 << fragNdx)) 14552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 14562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 fragPos = packets[packetNdx].position + tcu::IVec2(fragNdx%2, fragNdx/2); 14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(deInBounds32(fragPos.x(), 0, maskMap.getWidth())); 14592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(deInBounds32(fragPos.y(), 0, maskMap.getHeight())); 14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int previousMask = maskMap.getPixelInt(fragPos.x(), fragPos.y()).x(); 14622306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int newMask = (previousMask) | (1UL << bitNdx); 14632306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 14642306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry maskMap.setPixel(tcu::IVec4(newMask, 0, 0, 0), fragPos.x(), fragPos.y()); 14652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 14662306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 14672306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 14682306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 14692306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 14702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 14712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyryvoid setMaskMapCoverageBitForLines (const std::vector<tcu::Vec4>& screenspaceLines, float lineWidth, tcu::PixelBufferAccess maskMap) 14722306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 14732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int lineNdx = 0; lineNdx < (int)screenspaceLines.size(); ++lineNdx) 14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pa = screenspaceLines[lineNdx].swizzle(0, 1); 14762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pb = screenspaceLines[lineNdx].swizzle(2, 3); 14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14782306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry setMaskMapCoverageBitForLine(lineNdx, pa, pb, lineWidth, maskMap); 14792306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 14802306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14822306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry// verify line interpolation assuming line pixels are interpolated independently depending only on screen space location 14832306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrybool verifyLineGroupPixelIndependentInterpolation (const tcu::Surface& surface, 14842306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const LineSceneSpec& scene, 14852306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const RasterizationArguments& args, 14862306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::TestLog& log, 14872306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry LineInterpolationMethod interpolationMethod) 14882306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 14892306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(scene.lines.size() < 8); // coverage indices are stored as bitmask in a unsigned 8-bit ints 14902306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(interpolationMethod == LINEINTERPOLATION_STRICTLY_CORRECT || interpolationMethod == LINEINTERPOLATION_PROJECTED); 14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14922306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::RGBA invalidPixelColor = tcu::RGBA(255, 0, 0, 255); 14932306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 viewportSize = tcu::IVec2(surface.getWidth(), surface.getHeight()); 14942306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int errorFloodThreshold = 4; 14952306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int errorCount = 0; 14962306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Surface errorMask (surface.getWidth(), surface.getHeight()); 14972306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int invalidPixels = 0; 14982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<tcu::Vec4> screenspaceLines (scene.lines.size()); //!< packed (x0, y0, x1, y1) 14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15002306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Reference renderer produces correct fragments using the diamond-exit-rule. Make 2D int array, store line coverage as a 8-bit bitfield 15012306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // The map is used to find lines with potential coverage to a given pixel 15022306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::TextureLevel referenceLineMap (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT8), surface.getWidth(), surface.getHeight()); 15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15042306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::clear(referenceLineMap.getAccess(), tcu::IVec4(0, 0, 0, 0)); 15052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // log format 15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15092306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << "Verifying rasterization result. Native format is RGB" << args.redBits << args.greenBits << args.blueBits << tcu::TestLog::EndMessage; 15102306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (args.redBits > 8 || args.greenBits > 8 || args.blueBits > 8) 15112306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << "Warning! More than 8 bits in a color channel, this may produce false negatives." << tcu::TestLog::EndMessage; 15122306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 15132306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // prepare lookup map 15142306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 15152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry genScreenSpaceLines(screenspaceLines, scene.lines, viewportSize); 15162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry setMaskMapCoverageBitForLines(screenspaceLines, scene.lineWidth, referenceLineMap.getAccess()); 15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Find all possible lines with coverage, check pixel color matches one of them 15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 1; y < surface.getHeight() - 1; ++y) 15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 1; x < surface.getWidth() - 1; ++x) 15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA color = surface.getPixel(x, y); 15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec3 pixelNativeColor = convertRGB8ToNativeFormat(color, args); // Convert pixel color from rgba8 to the real pixel format. Usually rgba8 or 565 15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int lineCoverageSet = 0; // !< lines that may cover this fragment 15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int lineSurroundingCoverage = 0xFFFF; // !< lines that will cover this fragment 15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool matchFound = false; 15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec3 formatLimit ((1 << args.redBits) - 1, (1 << args.greenBits) - 1, (1 << args.blueBits) - 1); 15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<SingleSampleNarrowLineCandidate> candidates; 15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Find lines with possible coverage 15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dy = -1; dy < 2; ++dy) 15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int dx = -1; dx < 2; ++dx) 15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int coverage = referenceLineMap.getAccess().getPixelInt(x+dx, y+dy).x(); 15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineCoverageSet |= coverage; 15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry lineSurroundingCoverage &= coverage; 15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // background color is possible? 15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (lineSurroundingCoverage == 0 && compareColors(color, tcu::RGBA::black, args.redBits, args.greenBits, args.blueBits)) 15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check those lines 15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx) 15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (((lineCoverageSet >> lineNdx) & 0x01) != 0) 15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float wa = scene.lines[lineNdx].positions[0].w(); 15542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float wb = scene.lines[lineNdx].positions[1].w(); 15552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pa = screenspaceLines[lineNdx].swizzle(0, 1); 15562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pb = screenspaceLines[lineNdx].swizzle(2, 3); 15572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 15582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const LineInterpolationRange range = (interpolationMethod == LINEINTERPOLATION_STRICTLY_CORRECT) 15592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry ? (calcSingleSampleLineInterpolationRange(pa, wa, pb, wb, tcu::IVec2(x, y), args.subpixelBits)) 15602306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry : (calcSingleSampleLineInterpolationRangeAxisProjected(pa, wa, pb, wb, tcu::IVec2(x, y), args.subpixelBits)); 15612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 15622306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec4 valueMin = de::clamp(range.min.x(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[0] + de::clamp(range.min.y(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[1]; 15632306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec4 valueMax = de::clamp(range.max.x(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[0] + de::clamp(range.max.y(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[1]; 15642306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 15652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec3 colorMinF (de::clamp(valueMin.x() * formatLimit.x(), 0.0f, (float)formatLimit.x()), 15662306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMin.y() * formatLimit.y(), 0.0f, (float)formatLimit.y()), 15672306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMin.z() * formatLimit.z(), 0.0f, (float)formatLimit.z())); 15682306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec3 colorMaxF (de::clamp(valueMax.x() * formatLimit.x(), 0.0f, (float)formatLimit.x()), 15692306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMax.y() * formatLimit.y(), 0.0f, (float)formatLimit.y()), 15702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMax.z() * formatLimit.z(), 0.0f, (float)formatLimit.z())); 15712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec3 colorMin ((int)deFloatFloor(colorMinF.x()), 15722306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatFloor(colorMinF.y()), 15732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatFloor(colorMinF.z())); 15742306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec3 colorMax ((int)deFloatCeil (colorMaxF.x()), 15752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatCeil (colorMaxF.y()), 15762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatCeil (colorMaxF.z())); 15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Verify validity 15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (pixelNativeColor.x() < colorMin.x() || 15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.y() < colorMin.y() || 15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.z() < colorMin.z() || 15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.x() > colorMax.x() || 15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.y() > colorMax.y() || 15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pixelNativeColor.z() > colorMax.z()) 15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (errorCount < errorFloodThreshold) 15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Store candidate information for logging 15892306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry SingleSampleNarrowLineCandidate candidate; 15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidate.lineNdx = lineNdx; 15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidate.colorMin = colorMin; 15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidate.colorMax = colorMax; 15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidate.colorMinF = colorMinF; 15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidate.colorMaxF = colorMaxF; 15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidate.valueRangeMin = valueMin.swizzle(0, 1, 2); 15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidate.valueRangeMax = valueMax.swizzle(0, 1, 2); 15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry candidates.push_back(candidate); 16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry matchFound = true; 16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (matchFound) 16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // invalid fragment 16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++invalidPixels; 16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, invalidPixelColor); 16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++errorCount; 16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // don't fill the logs with too much data 16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (errorCount < errorFloodThreshold) 16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message 16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "Found an invalid pixel at (" << x << "," << y << "), " << (int)candidates.size() << " candidate reference value(s) found:\n" 16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tPixel color:\t\t" << color << "\n" 16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\tNative color:\t\t" << pixelNativeColor << "\n" 16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndMessage; 16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int candidateNdx = 0; candidateNdx < (int)candidates.size(); ++candidateNdx) 16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const SingleSampleNarrowLineCandidate& candidate = candidates[candidateNdx]; 16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "\tCandidate (line " << candidate.lineNdx << "):\n" 16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\t\tReference native color min: " << tcu::clamp(candidate.colorMin, tcu::IVec3(0,0,0), formatLimit) << "\n" 16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\t\tReference native color max: " << tcu::clamp(candidate.colorMax, tcu::IVec3(0,0,0), formatLimit) << "\n" 16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\t\tReference native float min: " << tcu::clamp(candidate.colorMinF, tcu::Vec3(0.0f, 0.0f, 0.0f), formatLimit.cast<float>()) << "\n" 16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\t\tReference native float max: " << tcu::clamp(candidate.colorMaxF, tcu::Vec3(0.0f, 0.0f, 0.0f), formatLimit.cast<float>()) << "\n" 16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\t\tFmin:\t" << tcu::clamp(candidate.valueRangeMin, tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 1.0f)) << "\n" 16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\t\tFmax:\t" << tcu::clamp(candidate.valueRangeMax, tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 1.0f)) << "\n" 16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndMessage; 16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // don't just hide failures 16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (errorCount > errorFloodThreshold) 16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Omitted " << (errorCount-errorFloodThreshold) << " pixel error description(s)." << tcu::TestLog::EndMessage; 16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // report result 16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (invalidPixels) 16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << invalidPixels << " invalid pixel(s) found." << tcu::TestLog::EndMessage; 16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("ErrorMask", "ErrorMask", errorMask) 16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage; 16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrybool verifySinglesampleNarrowLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 16712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 16722306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(scene.lineWidth == 1.0f); 16732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return verifyLineGroupPixelIndependentInterpolation(surface, scene, args, log, LINEINTERPOLATION_STRICTLY_CORRECT); 16742306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 16752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 16762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrybool verifyLineGroupInterpolationWithProjectedWeights (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 16772306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 16782306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return verifyLineGroupPixelIndependentInterpolation(surface, scene, args, log, LINEINTERPOLATION_PROJECTED); 16792306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 16802306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 16812306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrystruct SingleSampleWideLineCandidate 16822306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 16832306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry struct InterpolationPointCandidate 16842306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 16852306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::IVec2 interpolationPoint; 16862306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::IVec3 colorMin; 16872306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::IVec3 colorMax; 16882306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec3 colorMinF; 16892306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec3 colorMaxF; 16902306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec3 valueRangeMin; 16912306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec3 valueRangeMax; 16922306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry }; 16932306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 16942306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int lineNdx; 16952306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int numCandidates; 16962306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry InterpolationPointCandidate interpolationCandidates[3]; 16972306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry}; 16982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 16992306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry// return point on line at a given position on a given axis 17002306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrytcu::Vec2 getLineCoordAtAxisCoord (const tcu::Vec2& pa, const tcu::Vec2& pb, bool isXAxis, float axisCoord) 17012306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 17022306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int fixedCoordNdx = (isXAxis) ? (0) : (1); 17032306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int varyingCoordNdx = (isXAxis) ? (1) : (0); 17042306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float fixedDifference = pb[fixedCoordNdx] - pa[fixedCoordNdx]; 17062306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float varyingDifference = pb[varyingCoordNdx] - pa[varyingCoordNdx]; 17072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17082306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(fixedDifference != 0.0f); 17092306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17102306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float resultFixedCoord = axisCoord; 17112306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float resultVaryingCoord = pa[varyingCoordNdx] + (axisCoord - pa[fixedCoordNdx]) * (varyingDifference / fixedDifference); 17122306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17132306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return (isXAxis) ? (tcu::Vec2(resultFixedCoord, resultVaryingCoord)) 17142306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry : (tcu::Vec2(resultVaryingCoord, resultFixedCoord)); 17152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 17162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17172306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrybool isBlack (const tcu::RGBA& c) 17182306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 17192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return c.getRed() == 0 && c.getGreen() == 0 && c.getBlue() == 0; 17202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 17212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17222306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyrybool verifySinglesampleWideLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 17232306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry{ 17242306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(deFloatFrac(scene.lineWidth) != 0.5f); // rounding direction is not defined, disallow undefined cases 17252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(scene.lines.size() < 8); // coverage indices are stored as bitmask in a unsigned 8-bit ints 17262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry enum 17282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 17292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry FLAG_ROOT_NOT_SET = (1u << 16) 17302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry }; 17312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::RGBA invalidPixelColor = tcu::RGBA(255, 0, 0, 255); 17332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 viewportSize = tcu::IVec2(surface.getWidth(), surface.getHeight()); 17342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int errorFloodThreshold = 4; 17352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int errorCount = 0; 17362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Surface errorMask (surface.getWidth(), surface.getHeight()); 17372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int invalidPixels = 0; 17382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<tcu::Vec4> effectiveLines (scene.lines.size()); //!< packed (x0, y0, x1, y1) 17392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<bool> lineIsXMajor (scene.lines.size()); 17402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // for each line, for every distinct major direction fragment, store root pixel location (along 17422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // minor direction); 17432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<std::vector<deUint32> > rootPixelLocation (scene.lines.size()); //!< packed [16b - flags] [16b - coordinate] 17442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17452306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // log format 17462306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17472306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << "Verifying rasterization result. Native format is RGB" << args.redBits << args.greenBits << args.blueBits << tcu::TestLog::EndMessage; 17482306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (args.redBits > 8 || args.greenBits > 8 || args.blueBits > 8) 17492306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << "Warning! More than 8 bits in a color channel, this may produce false negatives." << tcu::TestLog::EndMessage; 17502306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17512306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Reference renderer produces correct fragments using the diamond-exit-rule. Make 2D int array, store line coverage as a 8-bit bitfield 17522306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // The map is used to find lines with potential coverage to a given pixel 17532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::TextureLevel referenceLineMap(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT8), surface.getWidth(), surface.getHeight()); 17542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::clear(referenceLineMap.getAccess(), tcu::IVec4(0, 0, 0, 0)); 17552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 17572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // calculate mask and effective line coordinates 17592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 17602306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<tcu::Vec4> screenspaceLines(scene.lines.size()); 17612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17622306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry genScreenSpaceLines(screenspaceLines, scene.lines, viewportSize); 17632306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry setMaskMapCoverageBitForLines(screenspaceLines, scene.lineWidth, referenceLineMap.getAccess()); 17642306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx) 17662306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 17672306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 lineScreenSpaceP0 = screenspaceLines[lineNdx].swizzle(0, 1); 17682306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 lineScreenSpaceP1 = screenspaceLines[lineNdx].swizzle(2, 3); 17692306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const bool isXMajor = isPackedSSLineXMajor(screenspaceLines[lineNdx]); 17702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineIsXMajor[lineNdx] = isXMajor; 17722306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // wide line interpolations are calculated for a line moved in minor direction 17742306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 17752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float offsetLength = (scene.lineWidth - 1.0f) / 2.0f; 17762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 offsetDirection = (isXMajor) ? (tcu::Vec2(0.0f, -1.0f)) : (tcu::Vec2(-1.0f, 0.0f)); 17772306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 offset = offsetDirection * offsetLength; 17782306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17792306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry effectiveLines[lineNdx] = tcu::Vec4(lineScreenSpaceP0.x() + offset.x(), 17802306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineScreenSpaceP0.y() + offset.y(), 17812306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineScreenSpaceP1.x() + offset.x(), 17822306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineScreenSpaceP1.y() + offset.y()); 17832306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 17842306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 17852306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 17862306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 17872306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx) 17882306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 17892306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Calculate root pixel lookup table for this line. Since the implementation's fragment 17902306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // major coordinate range might not be a subset of the correct line range (they are allowed 17912306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // to vary by one pixel), we must extend the domain to cover whole viewport along major 17922306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // dimension. 17932306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // 17942306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Expanding line strip to (effectively) infinite line might result in exit-diamnod set 17952306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // that is not a superset of the exit-diamond set of the line strip. In practice, this 17962306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // won't be an issue, since the allow-one-pixel-variation rule should tolerate this even 17972306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // if the original and extended line would resolve differently a diamond the line just 17982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // touches (precision lost in expansion changes enter/exit status). 17992306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18002306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18012306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const bool isXMajor = lineIsXMajor[lineNdx]; 18022306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int majorSize = (isXMajor) ? (surface.getWidth()) : (surface.getHeight()); 18032306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rr::LineExitDiamondGenerator diamondGenerator; 18042306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rr::LineExitDiamond diamonds[32]; 18052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int numRasterized = DE_LENGTH_OF_ARRAY(diamonds); 18062306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Expand to effectively infinite line (endpoints are just one pixel over viewport boundaries) 18082306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 expandedP0 = getLineCoordAtAxisCoord(effectiveLines[lineNdx].swizzle(0, 1), effectiveLines[lineNdx].swizzle(2, 3), isXMajor, -1.0f); 18092306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 expandedP1 = getLineCoordAtAxisCoord(effectiveLines[lineNdx].swizzle(0, 1), effectiveLines[lineNdx].swizzle(2, 3), isXMajor, (float)majorSize + 1.0f); 18102306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18112306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry diamondGenerator.init(tcu::Vec4(expandedP0.x(), expandedP0.y(), 0.0f, 1.0f), 18122306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::Vec4(expandedP1.x(), expandedP1.y(), 0.0f, 1.0f)); 18132306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18142306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rootPixelLocation[lineNdx].resize(majorSize, FLAG_ROOT_NOT_SET); 18152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry while (numRasterized == DE_LENGTH_OF_ARRAY(diamonds)) 18172306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18182306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry diamondGenerator.rasterize(diamonds, DE_LENGTH_OF_ARRAY(diamonds), numRasterized); 18192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int packetNdx = 0; packetNdx < numRasterized; ++packetNdx) 18212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18222306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 fragPos = diamonds[packetNdx].position; 18232306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int majorPos = (isXMajor) ? (fragPos.x()) : (fragPos.y()); 18242306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int rootPos = (isXMajor) ? (fragPos.y()) : (fragPos.x()); 18252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deUint32 packed = (deUint32)((deUint16)((deInt16)rootPos)); 18262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // infinite line will generate some diamonds outside the viewport 18282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (deInBounds32(majorPos, 0, majorSize)) 18292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT((rootPixelLocation[lineNdx][majorPos] & FLAG_ROOT_NOT_SET) != 0u); 18312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry rootPixelLocation[lineNdx][majorPos] = packed; 18322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 18332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 18342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 18352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Filled whole lookup table 18372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int majorPos = 0; majorPos < majorSize; ++majorPos) 18382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT((rootPixelLocation[lineNdx][majorPos] & FLAG_ROOT_NOT_SET) == 0u); 18392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 18402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 18412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Find all possible lines with coverage, check pixel color matches one of them 18432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int y = 1; y < surface.getHeight() - 1; ++y) 18452306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int x = 1; x < surface.getWidth() - 1; ++x) 18462306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18472306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::RGBA color = surface.getPixel(x, y); 18482306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec3 pixelNativeColor = convertRGB8ToNativeFormat(color, args); // Convert pixel color from rgba8 to the real pixel format. Usually rgba8 or 565 18492306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int lineCoverageSet = 0; // !< lines that may cover this fragment 18502306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry int lineSurroundingCoverage = 0xFFFF; // !< lines that will cover this fragment 18512306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry bool matchFound = false; 18522306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec3 formatLimit ((1 << args.redBits) - 1, (1 << args.greenBits) - 1, (1 << args.blueBits) - 1); 18532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry std::vector<SingleSampleWideLineCandidate> candidates; 18552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Find lines with possible coverage 18572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int dy = -1; dy < 2; ++dy) 18592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int dx = -1; dx < 2; ++dx) 18602306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int coverage = referenceLineMap.getAccess().getPixelInt(x+dx, y+dy).x(); 18622306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18632306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineCoverageSet |= coverage; 18642306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry lineSurroundingCoverage &= coverage; 18652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 18662306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18672306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // background color is possible? 18682306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (lineSurroundingCoverage == 0 && compareColors(color, tcu::RGBA::black, args.redBits, args.greenBits, args.blueBits)) 18692306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry continue; 18702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Check those lines 18722306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx) 18742306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (((lineCoverageSet >> lineNdx) & 0x01) != 0) 18762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 18772306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float wa = scene.lines[lineNdx].positions[0].w(); 18782306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const float wb = scene.lines[lineNdx].positions[1].w(); 18792306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pa = effectiveLines[lineNdx].swizzle(0, 1); 18802306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec2 pb = effectiveLines[lineNdx].swizzle(2, 3); 18812306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18822306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // \note Wide line fragments are generated by replicating the root fragment for each 18832306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // fragment column (row for y-major). Calculate interpolation at the root 18842306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // fragment. 18852306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const bool isXMajor = lineIsXMajor[lineNdx]; 18862306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int majorPosition = (isXMajor) ? (x) : (y); 18872306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const deUint32 minorInfoPacked = rootPixelLocation[lineNdx][majorPosition]; 18882306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const int minorPosition = (int)((deInt16)((deUint16)(minorInfoPacked & 0xFFFFu))); 18892306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 idealRootPos = (isXMajor) ? (tcu::IVec2(majorPosition, minorPosition)) : (tcu::IVec2(minorPosition, majorPosition)); 18902306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 minorDirection = (isXMajor) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0)); 18912306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18922306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry SingleSampleWideLineCandidate candidate; 18932306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18942306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry candidate.lineNdx = lineNdx; 18952306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry candidate.numCandidates = 0; 18962306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(candidate.interpolationCandidates) == 3); 18972306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 18982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Interpolation happens at the root fragment, which is then replicated in minor 18992306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // direction. Search for implementation's root position near accurate root. 19002306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int minorOffset = -1; minorOffset < 2; ++minorOffset) 19012306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19022306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec2 rootPosition = idealRootPos + minorOffset * minorDirection; 19032306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19042306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // A fragment can be root fragment only if it exists 19052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // \note root fragment can "exist" outside viewport 19062306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // \note no pixel format theshold since in this case allowing only black is more conservative 19072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (deInBounds32(rootPosition.x(), 0, surface.getWidth()) && 19082306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry deInBounds32(rootPosition.y(), 0, surface.getHeight()) && 19092306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry isBlack(surface.getPixel(rootPosition.x(), rootPosition.y()))) 19102306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19112306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry continue; 19122306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19132306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19142306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const LineInterpolationRange range = calcSingleSampleLineInterpolationRange(pa, wa, pb, wb, rootPosition, args.subpixelBits); 19152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec4 valueMin = de::clamp(range.min.x(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[0] + de::clamp(range.min.y(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[1]; 19172306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec4 valueMax = de::clamp(range.max.x(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[0] + de::clamp(range.max.y(), 0.0f, 1.0f) * scene.lines[lineNdx].colors[1]; 19182306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec3 colorMinF (de::clamp(valueMin.x() * formatLimit.x(), 0.0f, (float)formatLimit.x()), 19202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMin.y() * formatLimit.y(), 0.0f, (float)formatLimit.y()), 19212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMin.z() * formatLimit.z(), 0.0f, (float)formatLimit.z())); 19222306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::Vec3 colorMaxF (de::clamp(valueMax.x() * formatLimit.x(), 0.0f, (float)formatLimit.x()), 19232306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMax.y() * formatLimit.y(), 0.0f, (float)formatLimit.y()), 19242306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry de::clamp(valueMax.z() * formatLimit.z(), 0.0f, (float)formatLimit.z())); 19252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec3 colorMin ((int)deFloatFloor(colorMinF.x()), 19262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatFloor(colorMinF.y()), 19272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatFloor(colorMinF.z())); 19282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const tcu::IVec3 colorMax ((int)deFloatCeil (colorMaxF.x()), 19292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatCeil (colorMaxF.y()), 19302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry (int)deFloatCeil (colorMaxF.z())); 19312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Verify validity 19332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (pixelNativeColor.x() < colorMin.x() || 19342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry pixelNativeColor.y() < colorMin.y() || 19352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry pixelNativeColor.z() < colorMin.z() || 19362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry pixelNativeColor.x() > colorMax.x() || 19372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry pixelNativeColor.y() > colorMax.y() || 19382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry pixelNativeColor.z() > colorMax.z()) 19392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (errorCount < errorFloodThreshold) 19412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // Store candidate information for logging 19432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry SingleSampleWideLineCandidate::InterpolationPointCandidate& interpolationCandidate = candidate.interpolationCandidates[candidate.numCandidates++]; 19442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry DE_ASSERT(candidate.numCandidates <= DE_LENGTH_OF_ARRAY(candidate.interpolationCandidates)); 19452306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19462306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry interpolationCandidate.interpolationPoint = rootPosition; 19472306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry interpolationCandidate.colorMin = colorMin; 19482306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry interpolationCandidate.colorMax = colorMax; 19492306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry interpolationCandidate.colorMinF = colorMinF; 19502306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry interpolationCandidate.colorMaxF = colorMaxF; 19512306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry interpolationCandidate.valueRangeMin = valueMin.swizzle(0, 1, 2); 19522306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry interpolationCandidate.valueRangeMax = valueMax.swizzle(0, 1, 2); 19532306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19542306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19552306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry else 19562306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19572306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry matchFound = true; 19582306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry break; 19592306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19602306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19612306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19622306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (!matchFound) 19632306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19642306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // store info for logging 19652306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (errorCount < errorFloodThreshold && candidate.numCandidates > 0) 19662306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry candidates.push_back(candidate); 19672306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19682306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry else 19692306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19702306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // no need to check other lines 19712306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry break; 19722306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19732306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19742306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 19752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19762306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (matchFound) 19772306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry continue; 19782306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19792306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // invalid fragment 19802306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry ++invalidPixels; 19812306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry errorMask.setPixel(x, y, invalidPixelColor); 19822306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19832306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry ++errorCount; 19842306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19852306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // don't fill the logs with too much data 19862306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (errorCount < errorFloodThreshold) 19872306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19882306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry tcu::MessageBuilder msg(&log); 19892306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19902306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry msg << "Found an invalid pixel at (" << x << "," << y << "), " << (int)candidates.size() << " candidate reference value(s) found:\n" 19912306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\tPixel color:\t\t" << color << "\n" 19922306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\tNative color:\t\t" << pixelNativeColor << "\n"; 19932306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19942306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int lineCandidateNdx = 0; lineCandidateNdx < (int)candidates.size(); ++lineCandidateNdx) 19952306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 19962306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const SingleSampleWideLineCandidate& candidate = candidates[lineCandidateNdx]; 19972306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 19982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry msg << "\tCandidate line (line " << candidate.lineNdx << "):\n"; 19992306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20002306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry for (int interpolationCandidateNdx = 0; interpolationCandidateNdx < candidate.numCandidates; ++interpolationCandidateNdx) 20012306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 20022306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const SingleSampleWideLineCandidate::InterpolationPointCandidate& interpolationCandidate = candidate.interpolationCandidates[interpolationCandidateNdx]; 20032306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20042306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry msg << "\t\tCandidate interpolation point (index " << interpolationCandidateNdx << "):\n" 20052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\t\t\tRoot fragment position (non-replicated fragment): " << interpolationCandidate.interpolationPoint << ":\n" 20062306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\t\t\tReference native color min: " << tcu::clamp(interpolationCandidate.colorMin, tcu::IVec3(0,0,0), formatLimit) << "\n" 20072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\t\t\tReference native color max: " << tcu::clamp(interpolationCandidate.colorMax, tcu::IVec3(0,0,0), formatLimit) << "\n" 20082306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\t\t\tReference native float min: " << tcu::clamp(interpolationCandidate.colorMinF, tcu::Vec3(0.0f, 0.0f, 0.0f), formatLimit.cast<float>()) << "\n" 20092306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\t\t\tReference native float max: " << tcu::clamp(interpolationCandidate.colorMaxF, tcu::Vec3(0.0f, 0.0f, 0.0f), formatLimit.cast<float>()) << "\n" 20102306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\t\t\tFmin:\t" << tcu::clamp(interpolationCandidate.valueRangeMin, tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 1.0f)) << "\n" 20112306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << "\t\t\tFmax:\t" << tcu::clamp(interpolationCandidate.valueRangeMax, tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 1.0f)) << "\n"; 20122306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 20132306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 20142306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20152306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry msg << tcu::TestLog::EndMessage; 20162306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 20172306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 20182306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20192306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // don't just hide failures 20202306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (errorCount > errorFloodThreshold) 20212306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << "Omitted " << (errorCount-errorFloodThreshold) << " pixel error description(s)." << tcu::TestLog::EndMessage; 20222306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20232306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // report result 20242306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (invalidPixels) 20252306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 20262306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << invalidPixels << " invalid pixel(s) found." << tcu::TestLog::EndMessage; 20272306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 20282306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << tcu::TestLog::Image("Result", "Result", surface) 20292306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << tcu::TestLog::Image("ErrorMask", "ErrorMask", errorMask) 20302306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << tcu::TestLog::EndImageSet; 20312306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20322306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return false; 20332306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 20342306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry else 20352306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 20362306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage; 20372306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 20382306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << tcu::TestLog::Image("Result", "Result", surface) 20392306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry << tcu::TestLog::EndImageSet; 20402306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20412306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return true; 20422306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 20432306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry} 20442306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous 20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCoverageType calculateTriangleCoverage (const tcu::Vec4& p0, const tcu::Vec4& p1, const tcu::Vec4& p2, const tcu::IVec2& pixel, const tcu::IVec2& viewportSize, int subpixelBits, bool multisample) 20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef tcu::Vector<deInt64, 2> I64Vec2; 20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 numSubPixels = ((deUint64)1) << subpixelBits; 20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 pixelHitBoxSize = (multisample) ? (numSubPixels) : (2+2); //!< allow 4 central (2x2) for non-multisample pixels. Rounding may move edges 1 subpixel to any direction. 20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool order = isTriangleClockwise(p0, p1, p2); //!< clockwise / counter-clockwise 20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4& orderedP0 = p0; //!< vertices of a clockwise triangle 20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4& orderedP1 = (order) ? (p1) : (p2); 20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec4& orderedP2 = (order) ? (p2) : (p1); 20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 triangleNormalizedDeviceSpace[3] = 20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(orderedP0.x() / orderedP0.w(), orderedP0.y() / orderedP0.w()), 20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(orderedP1.x() / orderedP1.w(), orderedP1.y() / orderedP1.w()), 20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vec2(orderedP2.x() / orderedP2.w(), orderedP2.y() / orderedP2.w()), 20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vec2 triangleScreenSpace[3] = 20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (triangleNormalizedDeviceSpace[0] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (triangleNormalizedDeviceSpace[1] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (triangleNormalizedDeviceSpace[2] + tcu::Vec2(1.0f, 1.0f)) * 0.5f * tcu::Vec2((float)viewportSize.x(), (float)viewportSize.y()), 20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Broad bounding box - pixel check 20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float minX = de::min(de::min(triangleScreenSpace[0].x(), triangleScreenSpace[1].x()), triangleScreenSpace[2].x()); 20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float minY = de::min(de::min(triangleScreenSpace[0].y(), triangleScreenSpace[1].y()), triangleScreenSpace[2].y()); 20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float maxX = de::max(de::max(triangleScreenSpace[0].x(), triangleScreenSpace[1].x()), triangleScreenSpace[2].x()); 20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float maxY = de::max(de::max(triangleScreenSpace[0].y(), triangleScreenSpace[1].y()), triangleScreenSpace[2].y()); 20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((float)pixel.x() > maxX + 1 || 20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (float)pixel.y() > maxY + 1 || 20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (float)pixel.x() < minX - 1 || 20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (float)pixel.y() < minY - 1) 20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return COVERAGE_NONE; 20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Broad triangle - pixel area intersection 20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 pixelCenterPosition = I64Vec2(pixel.x(), pixel.y()) * I64Vec2(numSubPixels, numSubPixels) + I64Vec2(numSubPixels / 2, numSubPixels / 2); 20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 triangleSubPixelSpaceRound[3] = 20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deRoundFloatToInt32(triangleScreenSpace[0].x()*numSubPixels), deRoundFloatToInt32(triangleScreenSpace[0].y()*numSubPixels)), 20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deRoundFloatToInt32(triangleScreenSpace[1].x()*numSubPixels), deRoundFloatToInt32(triangleScreenSpace[1].y()*numSubPixels)), 20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deRoundFloatToInt32(triangleScreenSpace[2].x()*numSubPixels), deRoundFloatToInt32(triangleScreenSpace[2].y()*numSubPixels)), 20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check (using cross product) if pixel center is 20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // a) too far from any edge 20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // b) fully inside all edges 20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool insideAllEdges = true; 20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vtxNdx = 0; vtxNdx < 3; ++vtxNdx) 20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int otherVtxNdx = (vtxNdx + 1) % 3; 21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 maxPixelDistanceSquared = pixelHitBoxSize*pixelHitBoxSize; // Max distance from the pixel center from within the pixel is (sqrt(2) * boxWidth/2). Use 2x value for rounding tolerance 21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 edge = triangleSubPixelSpaceRound[otherVtxNdx] - triangleSubPixelSpaceRound[vtxNdx]; 21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 v = pixelCenterPosition - triangleSubPixelSpaceRound[vtxNdx]; 21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct = (edge.x() * v.y() - edge.y() * v.x()); 21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // distance from edge: (edge x v) / |edge| 21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // (edge x v) / |edge| > maxPixelDistance 21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // ==> (edge x v)^2 / edge^2 > maxPixelDistance^2 | edge x v > 0 21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // ==> (edge x v)^2 > maxPixelDistance^2 * edge^2 21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (crossProduct < 0 && crossProduct*crossProduct > maxPixelDistanceSquared * tcu::lengthSquared(edge)) 21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return COVERAGE_NONE; 21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (crossProduct < 0 || crossProduct*crossProduct < maxPixelDistanceSquared * tcu::lengthSquared(edge)) 21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry insideAllEdges = false; 21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (insideAllEdges) 21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return COVERAGE_FULL; 21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Accurate intersection for edge pixels 21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // In multisampling, the sample points can be anywhere in the pixel, and in single sampling only in the center. 21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 pixelCorners[4] = 21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2((pixel.x()+0) * numSubPixels, (pixel.y()+0) * numSubPixels), 21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2((pixel.x()+1) * numSubPixels, (pixel.y()+0) * numSubPixels), 21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2((pixel.x()+1) * numSubPixels, (pixel.y()+1) * numSubPixels), 21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2((pixel.x()+0) * numSubPixels, (pixel.y()+1) * numSubPixels), 21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 pixelCenterCorners[4] = 21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(pixel.x() * numSubPixels + numSubPixels/2 + 0, pixel.y() * numSubPixels + numSubPixels/2 + 0), 21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(pixel.x() * numSubPixels + numSubPixels/2 + 1, pixel.y() * numSubPixels + numSubPixels/2 + 0), 21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(pixel.x() * numSubPixels + numSubPixels/2 + 1, pixel.y() * numSubPixels + numSubPixels/2 + 1), 21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(pixel.x() * numSubPixels + numSubPixels/2 + 0, pixel.y() * numSubPixels + numSubPixels/2 + 1), 21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // both rounding directions 21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 triangleSubPixelSpaceFloor[3] = 21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deFloorFloatToInt32(triangleScreenSpace[0].x()*numSubPixels), deFloorFloatToInt32(triangleScreenSpace[0].y()*numSubPixels)), 21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deFloorFloatToInt32(triangleScreenSpace[1].x()*numSubPixels), deFloorFloatToInt32(triangleScreenSpace[1].y()*numSubPixels)), 21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deFloorFloatToInt32(triangleScreenSpace[2].x()*numSubPixels), deFloorFloatToInt32(triangleScreenSpace[2].y()*numSubPixels)), 21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 triangleSubPixelSpaceCeil[3] = 21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deCeilFloatToInt32(triangleScreenSpace[0].x()*numSubPixels), deCeilFloatToInt32(triangleScreenSpace[0].y()*numSubPixels)), 21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deCeilFloatToInt32(triangleScreenSpace[1].x()*numSubPixels), deCeilFloatToInt32(triangleScreenSpace[1].y()*numSubPixels)), 21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry I64Vec2(deCeilFloatToInt32(triangleScreenSpace[2].x()*numSubPixels), deCeilFloatToInt32(triangleScreenSpace[2].y()*numSubPixels)), 21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2* const corners = (multisample) ? (pixelCorners) : (pixelCenterCorners); 21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Test if any edge (with any rounding) intersects the pixel (boundary). If it does => Partial. If not => fully inside or outside 21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int edgeNdx = 0; edgeNdx < 3; ++edgeNdx) 21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int startRounding = 0; startRounding < 4; ++startRounding) 21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int endRounding = 0; endRounding < 4; ++endRounding) 21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int nextEdgeNdx = (edgeNdx+1) % 3; 21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 startPos ((startRounding&0x01) ? (triangleSubPixelSpaceFloor[edgeNdx].x()) : (triangleSubPixelSpaceCeil[edgeNdx].x()), (startRounding&0x02) ? (triangleSubPixelSpaceFloor[edgeNdx].y()) : (triangleSubPixelSpaceCeil[edgeNdx].y())); 21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 endPos ((endRounding&0x01) ? (triangleSubPixelSpaceFloor[nextEdgeNdx].x()) : (triangleSubPixelSpaceCeil[nextEdgeNdx].x()), (endRounding&0x02) ? (triangleSubPixelSpaceFloor[nextEdgeNdx].y()) : (triangleSubPixelSpaceCeil[nextEdgeNdx].y())); 21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int pixelEdgeNdx = 0; pixelEdgeNdx < 4; ++pixelEdgeNdx) 21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int pixelEdgeEnd = (pixelEdgeNdx + 1) % 4; 21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (lineLineIntersect(startPos, endPos, corners[pixelEdgeNdx], corners[pixelEdgeEnd])) 21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return COVERAGE_PARTIAL; 21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // fully inside or outside 21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int edgeNdx = 0; edgeNdx < 3; ++edgeNdx) 21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int nextEdgeNdx = (edgeNdx+1) % 3; 21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2& startPos = triangleSubPixelSpaceFloor[edgeNdx]; 21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2& endPos = triangleSubPixelSpaceFloor[nextEdgeNdx]; 21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 edge = endPos - startPos; 21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const I64Vec2 v = corners[0] - endPos; 21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deInt64 crossProduct = (edge.x() * v.y() - edge.y() * v.x()); 21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // a corner of the pixel is outside => "fully inside" option is impossible 21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (crossProduct < 0) 21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return COVERAGE_NONE; 21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return COVERAGE_FULL; 21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTriangleGroupRasterization (const tcu::Surface& surface, const TriangleSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log, VerificationMode mode) 21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 21933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(mode < VERIFICATIONMODE_LAST); 21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA backGroundColor = tcu::RGBA(0, 0, 0, 255); 21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA triangleColor = tcu::RGBA(255, 255, 255, 255); 21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA missingPixelColor = tcu::RGBA(255, 0, 255, 255); 21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA unexpectedPixelColor = tcu::RGBA(255, 0, 0, 255); 21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA partialPixelColor = tcu::RGBA(255, 255, 0, 255); 22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA primitivePixelColor = tcu::RGBA(30, 30, 30, 255); 22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int weakVerificationThreshold = 10; 22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool multisampled = (args.numSamples != 0); 22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec2 viewportSize = tcu::IVec2(surface.getWidth(), surface.getHeight()); 22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int missingPixels = 0; 22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int unexpectedPixels = 0; 22063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int subPixelBits = args.subpixelBits; 22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TextureLevel coverageMap (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT8), surface.getWidth(), surface.getHeight()); 22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Surface errorMask (surface.getWidth(), surface.getHeight()); 22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // subpixel bits in in a valid range? 22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (subPixelBits < 0) 22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Invalid subpixel count (" << subPixelBits << "), assuming 0" << tcu::TestLog::EndMessage; 22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry subPixelBits = 0; 22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (subPixelBits > 16) 22183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // At high subpixel bit counts we might overflow. Checking at lower bit count is ok, but is less strict 22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Subpixel count is greater than 16 (" << subPixelBits << "). Checking results using less strict 16 bit requirements. This may produce false positives." << tcu::TestLog::EndMessage; 22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry subPixelBits = 16; 22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // generate coverage map 22253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::clear(coverageMap.getAccess(), tcu::IVec4(COVERAGE_NONE, 0, 0, 0)); 22273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int triNdx = 0; triNdx < (int)scene.triangles.size(); ++triNdx) 22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::IVec4 aabb = getTriangleAABB(scene.triangles[triNdx], viewportSize); 22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = de::max(0, aabb.y()); y <= de::min(aabb.w(), coverageMap.getHeight() - 1); ++y) 22333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = de::max(0, aabb.x()); x <= de::min(aabb.z(), coverageMap.getWidth() - 1); ++x) 22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coverageMap.getAccess().getPixelUint(x, y).x() == COVERAGE_FULL) 22363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const CoverageType coverage = calculateTriangleCoverage(scene.triangles[triNdx].positions[0], 22393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry scene.triangles[triNdx].positions[1], 22403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry scene.triangles[triNdx].positions[2], 22413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::IVec2(x, y), 22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry viewportSize, 22433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry subPixelBits, 22443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry multisampled); 22453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (coverage == COVERAGE_FULL) 22473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry coverageMap.getAccess().setPixel(tcu::IVec4(COVERAGE_FULL, 0, 0, 0), x, y); 22493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (coverage == COVERAGE_PARTIAL) 22513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CoverageType resultCoverage = COVERAGE_PARTIAL; 22533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Sharing an edge with another triangle? 22553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // There should always be such a triangle, but the pixel in the other triangle might be 22563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // on multiple edges, some of which are not shared. In these cases the coverage cannot be determined. 22573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Assume full coverage if the pixel is only on a shared edge in shared triangle too. 22583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (pixelOnlyOnASharedEdge(tcu::IVec2(x, y), scene.triangles[triNdx], viewportSize)) 22593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool friendFound = false; 22613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int friendTriNdx = 0; friendTriNdx < (int)scene.triangles.size(); ++friendTriNdx) 22623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (friendTriNdx != triNdx && pixelOnlyOnASharedEdge(tcu::IVec2(x, y), scene.triangles[friendTriNdx], viewportSize)) 22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry friendFound = true; 22663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 22673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (friendFound) 22713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry resultCoverage = COVERAGE_FULL; 22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry coverageMap.getAccess().setPixel(tcu::IVec4(resultCoverage, 0, 0, 0), x, y); 22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // check pixels 22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int y = 0; y < surface.getHeight(); ++y) 22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int x = 0; x < surface.getWidth(); ++x) 22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::RGBA color = surface.getPixel(x, y); 22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool imageNoCoverage = compareColors(color, backGroundColor, args.redBits, args.greenBits, args.blueBits); 22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool imageFullCoverage = compareColors(color, triangleColor, args.redBits, args.greenBits, args.blueBits); 22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CoverageType referenceCoverage = (CoverageType)coverageMap.getAccess().getPixelUint(x, y).x(); 22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (referenceCoverage) 22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case COVERAGE_NONE: 22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!imageNoCoverage) 22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // coverage where there should not be 22973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++unexpectedPixels; 22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, unexpectedPixelColor); 22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case COVERAGE_PARTIAL: 23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // anything goes 23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, partialPixelColor); 23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case COVERAGE_FULL: 23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!imageFullCoverage) 23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // no coverage where there should be 23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ++missingPixels; 23123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, missingPixelColor); 23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry errorMask.setPixel(x, y, primitivePixelColor); 23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Output results 23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Verifying rasterization result." << tcu::TestLog::EndMessage; 23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (((mode == VERIFICATIONMODE_STRICT) && (missingPixels + unexpectedPixels > 0)) || 23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((mode == VERIFICATIONMODE_WEAK) && (missingPixels + unexpectedPixels > weakVerificationThreshold))) 23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "Invalid pixels found:\n\t" 23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << missingPixels << " missing pixels. (Marked with purple)\n\t" 23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << unexpectedPixels << " incorrectly filled pixels. (Marked with red)\n\t" 23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "Unknown (subpixel on edge) pixels are marked with yellow." 23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndMessage; 23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("ErrorMask", "ErrorMask", errorMask) 23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage; 23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry log << tcu::TestLog::ImageSet("Verification result", "Result of rendering") 23473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::Image("Result", "Result", surface) 23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::TestLog::EndImageSet; 23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyLineGroupRasterization (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool multisampled = args.numSamples != 0; 23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (multisampled) 23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyMultisampleLineGroupRasterization(surface, scene, args, log); 23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifySinglesampleLineGroupRasterization(surface, scene, args, log); 23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyPointGroupRasterization (const tcu::Surface& surface, const PointSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Splitting to triangles is a valid solution in multisampled cases and even in non-multisample cases too. 23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyMultisamplePointGroupRasterization(surface, scene, args, log); 23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTriangleGroupInterpolation (const tcu::Surface& surface, const TriangleSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return verifyTriangleGroupInterpolationWithInterpolator(surface, scene, args, log, TriangleInterpolator(scene)); 23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23752306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko PöyryLineInterpolationMethod verifyLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log) 23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool multisampled = args.numSamples != 0; 23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (multisampled) 23802306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 23812306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (verifyMultisampleLineGroupInterpolation(surface, scene, args, log)) 23822306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return LINEINTERPOLATION_STRICTLY_CORRECT; 23832306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return LINEINTERPOLATION_INCORRECT; 23842306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 23862306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 23872306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry const bool isNarrow = (scene.lineWidth == 1.0f); 23882306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 23892306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // accurate interpolation 23902306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (isNarrow) 23912306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 23922306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (verifySinglesampleNarrowLineGroupInterpolation(surface, scene, args, log)) 23932306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return LINEINTERPOLATION_STRICTLY_CORRECT; 23942306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 23952306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry else 23962306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry { 23972306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (verifySinglesampleWideLineGroupInterpolation(surface, scene, args, log)) 23982306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return LINEINTERPOLATION_STRICTLY_CORRECT; 23992306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 24002306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 24012306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry // check with projected (inaccurate) interpolation 24022306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry log << tcu::TestLog::Message << "Accurate verification failed, checking with projected weights (inaccurate equation)." << tcu::TestLog::EndMessage; 24032306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry if (verifyLineGroupInterpolationWithProjectedWeights(surface, scene, args, log)) 24042306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return LINEINTERPOLATION_PROJECTED; 24052306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry 24062306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry return LINEINTERPOLATION_INCORRECT; 24072306a3bf8214ab2c51d8023ca1ccd979fb8d31bbJarkko Pöyry } 24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // StateQueryUtil 24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gls 24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp 2413