const float halfLineWidth = scene.lineWidth * 0.5f;
TriangleSceneSpec triangleScene;
+ deUint32 stippleCounter = 0;
+ float leftoverPhase = 0.0f;
+
triangleScene.triangles.resize(2 * scene.lines.size());
for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx)
{
+
+ if (!scene.isStrip)
+ {
+ // reset stipple at the start of each line segment
+ stippleCounter = 0;
+ leftoverPhase = 0;
+ }
+
// Transform to screen space, add pixel offsets, convert back to normalized device space, and test as triangles
tcu::Vec2 lineNormalizedDeviceSpace[2] =
{
const tcu::Vec2 lineDir = tcu::normalize(lineScreenSpace[1] - lineScreenSpace[0]);
const tcu::Vec2 lineNormalDir = tcu::Vec2(lineDir.y(), -lineDir.x());
- const tcu::Vec2 lineQuadScreenSpace[4] =
+ if (scene.stippleEnable)
{
- lineScreenSpace[0] + lineNormalDir * halfLineWidth,
- lineScreenSpace[0] - lineNormalDir * halfLineWidth,
- lineScreenSpace[1] - lineNormalDir * halfLineWidth,
- lineScreenSpace[1] + lineNormalDir * halfLineWidth,
- };
- const tcu::Vec2 lineQuadNormalizedDeviceSpace[4] =
- {
- lineQuadScreenSpace[0] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
- lineQuadScreenSpace[1] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
- lineQuadScreenSpace[2] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
- lineQuadScreenSpace[3] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
- };
+ float lineLength = tcu::distance(lineScreenSpace[0], lineScreenSpace[1]);
+ float lineOffset = 0.0f;
- 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;
- 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;
- 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;
+ while (lineOffset < lineLength)
+ {
+ float d0 = (float)lineOffset;
+ float d1 = d0 + 1.0f;
- 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;
- 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;
- 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;
+ // "leftoverPhase" carries over a fractional stipple phase that was "unused"
+ // by the last line segment in the strip, if it wasn't an integer length.
+ if (leftoverPhase > lineLength)
+ {
+ DE_ASSERT(d0 == 0.0f);
+ d1 = lineLength;
+ leftoverPhase -= lineLength;
+ }
+ else if (leftoverPhase != 0.0f)
+ {
+ DE_ASSERT(d0 == 0.0f);
+ d1 = leftoverPhase;
+ leftoverPhase = 0.0f;
+ }
+ else
+ {
+ if (d0 + 1.0f > lineLength)
+ {
+ d1 = lineLength;
+ leftoverPhase = d0 + 1.0f - lineLength;
+ }
+ else
+ d1 = d0 + 1.0f;
+ }
+
+ // set offset for next iteration
+ lineOffset = d1;
+
+ int stippleBit = (stippleCounter / scene.stippleFactor) % 16;
+ bool stipplePass = (scene.stipplePattern & (1 << stippleBit)) != 0;
+
+ if (leftoverPhase == 0)
+ stippleCounter++;
+
+ if (!stipplePass)
+ continue;
+
+ d0 /= lineLength;
+ d1 /= lineLength;
+
+ tcu::Vec2 l0 = mix(lineScreenSpace[0], lineScreenSpace[1], d0);
+ tcu::Vec2 l1 = mix(lineScreenSpace[0], lineScreenSpace[1], d1);
+
+ const tcu::Vec2 lineQuadScreenSpace[4] =
+ {
+ l0 + lineNormalDir * halfLineWidth,
+ l0 - lineNormalDir * halfLineWidth,
+ l1 - lineNormalDir * halfLineWidth,
+ l1 + lineNormalDir * halfLineWidth,
+ };
+ const tcu::Vec2 lineQuadNormalizedDeviceSpace[4] =
+ {
+ lineQuadScreenSpace[0] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ lineQuadScreenSpace[1] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ lineQuadScreenSpace[2] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ lineQuadScreenSpace[3] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ };
+
+ TriangleSceneSpec::SceneTriangle tri;
+
+ tri.positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); tri.sharedEdge[0] = (d0 != 0.0f);
+ tri.positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[1].x(), lineQuadNormalizedDeviceSpace[1].y(), 0.0f, 1.0f); tri.sharedEdge[1] = false;
+ tri.positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); tri.sharedEdge[2] = true;
+
+ triangleScene.triangles.push_back(tri);
+
+ tri.positions[0] = tcu::Vec4(lineQuadNormalizedDeviceSpace[0].x(), lineQuadNormalizedDeviceSpace[0].y(), 0.0f, 1.0f); tri.sharedEdge[0] = true;
+ tri.positions[1] = tcu::Vec4(lineQuadNormalizedDeviceSpace[2].x(), lineQuadNormalizedDeviceSpace[2].y(), 0.0f, 1.0f); tri.sharedEdge[1] = (d1 != 1.0f);
+ tri.positions[2] = tcu::Vec4(lineQuadNormalizedDeviceSpace[3].x(), lineQuadNormalizedDeviceSpace[3].y(), 0.0f, 1.0f); tri.sharedEdge[2] = false;
+
+ triangleScene.triangles.push_back(tri);
+ }
+ }
+ else
+ {
+ const tcu::Vec2 lineQuadScreenSpace[4] =
+ {
+ lineScreenSpace[0] + lineNormalDir * halfLineWidth,
+ lineScreenSpace[0] - lineNormalDir * halfLineWidth,
+ lineScreenSpace[1] - lineNormalDir * halfLineWidth,
+ lineScreenSpace[1] + lineNormalDir * halfLineWidth,
+ };
+ const tcu::Vec2 lineQuadNormalizedDeviceSpace[4] =
+ {
+ lineQuadScreenSpace[0] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ lineQuadScreenSpace[1] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ lineQuadScreenSpace[2] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ lineQuadScreenSpace[3] / viewportSize * 2.0f - tcu::Vec2(1.0f, 1.0f),
+ };
+
+ 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;
+ 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;
+ 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;
+
+ 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;
+ 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;
+ 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;
+ }
}
- return verifyTriangleGroupRasterization(surface, triangleScene, args, log, VERIFICATIONMODE_STRICT, logStash);
+ return verifyTriangleGroupRasterization(surface, triangleScene, args, log, scene.verificationMode, logStash);
}
bool verifyMultisampleLineGroupInterpolation (const tcu::Surface& surface, const LineSceneSpec& scene, const RasterizationArguments& args, tcu::TestLog& log)
int referenceFragments = 0;
int resultFragments = 0;
int lineWidth = deFloorFloatToInt32(scene.lineWidth + 0.5f);
- bool imageShown = false;
std::vector<bool> lineIsXMajor (scene.lines.size());
std::vector<tcu::Vec4> screenspaceLines(scene.lines.size());
genScreenSpaceLines(screenspaceLines, scene.lines, tcu::IVec2(surface.getWidth(), surface.getHeight()));
+ rr::SingleSampleLineRasterizer rasterizer(tcu::IVec4(0, 0, surface.getWidth(), surface.getHeight()), args.subpixelBits);
for (int lineNdx = 0; lineNdx < (int)scene.lines.size(); ++lineNdx)
{
- rr::SingleSampleLineRasterizer rasterizer(tcu::IVec4(0, 0, surface.getWidth(), surface.getHeight()), args.subpixelBits);
rasterizer.init(tcu::Vec4(screenspaceLines[lineNdx][0],
screenspaceLines[lineNdx][1],
0.0f,
screenspaceLines[lineNdx][3],
0.0f,
1.0f),
- scene.lineWidth);
+ scene.lineWidth,
+ scene.stippleFactor,
+ scene.stipplePattern);
+
+ if (!scene.isStrip)
+ rasterizer.resetStipple();
// calculate majority of later use
lineIsXMajor[lineNdx] = isPackedSSLineXMajor(screenspaceLines[lineNdx]);
if (missingFragments)
{
- log << tcu::TestLog::Message << "Invalid deviation(s) found." << tcu::TestLog::EndMessage;
- log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
- << tcu::TestLog::Image("Result", "Result", surface)
- << tcu::TestLog::Image("ErrorMask", "ErrorMask", errorMask)
- << tcu::TestLog::EndImageSet;
-
- imageShown = true;
allOK = false;
}
else
<< tcu::TestLog::EndImageSet;
allOK = false;
- imageShown = true;
}
else
{
{
if (lineID && lineID != nearbyID)
multipleNearbyLines = true;
- lineID = nearbyID;
}
}
//duplicate fragments, nor may any fragments be omitted so as to interrupt
//continuity of the connected segments.
- if (!imageShown)
{
+ tcu::Surface reference(surface.getWidth(), surface.getHeight());
+
+ // show a helpful reference image
+ tcu::clear(reference.getAccess(), tcu::IVec4(0, 0, 0, 255));
+ for (int y = 0; y < surface.getHeight(); ++y)
+ for (int x = 0; x < surface.getWidth(); ++x)
+ if (referenceLineMap.getAccess().getPixelInt(x, y).x())
+ reference.setPixel(x, y, tcu::RGBA::white());
+
+ log << tcu::TestLog::Message << "Invalid fragment count in result image." << tcu::TestLog::EndMessage;
log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
- << tcu::TestLog::Image("Result", "Result", surface)
+ << tcu::TestLog::Image("Reference", "Reference", reference)
+ << tcu::TestLog::Image("Result", "Result", surface)
<< tcu::TestLog::EndImageSet;
}
rasterizer.init(tcu::Vec4(screenSpaceP0.x(), screenSpaceP0.y(), 0.0f, 1.0f),
tcu::Vec4(screenSpaceP1.x(), screenSpaceP1.y(), 0.0f, 1.0f),
- lineWidth);
+ lineWidth,
+ 1, 0xFFFF);
while (numRasterized == MAX_PACKETS)
{
const tcu::RGBA partialPixelColor = tcu::RGBA(255, 255, 0, 255);
const tcu::RGBA primitivePixelColor = tcu::RGBA(30, 30, 30, 255);
const int weakVerificationThreshold = 10;
+ const int weakerVerificationThreshold = 25;
const bool multisampled = (args.numSamples != 0);
const tcu::IVec2 viewportSize = tcu::IVec2(surface.getWidth(), surface.getHeight());
int missingPixels = 0;
}
if (((mode == VERIFICATIONMODE_STRICT) && (missingPixels + unexpectedPixels > 0)) ||
- ((mode == VERIFICATIONMODE_WEAK) && (missingPixels + unexpectedPixels > weakVerificationThreshold)))
+ ((mode == VERIFICATIONMODE_WEAK) && (missingPixels + unexpectedPixels > weakVerificationThreshold)) ||
+ ((mode == VERIFICATIONMODE_WEAKER) && (missingPixels + unexpectedPixels > weakerVerificationThreshold)) ||
+ ((mode == VERIFICATIONMODE_SMOOTH) && (missingPixels > weakVerificationThreshold)))
{
result = false;
}