diff --git a/src/common/PackedEnums.h b/src/common/PackedEnums.h index 43e8a3723..006367b2f 100644 --- a/src/common/PackedEnums.h +++ b/src/common/PackedEnums.h @@ -858,6 +858,14 @@ operator==(const T &lhs, const T &rhs) { return lhs.value == rhs.value; } + +template +typename std::enable_if::value && !std::is_same::value, + bool>::type +operator<(const T &lhs, const T &rhs) +{ + return lhs.value < rhs.value; +} } // namespace egl #undef ANGLE_DEFINE_ID_TYPE diff --git a/src/libANGLE/Display.h b/src/libANGLE/Display.h index 0c945939d..2966f082d 100644 --- a/src/libANGLE/Display.h +++ b/src/libANGLE/Display.h @@ -117,6 +117,10 @@ class ShareGroup final : angle::NonCopyable // Constant coded here as a reasonable limit. constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000; +using ImageMap = angle::HashMap; +using StreamSet = angle::HashSet; +using SyncMap = angle::HashMap; + class Display final : public LabeledObject, public angle::ObserverInterface, public angle::NonCopyable @@ -348,6 +352,8 @@ class Display final : public LabeledObject, egl::Image *getImage(egl::ImageID imageID); egl::Sync *getSync(egl::SyncID syncID); + const SyncMap &getSyncsForCapture() const { return mSyncMap; } + // Initialize thread-local variables used by the Display and its backing implementations. This // includes: // @@ -389,13 +395,8 @@ class Display final : public LabeledObject, ConfigSet mConfigSet; - typedef angle::HashMap ImageMap; ImageMap mImageMap; - - typedef angle::HashSet StreamSet; StreamSet mStreamSet; - - typedef angle::HashMap SyncMap; SyncMap mSyncMap; void destroyImageImpl(Image *image, ImageMap *images); diff --git a/src/libANGLE/EGLSync.cpp b/src/libANGLE/EGLSync.cpp index f6f971397..c8c20223f 100644 --- a/src/libANGLE/EGLSync.cpp +++ b/src/libANGLE/EGLSync.cpp @@ -25,6 +25,7 @@ Sync::Sync(rx::EGLImplFactory *factory, : mLabel(nullptr), mId(id), mType(type), + mAttributeMap(attribs), mCondition(EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR), mNativeFenceFD( attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID)) diff --git a/src/libANGLE/EGLSync.h b/src/libANGLE/EGLSync.h index 45f9757a8..eef6974b9 100644 --- a/src/libANGLE/EGLSync.h +++ b/src/libANGLE/EGLSync.h @@ -56,6 +56,7 @@ class Sync final : public angle::RefCountObject, public Error dupNativeFenceFD(const Display *display, EGLint *result) const; EGLenum getType() const { return mType; } + const AttributeMap &getAttributeMap() const { return mAttributeMap; } EGLint getCondition() const { return mCondition; } EGLint getNativeFenceFD() const { return mNativeFenceFD; } @@ -66,6 +67,7 @@ class Sync final : public angle::RefCountObject, public SyncID mId; EGLenum mType; + AttributeMap mAttributeMap; EGLint mCondition; EGLint mNativeFenceFD; }; diff --git a/src/libANGLE/capture/FrameCapture.cpp b/src/libANGLE/capture/FrameCapture.cpp index 7fe957bf0..6249c2865 100644 --- a/src/libANGLE/capture/FrameCapture.cpp +++ b/src/libANGLE/capture/FrameCapture.cpp @@ -30,6 +30,7 @@ #include "libANGLE/Context.h" #include "libANGLE/Context.inl.h" #include "libANGLE/Display.h" +#include "libANGLE/EGLSync.h" #include "libANGLE/Fence.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/GLES1Renderer.h" @@ -1375,6 +1376,44 @@ void MaybeResetResources(gl::ContextID contextID, } break; } + case ResourceIDType::egl_Sync: + { + TrackedResource &trackedEGLSyncs = + resourceTracker->getTrackedResource(contextID, ResourceIDType::egl_Sync); + ResourceSet &newEGLSyncs = trackedEGLSyncs.getNewResources(); + ResourceSet &eglSyncsToDelete = trackedEGLSyncs.getResourcesToDelete(); + ResourceSet &eglSyncsToRegen = trackedEGLSyncs.getResourcesToRegen(); + ResourceCalls &eglSyncRegenCalls = trackedEGLSyncs.getResourceRegenCalls(); + + if (!newEGLSyncs.empty() || !eglSyncsToDelete.empty()) + { + for (GLuint oldResource : eglSyncsToDelete) + { + out << " eglDestroySyncKHR(gEGLDisplay, gEGLSyncMap[" << oldResource + << "]);\n"; + } + + for (GLuint newResource : newEGLSyncs) + { + out << " eglDestroySyncKHR(gEGLDisplay, gEGLSyncMap[" << newResource + << "]);\n"; + } + } + + // If any of our starting EGLsyncs were deleted during the run, recreate them + for (GLuint id : eglSyncsToRegen) + { + // Emit their regen calls + for (CallCapture &call : eglSyncRegenCalls[id]) + { + out << " "; + WriteCppReplayForCall(call, replayWriter, out, header, binaryData, + maxResourceIDBufferSize); + out << ";\n"; + } + } + break; + } default: // TODO (http://anglebug.com/4599): Reset more resource types break; @@ -2248,8 +2287,9 @@ bool IsSharedObjectResource(ResourceIDType type) case ResourceIDType::Image: case ResourceIDType::Surface: case ResourceIDType::egl_Sync: - // Return false for all EGL object types. - return false; + // EGL types are associated with a display and not bound to a context + // For the way this function is used, we can treat them as shared. + return true; case ResourceIDType::EnumCount: default: @@ -3540,6 +3580,28 @@ void CaptureFenceSyncResetCalls(const gl::Context *context, MaybeCaptureUpdateResourceIDs(context, resourceTracker, &fenceSyncRegenCalls[syncID]); } +void CaptureEGLSyncResetCalls(const gl::Context *context, + const gl::State &replayState, + ResourceTracker *resourceTracker, + egl::SyncID eglSyncID, + EGLSync eglSyncObject, + const egl::Sync *eglSync) +{ + // Track this as a starting resource that may need to be restored. + TrackedResource &trackedEGLSyncs = + resourceTracker->getTrackedResource(context->id(), ResourceIDType::egl_Sync); + + // Track calls to regenerate a given buffer + ResourceCalls &eglSyncRegenCalls = trackedEGLSyncs.getResourceRegenCalls(); + + CallCapture createEGLSync = + CaptureCreateSyncKHR(nullptr, true, context->getDisplay(), eglSync->getType(), + eglSync->getAttributeMap(), eglSyncObject); + CaptureCustomCreateEGLSync("CreateEGLSyncKHR", createEGLSync, + eglSyncRegenCalls[eglSyncID.value]); + MaybeCaptureUpdateResourceIDs(context, resourceTracker, &eglSyncRegenCalls[eglSyncID.value]); +} + void CaptureBufferBindingResetCalls(const gl::State &replayState, ResourceTracker *resourceTracker, gl::BufferBinding binding, @@ -4449,6 +4511,29 @@ void CaptureShareGroupMidExecutionSetup( resourceTracker->getStartingFenceSyncs().insert(syncID); } + // Capture EGL Sync Objects + const egl::SyncMap eglSyncMap = context->getDisplay()->getSyncsForCapture(); + for (const auto &eglSyncIter : eglSyncMap) + { + egl::SyncID eglSyncID = {eglSyncIter.first}; + const egl::Sync *eglSync = eglSyncIter.second; + EGLSync eglSyncObject = gl::unsafe_int_to_pointer_cast(eglSyncID.value); + + if (!eglSync) + { + continue; + } + CallCapture createEGLSync = + CaptureCreateSync(nullptr, true, context->getDisplay(), eglSync->getType(), + eglSync->getAttributeMap(), eglSyncObject); + CaptureCustomCreateEGLSync("CreateEGLSyncKHR", createEGLSync, *setupCalls); + CaptureEGLSyncResetCalls(context, replayState, resourceTracker, eglSyncID, eglSyncObject, + eglSync); + resourceTracker->getTrackedResource(context->id(), ResourceIDType::egl_Sync) + .getStartingResources() + .insert(eglSyncID.value); + } + GLint contextUnpackAlignment = context->getState().getUnpackState().alignment; if (currentUnpackState.alignment != contextUnpackAlignment) { @@ -7563,6 +7648,33 @@ void FrameCaptureShared::maybeCapturePreCallUpdates( egl::AttributeMap::CreateFromIntArray); break; } + case EntryPoint::EGLCreateSync: + case EntryPoint::EGLCreateSyncKHR: + { + egl::SyncID eglSyncID = call.params.getReturnValue().value.egl_SyncIDVal; + FrameCaptureShared *frameCaptureShared = + context->getShareGroup()->getFrameCaptureShared(); + // If we're capturing, track which egl sync has been created + if (frameCaptureShared->isCaptureActive()) + { + handleGennedResource(context, eglSyncID); + } + break; + } + case EntryPoint::EGLDestroySync: + case EntryPoint::EGLDestroySyncKHR: + { + egl::SyncID eglSyncID = + call.params.getParam("syncPacked", ParamType::Tegl_SyncID, 1).value.egl_SyncIDVal; + FrameCaptureShared *frameCaptureShared = + context->getShareGroup()->getFrameCaptureShared(); + // If we're capturing, track which EGL sync has been deleted + if (frameCaptureShared->isCaptureActive()) + { + handleDeletedResource(context, eglSyncID); + } + break; + } case EntryPoint::GLDispatchCompute: { // When using shadow memory we need to update the real memory here @@ -8509,7 +8621,7 @@ TrackedResource &ResourceTracker::getTrackedResource(gl::ContextID contextID, Re { if (IsSharedObjectResource(type)) { - // No need to index with context if not shared + // No need to index with context if shared return mTrackedResourcesShared[static_cast(type)]; } else diff --git a/util/capture/trace_fixture.cpp b/util/capture/trace_fixture.cpp index 809fcd05f..caf0cb9ed 100644 --- a/util/capture/trace_fixture.cpp +++ b/util/capture/trace_fixture.cpp @@ -311,6 +311,7 @@ void FinishReplay() delete[] gBufferMap; delete[] gContextMap2; delete[] gEGLImageMap2; + delete[] gEGLSyncMap; delete[] gRenderbufferMap; delete[] gTextureMap; delete[] gFramebufferMap;