Commit 3fc83291 by Charlie Lao Committed by Commit Bot

Vulkan: offscreen perftests: use two FBOs and call glFlush every frame

For offscreen variant of perf tests, we blit from offscreen to onscreen for every frame and then every N frames we call swap. Right now we never call glFlush. This causes test accumulate many frames rendering without a flush, which changes the behavior. For example, gfxbench does issue glFlush for every frame. This CL adds glFlush call for every frame when swap is not called. Also ARM native GLES driver and ANGLE skip glFlush call if it is issued within the same FBO. For some traces that does not use any FBO, there is no frame boundary for drivers to detect, versus for onscreen there is actual frame boundary. To solve this mismatch problem, this CL also uses two offscreen FBOs and ping pong between them so that it will still have the frame boundary but not goes to screen. This allows drivers that try to detect frame boundary still function properly. Bug: b/184766477 Change-Id: I23edda66fdf391930afd3f6b1d955b41ec6ad019 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2861844 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent b62f8dd1
...@@ -131,17 +131,19 @@ class TracePerfTest : public ANGLERenderTest, public ::testing::WithParamInterfa ...@@ -131,17 +131,19 @@ class TracePerfTest : public ANGLERenderTest, public ::testing::WithParamInterfa
std::vector<TimeSample> mTimeline; std::vector<TimeSample> mTimeline;
std::string mStartingDirectory; std::string mStartingDirectory;
bool mUseTimestampQueries = false; bool mUseTimestampQueries = false;
GLuint mOffscreenFramebuffer = 0; static constexpr int mMaxOffscreenBufferCount = 2;
GLuint mOffscreenTexture = 0; std::array<GLuint, mMaxOffscreenBufferCount> mOffscreenFramebuffers = {0, 0};
GLuint mOffscreenDepthStencil = 0; std::array<GLuint, mMaxOffscreenBufferCount> mOffscreenTextures = {0, 0};
int mWindowWidth = 0; GLuint mOffscreenDepthStencil = 0;
int mWindowHeight = 0; int mWindowWidth = 0;
GLuint mDrawFramebufferBinding = 0; int mWindowHeight = 0;
GLuint mReadFramebufferBinding = 0; GLuint mDrawFramebufferBinding = 0;
uint32_t mCurrentFrame = 0; GLuint mReadFramebufferBinding = 0;
uint32_t mOffscreenFrameCount = 0; uint32_t mCurrentFrame = 0;
bool mScreenshotSaved = false; uint32_t mOffscreenFrameCount = 0;
uint32_t mTotalFrameCount = 0;
bool mScreenshotSaved = false;
std::unique_ptr<TraceLibrary> mTraceLibrary; std::unique_ptr<TraceLibrary> mTraceLibrary;
}; };
...@@ -1020,27 +1022,30 @@ void TracePerfTest::initializeBenchmark() ...@@ -1020,27 +1022,30 @@ void TracePerfTest::initializeBenchmark()
mWindowHeight *= 4; mWindowHeight *= 4;
} }
glGenFramebuffers(1, &mOffscreenFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
// Hard-code RGBA8/D24S8. This should be specified in the trace info.
glGenTextures(1, &mOffscreenTexture);
glBindTexture(GL_TEXTURE_2D, mOffscreenTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWindowWidth, mWindowHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
glGenRenderbuffers(1, &mOffscreenDepthStencil); glGenRenderbuffers(1, &mOffscreenDepthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, mOffscreenDepthStencil); glBindRenderbuffer(GL_RENDERBUFFER, mOffscreenDepthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mWindowWidth, mWindowHeight); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mWindowWidth, mWindowHeight);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
mOffscreenTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mOffscreenDepthStencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mOffscreenDepthStencil);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenFramebuffers(mMaxOffscreenBufferCount, mOffscreenFramebuffers.data());
glGenTextures(mMaxOffscreenBufferCount, mOffscreenTextures.data());
for (int i = 0; i < mMaxOffscreenBufferCount; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffers[i]);
// Hard-code RGBA8/D24S8. This should be specified in the trace info.
glBindTexture(GL_TEXTURE_2D, mOffscreenTextures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWindowWidth, mWindowHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
mOffscreenTextures[i], 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mOffscreenDepthStencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mOffscreenDepthStencil);
glBindTexture(GL_TEXTURE_2D, 0);
}
} }
// Potentially slow. Can load a lot of resources. // Potentially slow. Can load a lot of resources.
...@@ -1066,23 +1071,14 @@ void TracePerfTest::initializeBenchmark() ...@@ -1066,23 +1071,14 @@ void TracePerfTest::initializeBenchmark()
void TracePerfTest::destroyBenchmark() void TracePerfTest::destroyBenchmark()
{ {
if (mOffscreenTexture != 0) glDeleteTextures(mMaxOffscreenBufferCount, mOffscreenTextures.data());
{ mOffscreenTextures.fill(0);
glDeleteTextures(1, &mOffscreenTexture);
mOffscreenTexture = 0;
}
if (mOffscreenDepthStencil != 0) glDeleteRenderbuffers(1, &mOffscreenDepthStencil);
{ mOffscreenDepthStencil = 0;
glDeleteRenderbuffers(1, &mOffscreenDepthStencil);
mOffscreenDepthStencil = 0;
}
if (mOffscreenFramebuffer != 0) glDeleteFramebuffers(mMaxOffscreenBufferCount, mOffscreenFramebuffers.data());
{ mOffscreenFramebuffers.fill(0);
glDeleteFramebuffers(1, &mOffscreenFramebuffer);
mOffscreenFramebuffer = 0;
}
mTraceLibrary->finishReplay(); mTraceLibrary->finishReplay();
mTraceLibrary.reset(nullptr); mTraceLibrary.reset(nullptr);
...@@ -1136,6 +1132,18 @@ void TracePerfTest::drawBenchmark() ...@@ -1136,6 +1132,18 @@ void TracePerfTest::drawBenchmark()
sampleTime(); sampleTime();
} }
if (params.surfaceType == SurfaceType::Offscreen)
{
// Some driver (ARM and ANGLE) try to nop or defer the glFlush if it is called within the
// renderpass to avoid breaking renderpass (performance reason). For app traces that does
// not use any FBO, when we run in the offscreen mode, there is no frame boundary and
// glFlush call we issued at end of frame will get skipped. To overcome this (and also
// matches what onscreen double buffering behavior as well), we use two offscreen FBOs and
// ping pong between them for each frame.
glBindFramebuffer(GL_FRAMEBUFFER,
mOffscreenFramebuffers[mTotalFrameCount % mMaxOffscreenBufferCount]);
}
char frameName[32]; char frameName[32];
sprintf(frameName, "Frame %u", mCurrentFrame); sprintf(frameName, "Frame %u", mCurrentFrame);
beginInternalTraceEvent(frameName); beginInternalTraceEvent(frameName);
...@@ -1151,7 +1159,8 @@ void TracePerfTest::drawBenchmark() ...@@ -1151,7 +1159,8 @@ void TracePerfTest::drawBenchmark()
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &currentReadFBO); glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &currentReadFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mOffscreenFramebuffer); glBindFramebuffer(GL_READ_FRAMEBUFFER,
mOffscreenFramebuffers[mTotalFrameCount % mMaxOffscreenBufferCount]);
uint32_t frameX = (mOffscreenFrameCount % kFramesPerXY) % kFramesPerX; uint32_t frameX = (mOffscreenFrameCount % kFramesPerXY) % kFramesPerX;
uint32_t frameY = (mOffscreenFrameCount % kFramesPerXY) / kFramesPerX; uint32_t frameY = (mOffscreenFrameCount % kFramesPerXY) / kFramesPerX;
...@@ -1185,6 +1194,7 @@ void TracePerfTest::drawBenchmark() ...@@ -1185,6 +1194,7 @@ void TracePerfTest::drawBenchmark()
} }
else else
{ {
glFlush();
mOffscreenFrameCount++; mOffscreenFrameCount++;
} }
...@@ -1194,6 +1204,8 @@ void TracePerfTest::drawBenchmark() ...@@ -1194,6 +1204,8 @@ void TracePerfTest::drawBenchmark()
} }
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentDrawFBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentDrawFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER, currentReadFBO); glBindFramebuffer(GL_READ_FRAMEBUFFER, currentReadFBO);
mTotalFrameCount++;
} }
else else
{ {
...@@ -1293,7 +1305,8 @@ void TracePerfTest::onReplayFramebufferChange(GLenum target, GLuint framebuffer) ...@@ -1293,7 +1305,8 @@ void TracePerfTest::onReplayFramebufferChange(GLenum target, GLuint framebuffer)
{ {
if (framebuffer == 0 && GetParam().surfaceType == SurfaceType::Offscreen) if (framebuffer == 0 && GetParam().surfaceType == SurfaceType::Offscreen)
{ {
glBindFramebuffer(target, mOffscreenFramebuffer); glBindFramebuffer(target,
mOffscreenFramebuffers[mTotalFrameCount % mMaxOffscreenBufferCount]);
} }
else else
{ {
......
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