Commit 5b35c7f6 by Jamie Madill Committed by Commit Bot

Fix up screenshot saving for trace tests.

Now works when run in a sequence. Also saves RGB images to avoid issues with the alpha being inconsistent and also flips images vertically to fix the rendering. Bug: angleproject:4615 Change-Id: I8d3b38c5d914e0ca2227320ac42a0e28acd12c4d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2187971 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 234ea5b1
...@@ -238,10 +238,7 @@ template("angle_perftests_common") { ...@@ -238,10 +238,7 @@ template("angle_perftests_common") {
"perf_tests/third_party/perf/perf_test.cc", "perf_tests/third_party/perf/perf_test.cc",
"perf_tests/third_party/perf/perf_test.h", "perf_tests/third_party/perf/perf_test.h",
] ]
deps = [ deps = [ "$angle_jsoncpp_dir:jsoncpp" ]
"$angle_jsoncpp_dir:jsoncpp",
"$angle_root/util:angle_png_utils",
]
public_deps = [ "${invoker.test_utils}" ] public_deps = [ "${invoker.test_utils}" ]
public_configs += [ "${angle_root}:libANGLE_config" ] public_configs += [ "${angle_root}:libANGLE_config" ]
} }
...@@ -328,6 +325,7 @@ if (is_win || is_linux || is_android || is_mac || is_fuchsia) { ...@@ -328,6 +325,7 @@ if (is_win || is_linux || is_android || is_mac || is_fuchsia) {
deps = [ deps = [
":angle_perftests_shared", ":angle_perftests_shared",
"$angle_root:angle_compression", "$angle_root:angle_compression",
"$angle_root/util:angle_png_utils",
] ]
suppressed_configs += suppressed_configs +=
[ "$angle_root:constructor_and_destructor_warnings" ] [ "$angle_root:constructor_and_destructor_warnings" ]
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "common/utilities.h" #include "common/utilities.h"
#include "third_party/perf/perf_test.h" #include "third_party/perf/perf_test.h"
#include "third_party/trace_event/trace_event.h" #include "third_party/trace_event/trace_event.h"
#include "util/png_utils.h"
#include "util/shader_utils.h" #include "util/shader_utils.h"
#include "util/test_utils.h" #include "util/test_utils.h"
...@@ -565,6 +564,16 @@ void ANGLERenderTest::SetUp() ...@@ -565,6 +564,16 @@ void ANGLERenderTest::SetUp()
FAIL() << "Please initialize 'iterationsPerStep'."; FAIL() << "Please initialize 'iterationsPerStep'.";
// FAIL returns. // FAIL returns.
} }
// Capture a screenshot if enabled.
if (gScreenShotDir != nullptr)
{
std::stringstream screenshotNameStr;
screenshotNameStr << gScreenShotDir << GetPathSeparator() << "angle" << mBackend << "_"
<< mStory << ".png";
std::string screenshotName = screenshotNameStr.str();
saveScreenshot(screenshotName);
}
} }
void ANGLERenderTest::TearDown() void ANGLERenderTest::TearDown()
...@@ -655,9 +664,6 @@ void ANGLERenderTest::step() ...@@ -655,9 +664,6 @@ void ANGLERenderTest::step()
{ {
drawBenchmark(); drawBenchmark();
// Saves a screenshot. The test will also exit early if we're taking screenshots.
saveScreenshotIfEnabled();
// Swap is needed so that the GPU driver will occasionally flush its // Swap is needed so that the GPU driver will occasionally flush its
// internal command queue to the GPU. This is enabled for null back-end // internal command queue to the GPU. This is enabled for null back-end
// devices because some back-ends (e.g. Vulkan) also accumulate internal // devices because some back-ends (e.g. Vulkan) also accumulate internal
...@@ -758,33 +764,6 @@ std::vector<TraceEvent> &ANGLERenderTest::getTraceEventBuffer() ...@@ -758,33 +764,6 @@ std::vector<TraceEvent> &ANGLERenderTest::getTraceEventBuffer()
return mTraceEventBuffer; return mTraceEventBuffer;
} }
void ANGLERenderTest::saveScreenshotIfEnabled()
{
if (gScreenShotDir == nullptr)
{
return;
}
std::stringstream screenshotNameStr;
screenshotNameStr << gScreenShotDir << GetPathSeparator() << "angle" << mBackend << "_"
<< mStory << ".png";
std::string screenshotName = screenshotNameStr.str();
// RGBA 4-byte data.
std::vector<uint8_t> pixelData(mTestParams.windowWidth * mTestParams.windowHeight * 4);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glReadPixels(0, 0, mTestParams.windowWidth, mTestParams.windowHeight, GL_RGBA, GL_UNSIGNED_BYTE,
pixelData.data());
angle::SavePNG(screenshotName.c_str(), "ANGLE Screenshot", mTestParams.windowWidth,
mTestParams.windowHeight, pixelData);
// Early exit.
abortTest();
mSkipTest = true;
}
namespace angle namespace angle
{ {
double GetHostTimeSeconds() double GetHostTimeSeconds()
......
...@@ -85,6 +85,9 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable ...@@ -85,6 +85,9 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable
unsigned int getNumStepsPerformed() const { return mNumStepsPerformed; } unsigned int getNumStepsPerformed() const { return mNumStepsPerformed; }
void doRunLoop(double maxRunTime); void doRunLoop(double maxRunTime);
// Overriden in trace perf tests.
virtual void saveScreenshot(const std::string &screenshotName) {}
std::string mName; std::string mName;
std::string mBackend; std::string mBackend;
std::string mStory; std::string mStory;
...@@ -154,8 +157,6 @@ class ANGLERenderTest : public ANGLEPerfTest ...@@ -154,8 +157,6 @@ class ANGLERenderTest : public ANGLEPerfTest
bool mIsTimestampQueryAvailable; bool mIsTimestampQueryAvailable;
void saveScreenshotIfEnabled();
private: private:
void SetUp() override; void SetUp() override;
void TearDown() override; void TearDown() override;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "tests/perf_tests/DrawCallPerfParams.h" #include "tests/perf_tests/DrawCallPerfParams.h"
#include "util/egl_loader_autogen.h" #include "util/egl_loader_autogen.h"
#include "util/frame_capture_utils.h" #include "util/frame_capture_utils.h"
#include "util/png_utils.h"
#include "restricted_traces/restricted_traces_autogen.h" #include "restricted_traces/restricted_traces_autogen.h"
...@@ -90,6 +91,7 @@ class TracePerfTest : public ANGLERenderTest, public ::testing::WithParamInterfa ...@@ -90,6 +91,7 @@ class TracePerfTest : public ANGLERenderTest, public ::testing::WithParamInterfa
}; };
void sampleTime(); void sampleTime();
void saveScreenshot(const std::string &screenshotName) override;
// For tracking RenderPass/FBO change timing. // For tracking RenderPass/FBO change timing.
QueryInfo mCurrentQuery = {}; QueryInfo mCurrentQuery = {};
...@@ -292,6 +294,45 @@ void TracePerfTest::onFramebufferChange(GLenum target, GLuint framebuffer) ...@@ -292,6 +294,45 @@ void TracePerfTest::onFramebufferChange(GLenum target, GLuint framebuffer)
mCurrentQuery.framebuffer = framebuffer; mCurrentQuery.framebuffer = framebuffer;
} }
void TracePerfTest::saveScreenshot(const std::string &screenshotName)
{
// Render a single frame.
RestrictedTraceID testID = GetParam().testID;
const TraceInfo &traceInfo = kTraceInfos[testID];
ReplayFrame(testID, traceInfo.startFrame);
// RGBA 4-byte data.
uint32_t pixelCount = mTestParams.windowWidth * mTestParams.windowHeight;
std::vector<uint8_t> pixelData(pixelCount * 4);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glReadPixels(0, 0, mTestParams.windowWidth, mTestParams.windowHeight, GL_RGBA, GL_UNSIGNED_BYTE,
pixelData.data());
// Convert to RGB and flip y.
std::vector<uint8_t> rgbData(pixelCount * 3);
for (EGLint y = 0; y < mTestParams.windowHeight; ++y)
{
for (EGLint x = 0; x < mTestParams.windowWidth; ++x)
{
EGLint srcPixel = x + y * mTestParams.windowWidth;
EGLint dstPixel = x + (mTestParams.windowHeight - y - 1) * mTestParams.windowWidth;
memcpy(&rgbData[dstPixel * 3], &pixelData[srcPixel * 4], 3);
}
}
angle::SavePNGRGB(screenshotName.c_str(), "ANGLE Screenshot", mTestParams.windowWidth,
mTestParams.windowHeight, rgbData);
// Finish the frame loop.
for (uint32_t nextFrame = traceInfo.startFrame + 1; nextFrame < traceInfo.endFrame; ++nextFrame)
{
ReplayFrame(testID, nextFrame);
}
getGLWindow()->swap();
glFinish();
}
ANGLE_MAYBE_UNUSED void FramebufferChangeCallback(void *userData, GLenum target, GLuint framebuffer) ANGLE_MAYBE_UNUSED void FramebufferChangeCallback(void *userData, GLenum target, GLuint framebuffer)
{ {
reinterpret_cast<TracePerfTest *>(userData)->onFramebufferChange(target, framebuffer); reinterpret_cast<TracePerfTest *>(userData)->onFramebufferChange(target, framebuffer);
......
...@@ -39,11 +39,11 @@ class ScopedFILE ...@@ -39,11 +39,11 @@ class ScopedFILE
}; };
} // namespace } // namespace
bool SavePNG(const char *fileName, bool SavePNGRGB(const char *fileName,
const char *title, const char *title,
uint32_t width, uint32_t width,
uint32_t height, uint32_t height,
const std::vector<uint8_t> &data) const std::vector<uint8_t> &data)
{ {
ScopedFILE fp(fopen(fileName, "wb")); ScopedFILE fp(fopen(fileName, "wb"));
if (!fp.get()) if (!fp.get())
...@@ -78,7 +78,7 @@ bool SavePNG(const char *fileName, ...@@ -78,7 +78,7 @@ bool SavePNG(const char *fileName,
png_init_io(writeStruct, fp.get()); png_init_io(writeStruct, fp.get());
// Write header (8 bit colour depth) // Write header (8 bit colour depth)
png_set_IHDR(writeStruct, infoStruct, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, png_set_IHDR(writeStruct, infoStruct, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
// Set title // Set title
...@@ -98,8 +98,8 @@ bool SavePNG(const char *fileName, ...@@ -98,8 +98,8 @@ bool SavePNG(const char *fileName,
png_write_info(writeStruct, infoStruct); png_write_info(writeStruct, infoStruct);
// RGBA 4-byte stride. // RGB 3-byte stride.
const uint32_t rowStride = width * 4; const uint32_t rowStride = width * 3;
for (uint32_t row = 0; row < height; ++row) for (uint32_t row = 0; row < height; ++row)
{ {
uint32_t rowOffset = row * rowStride; uint32_t rowOffset = row * rowStride;
......
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
namespace angle namespace angle
{ {
bool SavePNG(const char *fileName, bool SavePNGRGB(const char *fileName,
const char *title, const char *title,
uint32_t width, uint32_t width,
uint32_t height, uint32_t height,
const std::vector<uint8_t> &data); const std::vector<uint8_t> &rgbData);
} // namespace angle } // namespace angle
#endif // UTIL_PNG_UTILS_H_ #endif // UTIL_PNG_UTILS_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment