diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2024-07-23 10:45:26 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-23 08:45:26 -0700 |
| commit | 986256ffb92ab7c8fc7cf9f2c424919a439a824f (patch) | |
| tree | 260e37bd439275e3398d16fe238b20cd00d08cb7 /source/slang-record-replay/record/slang-session.cpp | |
| parent | c28d8b6aec721fa3350fc52647f1572a353f6151 (diff) | |
Feature/capture (#4625)
* Add decoder
* Add a replay executable to consume the decoded content
Add file-processor.cpp/h where we implement the logic to process
the captured file block by block. Each block is:
function header + parameter buffer + function tailer + function
output[optional].
After reading one block, the block of data is sent to decoder module
to dispatch the corresponding API.
Add slang-decoder.cpp/h where we implement the logic to dispatch
the slang API according to the input block data.
- Rename api_callId.h to capture-format.h
- Renmae capture_utility.cpp to capture-utility.cpp
- Renmae capture_utility.h to capture-utility.h
- Change the #include file name accordingly.
* Reorganize source files structure
Move all the capture logic code into `capture` directory.
- the capture code will be build with slang dll.
Move all the replay logic code into `relay` directoy.
- the replay code is not part of slang dll, it will be built
as a stand alone binary and link against slang dll.
Change the #include file names accordingly.
Add tools/slang-replay/main.cpp for the slang-replay stand alone
binary place holder. Will implement it later.
Update premake5.lua accordingly.
* Update cmake files
Update cmake files to change the build process for
capture and relay system.
- capture component should be build with slang dll, so we
should not include replay component.
- replay component should be a separate executable tool, which
should not include capture component.
- In order to easy use our current cmake infrastructure, move
the shared files to a `util` folder
- change the header include path
* Redesgin the interfaces of consumers
Fix some issues in capture
Finish implementing all slang-decoder functions
* Fix the AppleClang build issue
* Address few comments
- Fix the weird indent issues.
- Correct the function name for CreateGlobalSession()
- Rename file-processor to captureFile-processor to be more specific.
- Use Slang::List instead of std::vector
* record/replay: name refactor change
Refactor the naming.
Change the name "encoder/capture" to "record".
Diffstat (limited to 'source/slang-record-replay/record/slang-session.cpp')
| -rw-r--r-- | source/slang-record-replay/record/slang-session.cpp | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/source/slang-record-replay/record/slang-session.cpp b/source/slang-record-replay/record/slang-session.cpp new file mode 100644 index 000000000..82c7a7479 --- /dev/null +++ b/source/slang-record-replay/record/slang-session.cpp @@ -0,0 +1,517 @@ +#include "../util/record-utility.h" +#include "slang-session.h" +#include "slang-entrypoint.h" +#include "slang-composite-component-type.h" +#include "slang-type-conformance.h" + +namespace SlangRecord +{ + + SessionRecorder::SessionRecorder(slang::ISession* session, RecordManager* recordManager) + : m_actualSession(session), + m_recordManager(recordManager) + { + SLANG_RECORD_ASSERT(m_actualSession); + SLANG_RECORD_ASSERT(m_recordManager); + m_sessionHandle = reinterpret_cast<uint64_t>(m_actualSession.get()); + slangRecordLog(LogLevel::Verbose, "%s: %p\n", "SessionRecorder create:", session); + } + + SessionRecorder::~SessionRecorder() + { + m_actualSession->release(); + } + + ISlangUnknown* SessionRecorder::getInterface(const Guid& guid) + { + if(guid == ISlangUnknown::getTypeGuid() || guid == ISession::getTypeGuid()) + return asExternal(this); + + return nullptr; + } + + SLANG_NO_THROW slang::IGlobalSession* SessionRecorder::getGlobalSession() + { + // No need to record this function. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + slang::IGlobalSession* pGlobalSession = m_actualSession->getGlobalSession(); + return pGlobalSession; + } + + SLANG_NO_THROW slang::IModule* SessionRecorder::loadModule( + const char* moduleName, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_loadModule, m_sessionHandle); + recorder->recordString(moduleName); + recorder = m_recordManager->endMethodRecord(); + } + + slang::IModule* pModule = m_actualSession->loadModule(moduleName, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(pModule); + m_recordManager->endMethodRecordAppendOutput(); + } + + ModuleRecorder* pModuleRecorder = getModuleRecorder(pModule); + return static_cast<slang::IModule*>(pModuleRecorder); + } + + SLANG_NO_THROW slang::IModule* SessionRecorder::loadModuleFromIRBlob( + const char* moduleName, + const char* path, + slang::IBlob* source, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_loadModuleFromIRBlob, m_sessionHandle); + recorder->recordString(moduleName); + recorder->recordString(path); + recorder->recordPointer(source); + recorder = m_recordManager->endMethodRecord(); + } + + slang::IModule* pModule = m_actualSession->loadModuleFromIRBlob(moduleName, path, source, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(pModule); + m_recordManager->endMethodRecordAppendOutput(); + } + + ModuleRecorder* pModuleRecorder = getModuleRecorder(pModule); + return static_cast<slang::IModule*>(pModuleRecorder); + } + + SLANG_NO_THROW slang::IModule* SessionRecorder::loadModuleFromSource( + const char* moduleName, + const char* path, + slang::IBlob* source, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_loadModuleFromSource, m_sessionHandle); + recorder->recordString(moduleName); + recorder->recordString(path); + recorder->recordPointer(source); + recorder = m_recordManager->endMethodRecord(); + } + + slang::IModule* pModule = m_actualSession->loadModuleFromSource(moduleName, path, source, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(pModule); + m_recordManager->endMethodRecordAppendOutput(); + } + + ModuleRecorder* pModuleRecorder = getModuleRecorder(pModule); + return static_cast<slang::IModule*>(pModuleRecorder); + } + + SLANG_NO_THROW slang::IModule* SessionRecorder::loadModuleFromSourceString( + const char* moduleName, + const char* path, + const char* string, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_loadModuleFromSourceString, m_sessionHandle); + recorder->recordString(moduleName); + recorder->recordString(path); + recorder->recordString(string); + recorder = m_recordManager->endMethodRecord(); + } + + slang::IModule* pModule = m_actualSession->loadModuleFromSourceString(moduleName, path, string, outDiagnostics); + + { + // TODO: Not sure if we need to record the diagnostics blob. + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(pModule); + m_recordManager->endMethodRecordAppendOutput(); + } + + ModuleRecorder* pModuleRecorder = getModuleRecorder(pModule); + return static_cast<slang::IModule*>(pModuleRecorder); + } + + SLANG_NO_THROW SlangResult SessionRecorder::createCompositeComponentType( + slang::IComponentType* const* componentTypes, + SlangInt componentTypeCount, + slang::IComponentType** outCompositeComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + Slang::List<slang::IComponentType*> componentTypeList; + + // get the actual component types from our record wrappers + if(SLANG_OK != getActualComponentTypes(componentTypes, componentTypeCount, componentTypeList)) + { + SLANG_RECORD_ASSERT(!"Failed to get actual component types"); + } + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_createCompositeComponentType, m_sessionHandle); + recorder->recordAddressArray(componentTypeList.getBuffer(), componentTypeCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult result = m_actualSession->createCompositeComponentType( + componentTypeList.getBuffer(), componentTypeCount, outCompositeComponentType, outDiagnostics); + + { + recorder->recordAddress(*outCompositeComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + if (SLANG_OK == result) + { + CompositeComponentTypeRecorder* compositeComponentTypeRecord = + new CompositeComponentTypeRecorder(*outCompositeComponentType, m_recordManager); + Slang::ComPtr<CompositeComponentTypeRecorder> resultRecord(compositeComponentTypeRecord); + *outCompositeComponentType = resultRecord.detach(); + } + + return result; + } + + SLANG_NO_THROW slang::TypeReflection* SessionRecorder::specializeType( + slang::TypeReflection* type, + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_specializeType, m_sessionHandle); + recorder->recordAddress(type); + recorder->recordStructArray(specializationArgs, specializationArgCount); + recorder = m_recordManager->endMethodRecord(); + } + + slang::TypeReflection* pTypeReflection = m_actualSession->specializeType(type, specializationArgs, specializationArgCount, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(pTypeReflection); + m_recordManager->endMethodRecordAppendOutput(); + } + + return pTypeReflection; + } + + SLANG_NO_THROW slang::TypeLayoutReflection* SessionRecorder::getTypeLayout( + slang::TypeReflection* type, + SlangInt targetIndex, + slang::LayoutRules rules, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_getTypeLayout, m_sessionHandle); + recorder->recordAddress(type); + recorder->recordInt64(targetIndex); + recorder->recordEnumValue(rules); + recorder = m_recordManager->endMethodRecord(); + } + + slang::TypeLayoutReflection* pTypeLayoutReflection = m_actualSession->getTypeLayout(type, targetIndex, rules, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(pTypeLayoutReflection); + m_recordManager->endMethodRecordAppendOutput(); + } + + return pTypeLayoutReflection; + } + + SLANG_NO_THROW slang::TypeReflection* SessionRecorder::getContainerType( + slang::TypeReflection* elementType, + slang::ContainerType containerType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_getContainerType, m_sessionHandle); + recorder->recordAddress(elementType); + recorder->recordEnumValue(containerType); + recorder = m_recordManager->endMethodRecord(); + } + + slang::TypeReflection* pTypeReflection = m_actualSession->getContainerType(elementType, containerType, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(pTypeReflection); + m_recordManager->endMethodRecordAppendOutput(); + } + + return pTypeReflection; + } + + SLANG_NO_THROW slang::TypeReflection* SessionRecorder::getDynamicType() + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_getDynamicType, m_sessionHandle); + recorder = m_recordManager->endMethodRecord(); + } + + slang::TypeReflection* pTypeReflection = m_actualSession->getDynamicType(); + + { + recorder->recordAddress(pTypeReflection); + m_recordManager->endMethodRecordAppendOutput(); + } + + return pTypeReflection; + } + + SLANG_NO_THROW SlangResult SessionRecorder::getTypeRTTIMangledName( + slang::TypeReflection* type, + ISlangBlob** outNameBlob) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_getTypeRTTIMangledName, m_sessionHandle); + recorder->recordAddress(type); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult result = m_actualSession->getTypeRTTIMangledName(type, outNameBlob); + + { + recorder->recordAddress(outNameBlob); + m_recordManager->endMethodRecordAppendOutput(); + } + + return result; + } + + SLANG_NO_THROW SlangResult SessionRecorder::getTypeConformanceWitnessMangledName( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + ISlangBlob** outNameBlob) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_getTypeConformanceWitnessMangledName, m_sessionHandle); + recorder->recordAddress(type); + recorder->recordAddress(interfaceType); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult result = m_actualSession->getTypeConformanceWitnessMangledName(type, interfaceType, outNameBlob); + + { + recorder->recordAddress(outNameBlob); + m_recordManager->endMethodRecordAppendOutput(); + } + + return result; + } + + SLANG_NO_THROW SlangResult SessionRecorder::getTypeConformanceWitnessSequentialID( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + uint32_t* outId) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_getTypeConformanceWitnessSequentialID, m_sessionHandle); + recorder->recordAddress(type); + recorder->recordAddress(interfaceType); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult result = m_actualSession->getTypeConformanceWitnessSequentialID(type, interfaceType, outId); + + // No need to record outId, it's not slang allocation + return result; + } + + SLANG_NO_THROW SlangResult SessionRecorder::createTypeConformanceComponentType( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + slang::ITypeConformance** outConformance, + SlangInt conformanceIdOverride, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_createTypeConformanceComponentType, m_sessionHandle); + recorder->recordAddress(type); + recorder->recordAddress(interfaceType); + recorder->recordInt64(conformanceIdOverride); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult result = m_actualSession->createTypeConformanceComponentType(type, interfaceType, outConformance, conformanceIdOverride, outDiagnostics); + + { + recorder->recordAddress(*outConformance); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + if (SLANG_OK != result) + { + TypeConformanceRecorder* conformanceRecord = new TypeConformanceRecorder(*outConformance, m_recordManager); + Slang::ComPtr<TypeConformanceRecorder> resultRecord(conformanceRecord); + *outConformance = resultRecord.detach(); + } + + return result; + } + + SLANG_NO_THROW SlangResult SessionRecorder::createCompileRequest( + SlangCompileRequest** outCompileRequest) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_createCompileRequest, m_sessionHandle); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult result = m_actualSession->createCompileRequest(outCompileRequest); + + { + recorder->recordAddress(*outCompileRequest); + m_recordManager->endMethodRecordAppendOutput(); + } + + return result; + } + + SLANG_NO_THROW SlangInt SessionRecorder::getLoadedModuleCount() + { + // No need to record this function, it's just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + SlangInt count = m_actualSession->getLoadedModuleCount(); + return count; + } + + SLANG_NO_THROW slang::IModule* SessionRecorder::getLoadedModule(SlangInt index) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ISession_getLoadedModule, m_sessionHandle); + recorder->recordInt64(index); + recorder = m_recordManager->endMethodRecord(); + } + + slang::IModule* pModule = m_actualSession->getLoadedModule(index); + + { + recorder->recordAddress(pModule); + m_recordManager->endMethodRecordAppendOutput(); + } + + if (pModule) + { + ModuleRecorder* moduleRecord = m_mapModuleToRecord.tryGetValue(pModule); + if (!moduleRecord) + { + SLANG_RECORD_ASSERT(!"Module not found in mapModuleToRecord"); + } + return static_cast<slang::IModule*>(moduleRecord); + } + + return pModule; + } + + SLANG_NO_THROW bool SessionRecorder::isBinaryModuleUpToDate(const char* modulePath, slang::IBlob* binaryModuleBlob) + { + // No need to record this function, it's a query function and doesn't impact slang internal state. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + bool result = m_actualSession->isBinaryModuleUpToDate(modulePath, binaryModuleBlob); + return result; + } + + ModuleRecorder* SessionRecorder::getModuleRecorder(slang::IModule* module) + { + ModuleRecorder* moduleRecord = nullptr; + moduleRecord = m_mapModuleToRecord.tryGetValue(module); + if (!moduleRecord) + { + moduleRecord = new ModuleRecorder(module, m_recordManager); + Slang::ComPtr<ModuleRecorder> result(moduleRecord); + m_mapModuleToRecord.add(module, *result.detach()); + } + return moduleRecord; + } + + SlangResult SessionRecorder::getActualComponentTypes( + slang::IComponentType* const* componentTypes, + SlangInt componentTypeCount, + List<slang::IComponentType*>& outActualComponentTypes) + { + for (SlangInt i = 0; i < componentTypeCount; i++) + { + slang::IComponentType* const& componentType = componentTypes[i]; + void* outObj = nullptr; + + if (componentType->queryInterface(ModuleRecorder::getTypeGuid(), &outObj) == SLANG_OK) + { + ModuleRecorder* moduleRecord = static_cast<ModuleRecorder*>(outObj); + outActualComponentTypes.add(moduleRecord->getActualModule()); + } + else if (componentType->queryInterface(EntryPointRecorder::getTypeGuid(), &outObj) == SLANG_OK) + { + EntryPointRecorder* entrypointRecord = static_cast<EntryPointRecorder*>(outObj); + outActualComponentTypes.add(entrypointRecord->getActualEntryPoint()); + } + // will fall back to the actual component type, it means that we didn't record this type. + else + { + outActualComponentTypes.add(componentType); + } + } + + if (componentTypeCount == outActualComponentTypes.getCount()) + { + return SLANG_OK; + } + return SLANG_FAIL; + } +} // namespace SlangRecord |
