// // Copyright 2020 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // frame_capture_test_utils: // Helper functions for capture and replay of traces. // #ifndef UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_ #define UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_ #include #include #include #include #include #include #include "common/angleutils.h" #include "common/debug.h" #include "common/frame_capture_utils.h" #include "common/system_utils.h" #include "trace_interface.h" #define USE_SYSTEM_ZLIB #include "compression_utils_portable.h" #define ANGLE_MACRO_STRINGIZE_AUX(a) #a #define ANGLE_MACRO_STRINGIZE(a) ANGLE_MACRO_STRINGIZE_AUX(a) #define ANGLE_MACRO_CONCAT_AUX(a, b) a##b #define ANGLE_MACRO_CONCAT(a, b) ANGLE_MACRO_CONCAT_AUX(a, b) namespace angle { using ValidateSerializedStateCallback = void (*)(const char *, const char *, uint32_t); using GetSerializedContextStateFunc = const char *(*)(uint32_t); using SetValidateSerializedStateCallbackFunc = void (*)(ValidateSerializedStateCallback); using SetupEntryPoints = void (*)(angle::TraceCallbacks *, angle::TraceFunctions **); class TraceLibrary : angle::NonCopyable, angle::TraceCallbacks { public: TraceLibrary(const std::string &traceName, const TraceInfo &traceInfo, const std::string &baseDir); bool valid() const { return (mTraceLibrary != nullptr) && (mTraceLibrary->getNative() != nullptr); } void setReplayResourceMode(const bool resourceMode) { mTraceFunctions->SetReplayResourceMode( (resourceMode ? ReplayResourceMode::All : ReplayResourceMode::Active)); } void setBinaryDataDir(const char *dataDir) { mBinaryDataDir = dataDir; mTraceFunctions->SetBinaryDataDir(dataDir); } void setDebugOutputDir(const char *dataDir) { mDebugOutputDir = dataDir; } void replayFrame(uint32_t frameIndex) { mTraceFunctions->ReplayFrame(frameIndex); } void setupReplay() { mTraceFunctions->SetupReplay(); } void resetReplay() { mTraceFunctions->ResetReplay(); } void finishReplay() { mTraceFunctions->FinishReplay(); mBinaryData = {}; // set to empty vector to release memory. } void setupFirstFrame() { mTraceFunctions->SetupFirstFrame(); } const char *getSerializedContextState(uint32_t frameIndex) { return callFunc("GetSerializedContextState", frameIndex); } void setValidateSerializedStateCallback(ValidateSerializedStateCallback callback) { return callFunc( "SetValidateSerializedStateCallback", callback); } void setTraceGzPath(const std::string &traceGzPath) { mTraceFunctions->SetTraceGzPath(traceGzPath); } private: template typename std::invoke_result::type callFunc(const char *funcName, ArgsT... args) { void *untypedFunc = mTraceLibrary->getSymbol(funcName); if (!untypedFunc) { fprintf(stderr, "Error loading function: %s\n", funcName); ASSERT(untypedFunc); } auto typedFunc = reinterpret_cast(untypedFunc); return typedFunc(args...); } uint8_t *LoadBinaryData(const char *fileName) override; std::unique_ptr mTraceLibrary; std::vector mBinaryData; std::string mBinaryDataDir; std::string mDebugOutputDir; angle::TraceInfo mTraceInfo; angle::TraceFunctions *mTraceFunctions = nullptr; }; bool LoadTraceNamesFromJSON(const std::string jsonFilePath, std::vector *namesOut); bool LoadTraceInfoFromJSON(const std::string &traceName, const std::string &traceJsonPath, TraceInfo *traceInfoOut); using TraceFunction = std::vector; using TraceFunctionMap = std::map; void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions); void ReplayCustomFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions); template struct AssertFalse : std::false_type {}; GLuint GetResourceIDMapValue(ResourceIDType resourceIDType, GLuint key); template T GetParamValue(ParamType type, const ParamValue &value); template <> inline GLuint GetParamValue(ParamType type, const ParamValue &value) { ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(type); if (resourceIDType == ResourceIDType::InvalidEnum) { return value.GLuintVal; } else { return GetResourceIDMapValue(resourceIDType, value.GLuintVal); } } template <> inline GLint GetParamValue(ParamType type, const ParamValue &value) { return value.GLintVal; } template <> inline const void *GetParamValue(ParamType type, const ParamValue &value) { return value.voidConstPointerVal; } template <> inline GLuint64 GetParamValue(ParamType type, const ParamValue &value) { return value.GLuint64Val; } template <> inline GLint64 GetParamValue(ParamType type, const ParamValue &value) { return value.GLint64Val; } template <> inline const char *GetParamValue(ParamType type, const ParamValue &value) { return value.GLcharConstPointerVal; } template <> inline void *GetParamValue(ParamType type, const ParamValue &value) { return value.voidPointerVal; } #if defined(ANGLE_IS_64_BIT_CPU) template <> inline const EGLAttrib *GetParamValue(ParamType type, const ParamValue &value) { return value.EGLAttribConstPointerVal; } #endif // defined(ANGLE_IS_64_BIT_CPU) template <> inline const EGLint *GetParamValue(ParamType type, const ParamValue &value) { return value.EGLintConstPointerVal; } template <> inline const GLchar *const *GetParamValue(ParamType type, const ParamValue &value) { return value.GLcharConstPointerPointerVal; } // On Apple platforms, std::is_same is false despite being both 8 bits. #if defined(ANGLE_PLATFORM_APPLE) || !defined(ANGLE_IS_64_BIT_CPU) template <> inline long GetParamValue(ParamType type, const ParamValue &value) { return static_cast(value.GLint64Val); } template <> inline unsigned long GetParamValue(ParamType type, const ParamValue &value) { return static_cast(value.GLuint64Val); } #endif // defined(ANGLE_PLATFORM_APPLE) template T GetParamValue(ParamType type, const ParamValue &value) { static_assert(AssertFalse::value, "No specialization for type."); } template struct Traits; template struct Traits { static constexpr size_t NArgs = sizeof...(Args); template struct Arg { typedef typename std::tuple_element>::type Type; }; }; template using FnArg = typename Traits::template Arg::Type; template using EnableIfNArgs = typename std::enable_if_t::NArgs == NArgs, int>; template FnArg Arg(const Captures &cap) { ASSERT(Idx < cap.size()); return GetParamValue>(cap[Idx].type, cap[Idx].value); } } // namespace angle #endif // UTIL_CAPTURE_FRAME_CAPTURE_TEST_UTILS_H_