-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
capture/replay: implement infrastructure for capture (#4372)
* Define api call ID for each being captured methods * Add parameter encoder interface * Add outputStream and capture manager Add infrastructure for output stream This is the interface to record the method and parameter, and also provide functionality to write all the serialized data into file. Add capture manager: Capture manager is associated to global session object, it will provide the functionality to actual record all the APIs. Implement some of parameter encoder functions. * Fix some Windows & cmake build error * remove unused headers
- Loading branch information
1 parent
ecc6ecb
commit f0d40ad
Showing
12 changed files
with
507 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#ifndef API_CALL_ID_H | ||
#define API_CALL_ID_H | ||
|
||
#include <cstdint> | ||
|
||
namespace SlangCapture | ||
{ | ||
constexpr uint32_t makeApiCallId(uint16_t classId, uint16_t memberFunctionId) | ||
{ | ||
return ((static_cast<uint32_t>(classId) << 16) & 0xffff0000) | (static_cast<uint32_t>(memberFunctionId) & 0x0000ffff); | ||
} | ||
|
||
constexpr uint16_t getClassId(uint32_t callId) | ||
{ | ||
return static_cast<uint16_t>((callId >> 16) & 0x0000ffff); | ||
} | ||
|
||
constexpr uint16_t getMemberFunctionId(uint32_t callId) | ||
{ | ||
return static_cast<uint16_t>(callId & 0x0000ffff); | ||
} | ||
|
||
enum ApiClassId : uint16_t | ||
{ | ||
GlobalFunction = 1, | ||
Class_IGlobalSession = 2, | ||
Class_ISession = 3, | ||
Class_IModule = 4, | ||
Class_IEntryPoint = 5, | ||
Class_ICompositeComponentType = 6, | ||
Class_ITypeConformance = 7, | ||
}; | ||
|
||
typedef uint64_t AddressFormat; | ||
|
||
constexpr uint64_t g_globalFunctionHandle = 0; | ||
|
||
enum ApiCallId : uint32_t | ||
{ | ||
InvalidCallId = 0x00000000, | ||
ICreateGlobalSession = makeApiCallId(GlobalFunction, 0x0000), | ||
IGlobalSession_createSession = makeApiCallId(Class_IGlobalSession, 0x0001), | ||
IGlobalSession_findProfile = makeApiCallId(Class_IGlobalSession, 0x0002), | ||
IGlobalSession_setDownstreamCompilerPath = makeApiCallId(Class_IGlobalSession, 0x0003), | ||
IGlobalSession_setDownstreamCompilerPrelude = makeApiCallId(Class_IGlobalSession, 0x0004), | ||
IGlobalSession_getDownstreamCompilerPrelude = makeApiCallId(Class_IGlobalSession, 0x0005), | ||
IGlobalSession_getBuildTagString = makeApiCallId(Class_IGlobalSession, 0x0006), | ||
IGlobalSession_setDefaultDownstreamCompiler = makeApiCallId(Class_IGlobalSession, 0x0007), | ||
IGlobalSession_getDefaultDownstreamCompiler = makeApiCallId(Class_IGlobalSession, 0x0008), | ||
IGlobalSession_setLanguagePrelude = makeApiCallId(Class_IGlobalSession, 0x0009), | ||
IGlobalSession_getLanguagePrelude = makeApiCallId(Class_IGlobalSession, 0x000A), | ||
IGlobalSession_createCompileRequest = makeApiCallId(Class_IGlobalSession, 0x000B), | ||
IGlobalSession_addBuiltins = makeApiCallId(Class_IGlobalSession, 0x000C), | ||
IGlobalSession_setSharedLibraryLoader = makeApiCallId(Class_IGlobalSession, 0x000D), | ||
IGlobalSession_getSharedLibraryLoader = makeApiCallId(Class_IGlobalSession, 0x000E), | ||
IGlobalSession_checkCompileTargetSupport = makeApiCallId(Class_IGlobalSession, 0x000F), | ||
IGlobalSession_checkPassThroughSupport = makeApiCallId(Class_IGlobalSession, 0x0010), | ||
IGlobalSession_compileStdLib = makeApiCallId(Class_IGlobalSession, 0x0011), | ||
IGlobalSession_loadStdLib = makeApiCallId(Class_IGlobalSession, 0x0012), | ||
IGlobalSession_saveStdLib = makeApiCallId(Class_IGlobalSession, 0x0013), | ||
IGlobalSession_findCapability = makeApiCallId(Class_IGlobalSession, 0x0014), | ||
IGlobalSession_setDownstreamCompilerForTransition = makeApiCallId(Class_IGlobalSession, 0x0015), | ||
IGlobalSession_getDownstreamCompilerForTransition = makeApiCallId(Class_IGlobalSession, 0x0016), | ||
IGlobalSession_getCompilerElapsedTime = makeApiCallId(Class_IGlobalSession, 0x0017), | ||
IGlobalSession_setSPIRVCoreGrammar = makeApiCallId(Class_IGlobalSession, 0x0018), | ||
IGlobalSession_parseCommandLineArguments = makeApiCallId(Class_IGlobalSession, 0x0019), | ||
IGlobalSession_getSessionDescDigest = makeApiCallId(Class_IGlobalSession, 0x001A), | ||
|
||
ISession_getGlobalSession = makeApiCallId(Class_ISession, 0x0001), | ||
ISession_loadModule = makeApiCallId(Class_ISession, 0x0002), | ||
ISession_loadModuleFromBlob = makeApiCallId(Class_ISession, 0x0003), | ||
ISession_loadModuleFromIRBlob = makeApiCallId(Class_ISession, 0x0004), | ||
ISession_loadModuleFromSource = makeApiCallId(Class_ISession, 0x0005), | ||
ISession_loadModuleFromSourceString = makeApiCallId(Class_ISession, 0x0006), | ||
ISession_createCompositeComponentType = makeApiCallId(Class_ISession, 0x0007), | ||
ISession_specializeType = makeApiCallId(Class_ISession, 0x0008), | ||
ISession_getTypeLayout = makeApiCallId(Class_ISession, 0x0009), | ||
ISession_getContainerType = makeApiCallId(Class_ISession, 0x000A), | ||
ISession_getDynamicType = makeApiCallId(Class_ISession, 0x000B), | ||
ISession_getTypeRTTIMangledName = makeApiCallId(Class_ISession, 0x000C), | ||
ISession_getTypeConformanceWitnessMangledName = makeApiCallId(Class_ISession, 0x000D), | ||
ISession_getTypeConformanceWitnessSequentialID = makeApiCallId(Class_ISession, 0x000E), | ||
ISession_createTypeConformanceComponentType = makeApiCallId(Class_ISession, 0x000F), | ||
ISession_createCompileRequest = makeApiCallId(Class_ISession, 0x0010), | ||
ISession_getLoadedModuleCount = makeApiCallId(Class_ISession, 0x0011), | ||
ISession_getLoadedModule = makeApiCallId(Class_ISession, 0x0012), | ||
ISession_isBinaryModuleUpToDate = makeApiCallId(Class_ISession, 0x0013), | ||
|
||
IModule_findEntryPointByName = makeApiCallId(Class_IModule, 0x0001), | ||
IModule_getDefinedEntryPointCount = makeApiCallId(Class_IModule, 0x0002), | ||
IModule_getDefinedEntryPoint = makeApiCallId(Class_IModule, 0x0003), | ||
IModule_serialize = makeApiCallId(Class_IModule, 0x0004), | ||
IModule_writeToFile = makeApiCallId(Class_IModule, 0x0005), | ||
IModule_getName = makeApiCallId(Class_IModule, 0x0006), | ||
IModule_getFilePath = makeApiCallId(Class_IModule, 0x0007), | ||
IModule_getUniqueIdentity = makeApiCallId(Class_IModule, 0x0008), | ||
IModule_findAndCheckEntryPoint = makeApiCallId(Class_IModule, 0x0009), | ||
IModule_getSession = makeApiCallId(Class_IModule, 0x000A), | ||
IModule_getLayout = makeApiCallId(Class_IModule, 0x000B), | ||
IModule_getSpecializationParamCount = makeApiCallId(Class_IModule, 0x000C), | ||
IModule_getEntryPointCode = makeApiCallId(Class_IModule, 0x000D), | ||
IModule_getResultAsFileSystem = makeApiCallId(Class_IModule, 0x000E), | ||
IModule_getEntryPointHash = makeApiCallId(Class_IModule, 0x000F), | ||
IModule_specialize = makeApiCallId(Class_IModule, 0x0010), | ||
IModule_link = makeApiCallId(Class_IModule, 0x0011), | ||
IModule_getEntryPointHostCallable = makeApiCallId(Class_IModule, 0x0012), | ||
IModule_renameEntryPoint = makeApiCallId(Class_IModule, 0x0013), | ||
IModule_linkWithOptions = makeApiCallId(Class_IModule, 0x0014), | ||
|
||
IEntryPoint_getSession = makeApiCallId(Class_IEntryPoint, 0x0001), | ||
IEntryPoint_getLayout = makeApiCallId(Class_IEntryPoint, 0x0002), | ||
IEntryPoint_getSpecializationParamCount = makeApiCallId(Class_IEntryPoint, 0x0003), | ||
IEntryPoint_getEntryPointCode = makeApiCallId(Class_IEntryPoint, 0x0004), | ||
IEntryPoint_getResultAsFileSystem = makeApiCallId(Class_IEntryPoint, 0x0005), | ||
IEntryPoint_getEntryPointHash = makeApiCallId(Class_IEntryPoint, 0x0006), | ||
IEntryPoint_specialize = makeApiCallId(Class_IEntryPoint, 0x0007), | ||
IEntryPoint_link = makeApiCallId(Class_IEntryPoint, 0x0008), | ||
IEntryPoint_getEntryPointHostCallable = makeApiCallId(Class_IEntryPoint, 0x0009), | ||
IEntryPoint_renameEntryPoint = makeApiCallId(Class_IEntryPoint, 0x000A), | ||
IEntryPoint_linkWithOptions = makeApiCallId(Class_IEntryPoint, 0x000B), | ||
|
||
ICompositeComponentType_getSession = makeApiCallId(Class_ICompositeComponentType, 0x0001), | ||
ICompositeComponentType_getLayout = makeApiCallId(Class_ICompositeComponentType, 0x0002), | ||
ICompositeComponentType_getSpecializationParamCount = makeApiCallId(Class_ICompositeComponentType, 0x0003), | ||
ICompositeComponentType_getEntryPointCode = makeApiCallId(Class_ICompositeComponentType, 0x0004), | ||
ICompositeComponentType_getResultAsFileSystem = makeApiCallId(Class_ICompositeComponentType, 0x0005), | ||
ICompositeComponentType_getEntryPointHash = makeApiCallId(Class_ICompositeComponentType, 0x0006), | ||
ICompositeComponentType_specialize = makeApiCallId(Class_ICompositeComponentType, 0x0007), | ||
ICompositeComponentType_link = makeApiCallId(Class_ICompositeComponentType, 0x0008), | ||
ICompositeComponentType_getEntryPointHostCallable = makeApiCallId(Class_ICompositeComponentType, 0x0009), | ||
ICompositeComponentType_renameEntryPoint = makeApiCallId(Class_ICompositeComponentType, 0x000A), | ||
ICompositeComponentType_linkWithOptions = makeApiCallId(Class_ICompositeComponentType, 0x000B), | ||
|
||
ITypeConformance_getSession = makeApiCallId(Class_ITypeConformance, 0x0001), | ||
ITypeConformance_getLayout = makeApiCallId(Class_ITypeConformance, 0x0002), | ||
ITypeConformance_getSpecializationParamCount = makeApiCallId(Class_ITypeConformance, 0x0003), | ||
ITypeConformance_getEntryPointCode = makeApiCallId(Class_ITypeConformance, 0x0004), | ||
ITypeConformance_getResultAsFileSystem = makeApiCallId(Class_ITypeConformance, 0x0005), | ||
ITypeConformance_getEntryPointHash = makeApiCallId(Class_ITypeConformance, 0x0006), | ||
ITypeConformance_specialize = makeApiCallId(Class_ITypeConformance, 0x0007), | ||
ITypeConformance_link = makeApiCallId(Class_ITypeConformance, 0x0008), | ||
ITypeConformance_getEntryPointHostCallable = makeApiCallId(Class_ITypeConformance, 0x0009), | ||
ITypeConformance_renameEntryPoint = makeApiCallId(Class_ITypeConformance, 0x000A), | ||
ITypeConformance_linkWithOptions = makeApiCallId(Class_ITypeConformance, 0x000B) | ||
}; | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
|
||
#include <string> | ||
#include <sstream> | ||
#include <thread> | ||
#include "capture-manager.h" | ||
|
||
namespace SlangCapture | ||
{ | ||
CaptureManager::CaptureManager(uint64_t globalSessionHandle) | ||
: m_encoder(&m_memoryStream) | ||
{ | ||
std::stringstream ss; | ||
ss << "gs-"<< globalSessionHandle <<"t-"<<std::this_thread::get_id() << ".cap"; | ||
m_fileStream = std::make_unique<FileOutputStream>(ss.str()); | ||
} | ||
|
||
void CaptureManager::clearWithHeader(const ApiCallId& callId, uint64_t handleId) | ||
{ | ||
m_memoryStream.flush(); | ||
FunctionHeader header {}; | ||
header.callId = callId; | ||
header.handleId = handleId; | ||
|
||
// write header to memory stream | ||
m_memoryStream.write(&header, sizeof(FunctionHeader)); | ||
} | ||
|
||
ParameterEncoder* CaptureManager::beginMethodCapture(const ApiCallId& callId, uint64_t handleId) | ||
{ | ||
clearWithHeader(callId, handleId); | ||
return &m_encoder; | ||
} | ||
|
||
void CaptureManager::endMethodCapture() | ||
{ | ||
FunctionHeader* pHeader = const_cast<FunctionHeader*>( | ||
reinterpret_cast<const FunctionHeader*>(m_memoryStream.getData())); | ||
|
||
pHeader->dataSizeInBytes = m_memoryStream.getSizeInBytes() - sizeof(FunctionHeader); | ||
|
||
std::hash<std::thread::id> hasher; | ||
pHeader->threadId = hasher(std::this_thread::get_id()); | ||
|
||
// write capture data to file | ||
m_fileStream->write(m_memoryStream.getData(), m_memoryStream.getSizeInBytes()); | ||
|
||
// take effect of the write | ||
m_fileStream->flush(); | ||
|
||
// clear the memory stream | ||
m_memoryStream.flush(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#ifndef CAPTURE_MANAGER_H | ||
#define CAPTURE_MANAGER_H | ||
|
||
#include "parameter-encoder.h" | ||
#include "api_callId.h" | ||
namespace SlangCapture | ||
{ | ||
class CaptureManager | ||
{ | ||
public: | ||
CaptureManager(uint64_t globalSessionHandle); | ||
ParameterEncoder* beginMethodCapture(const ApiCallId& callId, uint64_t handleId); | ||
void endMethodCapture(); | ||
private: | ||
void clearWithHeader(const ApiCallId& callId, uint64_t handleId); | ||
|
||
struct FunctionHeader | ||
{ | ||
ApiCallId callId {InvalidCallId}; | ||
uint64_t handleId {0}; | ||
uint64_t dataSizeInBytes {0}; | ||
uint64_t threadId {0}; | ||
}; | ||
|
||
MemoryStream m_memoryStream; | ||
std::unique_ptr<FileOutputStream> m_fileStream; | ||
ParameterEncoder m_encoder; | ||
}; | ||
} // namespace SlangCapture | ||
#endif // CAPTURE_MANAGER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#include "output-stream.h" | ||
#include "capture_utility.h" | ||
|
||
namespace SlangCapture | ||
{ | ||
FileOutputStream::FileOutputStream(const std::string& filename, bool append) | ||
{ | ||
Slang::String path(filename.c_str()); | ||
Slang::FileMode fileMode = append ? Slang::FileMode::Append : Slang::FileMode::Create; | ||
Slang::FileAccess fileAccess = Slang::FileAccess::Write; | ||
Slang::FileShare fileShare = Slang::FileShare::None; | ||
|
||
SlangResult res = m_fileStream.init(path, fileMode, fileAccess, fileShare); | ||
|
||
if (res != SLANG_OK) | ||
{ | ||
SlangCapture::slangCaptureLog(SlangCapture::LogLevel::Error, "Failed to open file %s\n", filename.c_str()); | ||
std::abort(); | ||
} | ||
} | ||
|
||
FileOutputStream::~FileOutputStream() | ||
{ | ||
m_fileStream.close(); | ||
} | ||
|
||
void FileOutputStream::write(const void* data, size_t len) | ||
{ | ||
SLANG_CAPTURE_ASSERT(m_fileStream.write(data, len)); | ||
} | ||
|
||
MemoryStream::MemoryStream() | ||
: m_memoryStream(Slang::FileAccess::Write) | ||
{ } | ||
|
||
void FileOutputStream::flush() | ||
{ | ||
SLANG_CAPTURE_ASSERT(m_fileStream.flush()); | ||
} | ||
|
||
void MemoryStream::write(const void* data, size_t len) | ||
{ | ||
SLANG_CAPTURE_ASSERT(m_memoryStream.write(data, len)); | ||
} | ||
|
||
void MemoryStream::flush() | ||
{ | ||
// This call will reset the underlying buffer to size 0, | ||
// and reset the write position to 0. | ||
m_memoryStream.setContent(nullptr, 0); | ||
} | ||
} |
Oops, something went wrong.