ReadPixelsTest::ReadPixelsTest (Context& context, const char* name, const char* description, bool chooseFormat, int alignment) : TestCase (context, name, description) , m_chooseFormat (chooseFormat) , m_alignment (alignment) , m_seed (deStringHash(name)) { }
MakeCurrentPerfCase::MakeCurrentPerfCase (EglTestContext& eglTestCtx, const Spec& spec, const char* name, const char* description) : TestCase (eglTestCtx, tcu::NODETYPE_PERFORMANCE, name, description) , m_spec (spec) , m_rnd (deStringHash(name)) , m_config (DE_NULL) { }
IterateResult iterate (void) { de::Random rnd (deStringHash(getName()) ^ 0x776002); std::vector<tcu::Vec2> inputs; std::vector<deUint32> outputs; const int maxDiff = m_precision == glu::PRECISION_HIGHP ? 1 : // Rounding only. m_precision == glu::PRECISION_MEDIUMP ? 33 : // (2^-10) * (2^15) + 1 m_precision == glu::PRECISION_LOWP ? 129 : 0; // (2^-8) * (2^15) + 1 // Special values to check. inputs.push_back(tcu::Vec2(0.0f, 0.0f)); inputs.push_back(tcu::Vec2(-1.0f, 1.0f)); inputs.push_back(tcu::Vec2(0.5f, -0.5f)); inputs.push_back(tcu::Vec2(-1.5f, 1.5f)); inputs.push_back(tcu::Vec2(0.25f, -0.75f)); // Random values, mostly in range. for (int ndx = 0; ndx < 15; ndx++) { const float x = rnd.getFloat()*2.5f - 1.25f; const float y = rnd.getFloat()*2.5f - 1.25f; inputs.push_back(tcu::Vec2(x, y)); } // Large random values. for (int ndx = 0; ndx < 80; ndx++) { const float x = rnd.getFloat()*1e6f - 0.5e6f; const float y = rnd.getFloat()*1e6f - 0.5e6f; inputs.push_back(tcu::Vec2(x, y)); } outputs.resize(inputs.size()); m_testCtx.getLog() << TestLog::Message << "Executing shader for " << inputs.size() << " input values" << tcu::TestLog::EndMessage; { const void* in = &inputs[0]; void* out = &outputs[0]; m_executor->useProgram(); m_executor->execute((int)inputs.size(), &in, &out); } // Verify { const int numValues = (int)inputs.size(); const int maxPrints = 10; int numFailed = 0; for (int valNdx = 0; valNdx < numValues; valNdx++) { const deUint16 ref0 = (deUint16)de::clamp(deRoundFloatToInt32(de::clamp(inputs[valNdx].x(), -1.0f, 1.0f) * 32767.0f), -(1<<15), (1<<15)-1); const deUint16 ref1 = (deUint16)de::clamp(deRoundFloatToInt32(de::clamp(inputs[valNdx].y(), -1.0f, 1.0f) * 32767.0f), -(1<<15), (1<<15)-1); const deUint32 ref = (ref1 << 16) | ref0; const deUint32 res = outputs[valNdx]; const deUint16 res0 = (deUint16)(res & 0xffff); const deUint16 res1 = (deUint16)(res >> 16); const int diff0 = de::abs((int)ref0 - (int)res0); const int diff1 = de::abs((int)ref1 - (int)res1); if (diff0 > maxDiff || diff1 > maxDiff) { if (numFailed < maxPrints) { m_testCtx.getLog() << TestLog::Message << "ERROR: Mismatch in value " << valNdx << ", expected packSnorm2x16(" << inputs[valNdx] << ") = " << tcu::toHex(ref) << ", got " << tcu::toHex(res) << "\n diffs = (" << diff0 << ", " << diff1 << "), max diff = " << maxDiff << TestLog::EndMessage; } else if (numFailed == maxPrints) m_testCtx.getLog() << TestLog::Message << "..." << TestLog::EndMessage; numFailed += 1; } } m_testCtx.getLog() << TestLog::Message << (numValues - numFailed) << " / " << numValues << " values passed" << TestLog::EndMessage; m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, numFailed == 0 ? "Pass" : "Result comparison failed"); } return STOP; }
bool DitheringCase::drawAndCheckUnicoloredQuad (const Vec4& quadColor) const { TestLog& log = m_testCtx.getLog(); Random rnd (deStringHash(getName())); const int maxViewportWid = 32; const int maxViewportHei = 32; const int viewportWid = de::min(m_renderCtx.getRenderTarget().getWidth(), maxViewportWid); const int viewportHei = de::min(m_renderCtx.getRenderTarget().getHeight(), maxViewportHei); const int viewportX = rnd.getInt(0, m_renderCtx.getRenderTarget().getWidth() - viewportWid); const int viewportY = rnd.getInt(0, m_renderCtx.getRenderTarget().getHeight() - viewportHei); Quad quad; Surface renderedImg (viewportWid, viewportHei); GLU_CHECK_CALL(glViewport(viewportX, viewportY, viewportWid, viewportHei)); log << TestLog::Message << "Dithering is " << (m_ditheringEnabled ? "enabled" : "disabled") << TestLog::EndMessage; if (m_ditheringEnabled) GLU_CHECK_CALL(glEnable(GL_DITHER)); else GLU_CHECK_CALL(glDisable(GL_DITHER)); log << TestLog::Message << "Drawing an unicolored quad with color " << quadColor << TestLog::EndMessage; quad.color[0] = quadColor; quad.color[1] = quadColor; quad.color[2] = quadColor; quad.color[3] = quadColor; m_renderer->render(quad); glu::readPixels(m_renderCtx, viewportX, viewportY, renderedImg.getAccess()); GLU_CHECK_MSG("glReadPixels()"); log << TestLog::Image(("Quad" + de::toString(m_iteration)).c_str(), ("Quad " + de::toString(m_iteration)).c_str(), renderedImg); // Validate, at each pixel, that each color channel is one of its two allowed values. { Surface errorMask (viewportWid, viewportHei); bool colorChoicesOk = true; for (int y = 0; y < renderedImg.getHeight(); y++) { for (int x = 0; x < renderedImg.getWidth(); x++) { if (!checkColor(quadColor, renderedImg.getPixel(x, y), colorChoicesOk)) { errorMask.setPixel(x, y, tcu::RGBA::red); if (colorChoicesOk) { log << TestLog::Message << "First failure at pixel (" << x << ", " << y << ") (not printing further errors)" << TestLog::EndMessage; colorChoicesOk = false; } } else errorMask.setPixel(x, y, tcu::RGBA::green); } } if (!colorChoicesOk) { log << TestLog::Image("ColorChoiceErrorMask", "Error mask for color choices", errorMask); return false; } } // When dithering is disabled, the color selection must be coordinate-independent - i.e. the entire rendered image must be unicolored. if (!m_ditheringEnabled) { const tcu::RGBA renderedClr00 = renderedImg.getPixel(0, 0); for (int y = 0; y < renderedImg.getHeight(); y++) { for (int x = 0; x < renderedImg.getWidth(); x++) { const tcu::RGBA curClr = renderedImg.getPixel(x, y); if (curClr != renderedClr00) { log << TestLog::Message << "Failure: color at (" << x << ", " << y << ") is " << curClr << " and does not equal the color at (0, 0), which is " << renderedClr00 << TestLog::EndMessage; return false; } } } } return true; }
bool DitheringCase::drawAndCheckGradient (const bool isVerticallyIncreasing, const Vec4& highColor) const { TestLog& log = m_testCtx.getLog(); Random rnd (deStringHash(getName())); const int maxViewportWid = 256; const int maxViewportHei = 256; const int viewportWid = de::min(m_renderCtx.getRenderTarget().getWidth(), maxViewportWid); const int viewportHei = de::min(m_renderCtx.getRenderTarget().getHeight(), maxViewportHei); const int viewportX = rnd.getInt(0, m_renderCtx.getRenderTarget().getWidth() - viewportWid); const int viewportY = rnd.getInt(0, m_renderCtx.getRenderTarget().getHeight() - viewportHei); const Vec4 quadClr0 (0.0f, 0.0f, 0.0f, 0.0f); const Vec4& quadClr1 = highColor; Quad quad; Surface renderedImg (viewportWid, viewportHei); GLU_CHECK_CALL(glViewport(viewportX, viewportY, viewportWid, viewportHei)); log << TestLog::Message << "Dithering is " << (m_ditheringEnabled ? "enabled" : "disabled") << TestLog::EndMessage; if (m_ditheringEnabled) GLU_CHECK_CALL(glEnable(GL_DITHER)); else GLU_CHECK_CALL(glDisable(GL_DITHER)); log << TestLog::Message << "Drawing a " << (isVerticallyIncreasing ? "vertically" : "horizontally") << " increasing gradient" << TestLog::EndMessage; quad.color[0] = quadClr0; quad.color[1] = isVerticallyIncreasing ? quadClr1 : quadClr0; quad.color[2] = isVerticallyIncreasing ? quadClr0 : quadClr1; quad.color[3] = quadClr1; m_renderer->render(quad); glu::readPixels(m_renderCtx, viewportX, viewportY, renderedImg.getAccess()); GLU_CHECK_MSG("glReadPixels()"); log << TestLog::Image(isVerticallyIncreasing ? "VerGradient" : "HorGradient", isVerticallyIncreasing ? "Vertical gradient" : "Horizontal gradient", renderedImg); // Validate, at each pixel, that each color channel is one of its two allowed values. { Surface errorMask (viewportWid, viewportHei); bool colorChoicesOk = true; for (int y = 0; y < renderedImg.getHeight(); y++) { for (int x = 0; x < renderedImg.getWidth(); x++) { const float inputF = ((float)(isVerticallyIncreasing ? y : x) + 0.5f) / (float)(isVerticallyIncreasing ? renderedImg.getHeight() : renderedImg.getWidth()); const Vec4 inputClr = (1.0f-inputF)*quadClr0 + inputF*quadClr1; if (!checkColor(inputClr, renderedImg.getPixel(x, y), colorChoicesOk)) { errorMask.setPixel(x, y, tcu::RGBA::red); if (colorChoicesOk) { log << TestLog::Message << "First failure at pixel (" << x << ", " << y << ") (not printing further errors)" << TestLog::EndMessage; colorChoicesOk = false; } } else errorMask.setPixel(x, y, tcu::RGBA::green); } } if (!colorChoicesOk) { log << TestLog::Image("ColorChoiceErrorMask", "Error mask for color choices", errorMask); return false; } } // When dithering is disabled, the color selection must be coordinate-independent - i.e. the colors must be constant in the gradient's constant direction. if (!m_ditheringEnabled) { const int increasingDirectionSize = isVerticallyIncreasing ? renderedImg.getHeight() : renderedImg.getWidth(); const int constantDirectionSize = isVerticallyIncreasing ? renderedImg.getWidth() : renderedImg.getHeight(); for (int incrPos = 0; incrPos < increasingDirectionSize; incrPos++) { tcu::RGBA prevConstantDirectionPix; for (int constPos = 0; constPos < constantDirectionSize; constPos++) { const int x = isVerticallyIncreasing ? constPos : incrPos; const int y = isVerticallyIncreasing ? incrPos : constPos; const tcu::RGBA clr = renderedImg.getPixel(x, y); if (constPos > 0 && clr != prevConstantDirectionPix) { log << TestLog::Message << "Failure: colors should be constant per " << (isVerticallyIncreasing ? "row" : "column") << " (since dithering is disabled), but the color at position (" << x << ", " << y << ") is " << clr << " and does not equal the color at (" << (isVerticallyIncreasing ? x-1 : x) << ", " << (isVerticallyIncreasing ? y : y-1) << "), which is " << prevConstantDirectionPix << TestLog::EndMessage; return false; } prevConstantDirectionPix = clr; } } } return true; }
GLW_APICALL GLint GLW_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name) { DE_UNREF(program); return (GLint)(deStringHash(name) & 0x7FFFFFFF); }