Commit 7444466c by Tim Van Patten Committed by Commit Bot

Reland "Capture/Replay: Reset GL Fence Sync objects"

This is a reland of 9b4fd545 This fixes the original CL by moving where setCaptureActive() is called to allow the first replay source file to be written. Original change's description: > Capture/Replay: Reset GL Fence Sync objects > > Asphalt 9 uses GL Fence Sync objects during rendering, which results in > Fence Sync objects being created during setup and deleted while > replaying frames. When the replay is restarted, the Fence Sync objects > that were created during setup and deleted during the replay need to be > recreated during the reset phase. > > Bug: angleproject:5883 > Bug: angleproject:4599 > Change-Id: I118f2b7208c4d512ab646b10f52b3a0936895089 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2838237 > Commit-Queue: Tim Van Patten <timvp@google.com> > Reviewed-by: Cody Northrop <cnorthrop@google.com> > Reviewed-by: Jamie Madill <jmadill@chromium.org> Bug: angleproject:5883 Bug: angleproject:4599 Bug: angleproject:5900 Change-Id: I5e1d901d8875007691699b7b973f3fb7db027337 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2850758Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Tim Van Patten <timvp@google.com>
parent dcfd5526
......@@ -931,6 +931,37 @@ void MaybeResetResources(std::stringstream &out,
}
}
void MaybeResetFenceSyncObjects(std::stringstream &out,
DataTracker *dataTracker,
std::stringstream &header,
ResourceTracker *resourceTracker,
std::vector<uint8_t> *binaryData)
{
FenceSyncCalls &fenceSyncRegenCalls = resourceTracker->getFenceSyncRegenCalls();
// If any of our starting fence sync objects were deleted during the run, recreate them
FenceSyncSet &fenceSyncsToRegen = resourceTracker->getFenceSyncsToRegen();
for (const GLsync sync : fenceSyncsToRegen)
{
// Emit their regen calls
for (CallCapture &call : fenceSyncRegenCalls[sync])
{
out << " ";
WriteCppReplayForCall(call, dataTracker, out, header, binaryData);
out << ";\n";
}
}
}
void MaybeResetOpaqueTypeObjects(std::stringstream &out,
DataTracker *dataTracker,
std::stringstream &header,
ResourceTracker *resourceTracker,
std::vector<uint8_t> *binaryData)
{
MaybeResetFenceSyncObjects(out, dataTracker, header, resourceTracker, binaryData);
}
void WriteCppReplayFunctionWithParts(const gl::Context *context,
ReplayFunc replayFunc,
DataTracker *dataTracker,
......@@ -1058,8 +1089,11 @@ void WriteCppReplay(bool compression,
resourceTracker, binaryData);
}
out << restoreCallStream.str();
// Reset opaque type objects that don't have IDs, so are not ResourceIDTypes.
MaybeResetOpaqueTypeObjects(restoreCallStream, &dataTracker, header, resourceTracker,
binaryData);
out << restoreCallStream.str();
out << "}\n";
}
......@@ -2104,6 +2138,18 @@ void CaptureBufferResetCalls(const gl::State &replayState,
CaptureUnmapBuffer(replayState, true, gl::BufferBinding::Array, GL_TRUE));
}
void CaptureFenceSyncResetCalls(const gl::State &replayState,
ResourceTracker *resourceTracker,
GLsync syncID,
const gl::Sync *sync)
{
// Track calls to regenerate a given fence sync
FenceSyncCalls &fenceSyncRegenCalls = resourceTracker->getFenceSyncRegenCalls();
Capture(&fenceSyncRegenCalls[syncID],
CaptureFenceSync(replayState, true, sync->getCondition(), sync->getFlags(), syncID));
MaybeCaptureUpdateResourceIDs(&fenceSyncRegenCalls[syncID]);
}
void CaptureBufferBindingResetCalls(const gl::State &replayState,
ResourceTracker *resourceTracker,
gl::BufferBinding binding,
......@@ -3073,6 +3119,8 @@ void CaptureMidExecutionSetup(const gl::Context *context,
continue;
}
cap(CaptureFenceSync(replayState, true, sync->getCondition(), sync->getFlags(), syncID));
CaptureFenceSyncResetCalls(replayState, resourceTracker, syncID, sync);
resourceTracker->getStartingFenceSyncs().insert(syncID);
}
// Capture Image Texture bindings
......@@ -4047,7 +4095,7 @@ void FrameCapture::maybeCapturePreCallUpdates(const gl::Context *context, CallCa
mBufferDataMap.erase(bufferDataInfo);
}
// If we're capturing, track what buffers have been deleted
if (mFrameIndex >= mCaptureStartFrame)
if (isCaptureActive())
{
mResourceTracker.setDeletedBuffer(bufferIDs[i]);
}
......@@ -4064,7 +4112,7 @@ void FrameCapture::maybeCapturePreCallUpdates(const gl::Context *context, CallCa
for (GLsizei i = 0; i < count; i++)
{
// If we're capturing, track what new buffers have been genned
if (mFrameIndex >= mCaptureStartFrame)
if (isCaptureActive())
{
mResourceTracker.setGennedBuffer(bufferIDs[i]);
}
......@@ -4072,6 +4120,17 @@ void FrameCapture::maybeCapturePreCallUpdates(const gl::Context *context, CallCa
break;
}
case EntryPoint::GLDeleteSync:
{
GLsync sync = call.params.getParam("sync", ParamType::TGLsync, 0).value.GLsyncVal;
// If we're capturing, track which fence sync has been deleted
if (isCaptureActive())
{
mResourceTracker.setDeletedFenceSync(sync);
}
break;
}
case EntryPoint::GLDrawArrays:
{
maybeCaptureDrawArraysClientData(context, call, 1);
......@@ -4506,11 +4565,23 @@ void FrameCapture::checkForCaptureTrigger()
void FrameCapture::onEndFrame(const gl::Context *context)
{
if (mFrameIndex > mCaptureEndFrame)
{
setCaptureInactive();
return;
}
// On Android, we can trigger a capture during the run
checkForCaptureTrigger();
// Done after checkForCaptureTrigger(), since that can modify mCaptureStartFrame.
if (mFrameIndex >= mCaptureStartFrame)
{
setCaptureActive();
}
// Note that we currently capture before the start frame to collect shader and program sources.
if (!mFrameCalls.empty() && mFrameIndex >= mCaptureStartFrame)
if (!mFrameCalls.empty() && isCaptureActive())
{
if (mIsFirstFrame)
{
......@@ -4661,6 +4732,19 @@ void ResourceTracker::setDeletedBuffer(gl::BufferID id)
mBuffersToRestore.insert(id);
}
void ResourceTracker::setDeletedFenceSync(GLsync sync)
{
ASSERT(sync != nullptr);
if (mStartingFenceSyncs.find(sync) == mStartingFenceSyncs.end())
{
// This is a fence sync created after MEC was initialized. Ignore it.
return;
}
// In this case, the app is deleting a fence sync we started with, we need to regen on loop.
mFenceSyncsToRegen.insert(sync);
}
void ResourceTracker::setGennedBuffer(gl::BufferID id)
{
if (mStartingBuffers.find(id) == mStartingBuffers.end())
......
......@@ -213,6 +213,9 @@ using BufferCalls = std::map<gl::BufferID, std::vector<CallCapture>>;
// true means mapped, false means unmapped
using BufferMapStatusMap = std::map<gl::BufferID, bool>;
using FenceSyncSet = std::set<GLsync>;
using FenceSyncCalls = std::map<GLsync, std::vector<CallCapture>>;
// Helper to track resource changes during the capture
class ResourceTracker final : angle::NonCopyable
{
......@@ -258,6 +261,11 @@ class ResourceTracker final : angle::NonCopyable
void onShaderProgramAccess(gl::ShaderProgramID shaderProgramID);
uint32_t getMaxShaderPrograms() const { return mMaxShaderPrograms; }
FenceSyncSet &getStartingFenceSyncs() { return mStartingFenceSyncs; }
FenceSyncCalls &getFenceSyncRegenCalls() { return mFenceSyncRegenCalls; }
FenceSyncSet &getFenceSyncsToRegen() { return mFenceSyncsToRegen; }
void setDeletedFenceSync(GLsync sync);
private:
// Buffer regen calls will delete and gen a buffer
BufferCalls mBufferRegenCalls;
......@@ -287,6 +295,14 @@ class ResourceTracker final : angle::NonCopyable
// Maximum accessed shader program ID.
uint32_t mMaxShaderPrograms = 0;
// Fence sync objects created during MEC setup
FenceSyncSet mStartingFenceSyncs;
// Fence sync regen calls will create a fence sync objects
FenceSyncCalls mFenceSyncRegenCalls;
// Fence syncs to regen are a list of starting fence sync objects that were deleted and need to
// be regen'ed.
FenceSyncSet mFenceSyncsToRegen;
};
// Used by the CPP replay to filter out unnecessary code.
......@@ -361,6 +377,10 @@ class FrameCapture final : angle::NonCopyable
ReplayContext *replayContext,
const CallCapture &call);
void setCaptureActive() { mCaptureActive = true; }
void setCaptureInactive() { mCaptureActive = false; }
bool isCaptureActive() { return mCaptureActive; }
std::vector<CallCapture> mSetupCalls;
std::vector<CallCapture> mFrameCalls;
......@@ -391,6 +411,8 @@ class FrameCapture final : angle::NonCopyable
// Initialize it to the number of frames you want to capture, and then clear the value to 0 when
// you reach the content you want to capture. Currently only available on Android.
uint32_t mCaptureTrigger;
bool mCaptureActive = false;
};
// Shared class for any items that need to be tracked by FrameCapture across shared contexts
......
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