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 | |
| 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')
37 files changed, 8168 insertions, 0 deletions
diff --git a/source/slang-record-replay/record/output-stream.cpp b/source/slang-record-replay/record/output-stream.cpp new file mode 100644 index 000000000..8575d19d0 --- /dev/null +++ b/source/slang-record-replay/record/output-stream.cpp @@ -0,0 +1,52 @@ +#include "output-stream.h" +#include "../util/record-utility.h" + +namespace SlangRecord +{ + 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) + { + SlangRecord::slangRecordLog(SlangRecord::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_RECORD_CHECK(m_fileStream.write(data, len)); + } + + MemoryStream::MemoryStream() + : m_memoryStream(Slang::FileAccess::Write) + { } + + void FileOutputStream::flush() + { + SLANG_RECORD_CHECK(m_fileStream.flush()); + } + + void MemoryStream::write(const void* data, size_t len) + { + SLANG_RECORD_CHECK(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); + } +} diff --git a/source/slang-record-replay/record/output-stream.h b/source/slang-record-replay/record/output-stream.h new file mode 100644 index 000000000..770c2aeac --- /dev/null +++ b/source/slang-record-replay/record/output-stream.h @@ -0,0 +1,46 @@ +#ifndef OUTPUT_STREAM_H +#define OUTPUT_STREAM_H + +#include <string> +#include "../../core/slang-stream.h" + +namespace SlangRecord +{ + class OutputStream + { + public: + virtual ~OutputStream() {} + virtual void write(const void* data, size_t len) = 0; + virtual void flush() {} + }; + + class FileOutputStream : public OutputStream + { + public: + FileOutputStream(const std::string& filename, bool append = false); + virtual ~FileOutputStream() override; + virtual void write(const void* data, size_t len) override; + virtual void flush() override; + + private: + Slang::FileStream m_fileStream; + }; + + // The reason we inherit from OwnedMemoryStream instead of declaring it + // as a member is because OwnedMemoryStream lacks some of the functionality + // of operating on the underlying buffer directly. + class MemoryStream : public OutputStream + { + public: + MemoryStream(); + virtual ~MemoryStream() { } + virtual void write(const void* data, size_t len) override; + virtual void flush() override; + const void* getData() { return m_memoryStream.getContents().getBuffer(); } + size_t getSizeInBytes() { return m_memoryStream.getContents().getCount(); } + + private: + Slang::OwnedMemoryStream m_memoryStream; + }; +} // namespace SlangRecord +#endif // OUTPUT_STREAM_H diff --git a/source/slang-record-replay/record/parameter-recorder.cpp b/source/slang-record-replay/record/parameter-recorder.cpp new file mode 100644 index 000000000..1c2fd9609 --- /dev/null +++ b/source/slang-record-replay/record/parameter-recorder.cpp @@ -0,0 +1,123 @@ +#include "parameter-recorder.h" + +namespace SlangRecord +{ + void ParameterRecorder::recordStruct(slang::SessionDesc const& desc) + { + recordUint64(desc.structureSize); + recordInt64(desc.targetCount); + + for (SlangInt i = 0; i < desc.targetCount; i++) + { + recordStruct(desc.targets[i]); + } + + recordUint32(desc.flags); + recordEnumValue(desc.defaultMatrixLayoutMode); + recordInt64(desc.searchPathCount); + for (SlangInt i = 0; i < desc.searchPathCount; i++) + { + recordString(desc.searchPaths[i]); + } + + recordInt64(desc.preprocessorMacroCount); + for (SlangInt i = 0; i < desc.preprocessorMacroCount; i++) + { + recordStruct(desc.preprocessorMacros[i]); + } + + recordBool(desc.enableEffectAnnotations); + recordBool(desc.allowGLSLSyntax); + + recordUint32(desc.compilerOptionEntryCount); + for (uint32_t i = 0; i < desc.compilerOptionEntryCount; i++) + { + recordStruct(desc.compilerOptionEntries[i]); + } + } + + void ParameterRecorder::recordStruct(slang::PreprocessorMacroDesc const& desc) + { + recordString(desc.name); + recordString(desc.value); + } + + void ParameterRecorder::recordStruct(slang::CompilerOptionEntry const& entry) + { + recordEnumValue(entry.name); + recordStruct(entry.value); + } + + void ParameterRecorder::recordStruct(slang::CompilerOptionValue const& value) + { + recordEnumValue(value.kind); + recordInt32(value.intValue0); + recordString(value.stringValue0); + recordString(value.stringValue1); + } + + void ParameterRecorder::recordStruct(slang::TargetDesc const& targetDesc) + { + recordUint64(targetDesc.structureSize); + recordEnumValue(targetDesc.format); + recordEnumValue(targetDesc.profile); + recordEnumValue(targetDesc.flags); + recordEnumValue(targetDesc.floatingPointMode); + recordEnumValue(targetDesc.lineDirectiveMode); + recordBool(targetDesc.forceGLSLScalarBufferLayout); + recordUint32(targetDesc.compilerOptionEntryCount); + for (uint32_t i = 0; i < targetDesc.compilerOptionEntryCount; i++) + { + recordStruct(targetDesc.compilerOptionEntries[i]); + } + } + + void ParameterRecorder::recordStruct(slang::SpecializationArg const& specializationArg) + { + recordEnumValue(specializationArg.kind); + recordAddress(specializationArg.type); + } + + void ParameterRecorder::recordPointer(const void* value, bool omitData, size_t size) + { + recordAddress(value); + if (omitData) + { + recordUint64(0llu); + return; + } + + recordUint64(size); + if (size) + { + m_stream->write(value, size); + } + } + + void ParameterRecorder::recordPointer(ISlangBlob* blob) + { + recordAddress(static_cast<const void*>(blob)); + + if (blob) + { + size_t size = blob->getBufferSize(); + const void* buffer = blob->getBufferPointer(); + recordPointer(buffer, false, size); + } + } + + // first 4-bytes is the length of the string + void ParameterRecorder::recordString(const char* value) + { + if (value == nullptr) + { + recordUint32(0); + } + else + { + uint32_t size = (uint32_t)strlen(value); + recordUint32(size); + m_stream->write(value, size); + } + } +} diff --git a/source/slang-record-replay/record/parameter-recorder.h b/source/slang-record-replay/record/parameter-recorder.h new file mode 100644 index 000000000..29bf39fb3 --- /dev/null +++ b/source/slang-record-replay/record/parameter-recorder.h @@ -0,0 +1,94 @@ +#ifndef PARAMETER_ENCODER_H +#define PARAMETER_ENCODER_H + +#include <cstdio> +#include <cinttypes> +#include <cstdint> + +#include "output-stream.h" +#include "../util/record-format.h" + +namespace SlangRecord +{ + class ParameterRecorder + { + public: + ParameterRecorder(OutputStream* stream) : m_stream(stream) {}; + void recordInt8(int8_t value) { recordValue(value); } + void recordUint8(uint8_t value) { recordValue(value); } + void recordInt16(int16_t value) { recordValue(value); } + void recordUint16(uint16_t value) { recordValue(value); } + void recordInt32(int32_t value) { recordValue(value); } + void recordUint32(uint32_t value) { recordValue(value); } + void recordInt64(int64_t value) { recordValue(value); } + void recordUint64(uint64_t value) { recordValue(value); } + void recordFloat(float value) { recordValue(value); } + void recordDouble(double value) { recordValue(value); } + void recordBool(bool value) { recordValue(value); } + + template<typename T> + void recordEnumValue(T value) { recordValue(static_cast<uint32_t>(value)); } + + void recordString(const char* value); + void recordPointer(const void* value, bool omitData = false, size_t size = 0); + void recordPointer(ISlangBlob* blob); + void recordAddress(const void* value) { recordValue(reinterpret_cast<SlangRecord::AddressFormat>(value)); } + + void recordStruct(slang::SessionDesc const& desc); + void recordStruct(slang::PreprocessorMacroDesc const& desc); + void recordStruct(slang::CompilerOptionEntry const& entry); + void recordStruct(slang::CompilerOptionValue const& value); + void recordStruct(slang::TargetDesc const& targetDesc); + void recordStruct(slang::SpecializationArg const& specializationArg); + + template <typename T> + void recordValueArray(const T* array, size_t count) + { + recordUint32((uint32_t)count); + for (size_t i = 0; i < count; ++i) + { + recordValue(array[i]); + } + } + + void recordStringArray(const char* const* array, size_t count) + { + recordUint32((uint32_t)count); + for (size_t i = 0; i < count; ++i) + { + recordString(array[i]); + } + } + + template <typename T> + void recordStructArray(T const* array, size_t count) + { + recordUint32((uint32_t)count); + for (size_t i = 0; i < count; ++i) + { + recordStruct(array[i]); + } + } + + template <typename T> + void recordAddressArray(T* const* array, size_t count) + { + recordUint32((uint32_t)count); + for (size_t i = 0; i < count; ++i) + { + recordAddress(array[i]); + } + } + + + private: + template <typename T> + void recordValue(T value) + { + m_stream->write(&value, sizeof(T)); + } + OutputStream* m_stream; + }; +} // namespace SlangRecord + +#endif // PARAMETER_ENCODER_H diff --git a/source/slang-record-replay/record/record-manager.cpp b/source/slang-record-replay/record/record-manager.cpp new file mode 100644 index 000000000..f10d2c704 --- /dev/null +++ b/source/slang-record-replay/record/record-manager.cpp @@ -0,0 +1,97 @@ + +#include <string> +#include <sstream> +#include <thread> +#include "../util/record-utility.h" +#include "record-manager.h" + +namespace SlangRecord +{ + RecordManager::RecordManager(uint64_t globalSessionHandle) + : m_recorder(&m_memoryStream) + { + std::stringstream ss; + ss << "gs-"<< globalSessionHandle <<"-t-"<<std::this_thread::get_id() << ".cap"; + + m_recordFileDirectory = m_recordFileDirectory / "slang-record"; + + if (!std::filesystem::exists(m_recordFileDirectory)) + { + std::error_code ec; + if (!std::filesystem::create_directory(m_recordFileDirectory, ec)) + { + slangRecordLog(LogLevel::Error, "Fail to create directory: %s, error (%d): %s\n", + m_recordFileDirectory.string().c_str(), ec.value(), ec.message().c_str()); + } + } + + std::filesystem::path recordFilePath = m_recordFileDirectory / ss.str(); + m_fileStream = std::make_unique<FileOutputStream>(recordFilePath.string()); + } + + void RecordManager::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)); + } + + void RecordManager::clearWithTailer() + { + m_memoryStream.flush(); + FunctionTailer tailer; + + // write header to memory stream + m_memoryStream.write(&tailer, sizeof(FunctionTailer)); + } + + ParameterRecorder* RecordManager::beginMethodRecord(const ApiCallId& callId, uint64_t handleId) + { + clearWithHeader(callId, handleId); + return &m_recorder; + } + + ParameterRecorder* RecordManager::endMethodRecord() + { + 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 record 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(); + + clearWithTailer(); + return &m_recorder; + } + + void RecordManager::endMethodRecordAppendOutput() + { + FunctionTailer* pTailer = const_cast<FunctionTailer*>( + reinterpret_cast<const FunctionTailer*>(m_memoryStream.getData())); + + pTailer->dataSizeInBytes = (uint32_t)(m_memoryStream.getSizeInBytes() - sizeof(FunctionTailer)); + + // write record 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(); + } +} diff --git a/source/slang-record-replay/record/record-manager.h b/source/slang-record-replay/record/record-manager.h new file mode 100644 index 000000000..40992e8ad --- /dev/null +++ b/source/slang-record-replay/record/record-manager.h @@ -0,0 +1,35 @@ +#ifndef RECORD_MANAGER_H +#define RECORD_MANAGER_H + +#include <filesystem> +#include "parameter-recorder.h" +#include "../util/record-format.h" + +namespace SlangRecord +{ + class RecordManager + { + public: + RecordManager(uint64_t globalSessionHandle); + + // Each method record has to start with a FunctionHeader + ParameterRecorder* beginMethodRecord(const ApiCallId& callId, uint64_t handleId); + ParameterRecorder* endMethodRecord(); + + // endMethodRecordAppendOutput is an optional call that can be used to append output to + // the end of the record. It has to start with a FunctionTailer + void endMethodRecordAppendOutput(); + + std::filesystem::path const& getRecordFileDirectory() const { return m_recordFileDirectory; } + + private: + void clearWithHeader(const ApiCallId& callId, uint64_t handleId); + void clearWithTailer(); + + MemoryStream m_memoryStream; + std::unique_ptr<FileOutputStream> m_fileStream; + std::filesystem::path m_recordFileDirectory = std::filesystem::current_path(); + ParameterRecorder m_recorder; + }; +} // namespace SlangRecord +#endif // RECORD_MANAGER_H diff --git a/source/slang-record-replay/record/slang-composite-component-type.cpp b/source/slang-record-replay/record/slang-composite-component-type.cpp new file mode 100644 index 000000000..ef594a893 --- /dev/null +++ b/source/slang-record-replay/record/slang-composite-component-type.cpp @@ -0,0 +1,309 @@ +#include "../util/record-utility.h" +#include "slang-composite-component-type.h" + +namespace SlangRecord +{ + CompositeComponentTypeRecorder::CompositeComponentTypeRecorder( + slang::IComponentType* componentType, RecordManager* recordManager) + : m_actualCompositeComponentType(componentType), + m_recordManager(recordManager) + { + SLANG_RECORD_ASSERT(m_actualCompositeComponentType != nullptr); + SLANG_RECORD_ASSERT(m_recordManager != nullptr); + + m_compositeComponentHandle = reinterpret_cast<uint64_t>(m_actualCompositeComponentType.get()); + slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, componentType); + } + + CompositeComponentTypeRecorder::~CompositeComponentTypeRecorder() + { + m_actualCompositeComponentType->release(); + } + + ISlangUnknown* CompositeComponentTypeRecorder::getInterface(const Guid& guid) + { + if (guid == IComponentType::getTypeGuid()) + { + return static_cast<ISlangUnknown*>(this); + } + return nullptr; + } + + SLANG_NO_THROW slang::ISession* CompositeComponentTypeRecorder::getSession() + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getSession, m_compositeComponentHandle); + recorder = m_recordManager->endMethodRecord(); + } + + slang::ISession* res = m_actualCompositeComponentType->getSession(); + + { + recorder->recordAddress(res); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW slang::ProgramLayout* CompositeComponentTypeRecorder::getLayout( + SlangInt targetIndex, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getLayout, m_compositeComponentHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + slang::ProgramLayout* programLayout = m_actualCompositeComponentType->getLayout(targetIndex, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(programLayout); + m_recordManager->endMethodRecordAppendOutput(); + } + + return programLayout; + } + + SLANG_NO_THROW SlangInt CompositeComponentTypeRecorder::getSpecializationParamCount() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + SlangInt res = m_actualCompositeComponentType->getSpecializationParamCount(); + return res; + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getEntryPointCode, m_compositeComponentHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getTargetCode, m_compositeComponentHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->getTargetCode(targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getResultAsFileSystem, m_compositeComponentHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->getResultAsFileSystem(entryPointIndex, targetIndex, outFileSystem); + + { + recorder->recordAddress(*outFileSystem); + } + + // TODO: We might need to wrap the file system object. + return res; + } + + SLANG_NO_THROW void CompositeComponentTypeRecorder::getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getEntryPointHash, m_compositeComponentHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualCompositeComponentType->getEntryPointHash(entryPointIndex, targetIndex, outHash); + + { + recorder->recordAddress(*outHash); + m_recordManager->endMethodRecordAppendOutput(); + } + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_specialize, m_compositeComponentHandle); + recorder->recordInt64(specializationArgCount); + recorder->recordStructArray(specializationArgs, specializationArgCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->specialize(specializationArgs, specializationArgCount, outSpecializedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outSpecializedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::link( + slang::IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_link, m_compositeComponentHandle); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->link(outLinkedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getEntryPointHostCallable, m_compositeComponentHandle); + recorder->recordInt32(entryPointIndex); + recorder->recordInt32(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->getEntryPointHostCallable(entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); + + { + recorder->recordAddress(*outSharedLibrary); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_renameEntryPoint, m_compositeComponentHandle); + recorder->recordString(newName); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->renameEntryPoint(newName, outEntryPoint); + + { + recorder->recordAddress(*outEntryPoint); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult CompositeComponentTypeRecorder::linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_linkWithOptions, m_compositeComponentHandle); + recorder->recordUint32(compilerOptionEntryCount); + recorder->recordStructArray(compilerOptionEntries, compilerOptionEntryCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualCompositeComponentType->linkWithOptions(outLinkedComponentType, compilerOptionEntryCount, compilerOptionEntries, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } +} diff --git a/source/slang-record-replay/record/slang-composite-component-type.h b/source/slang-record-replay/record/slang-composite-component-type.h new file mode 100644 index 000000000..758a59434 --- /dev/null +++ b/source/slang-record-replay/record/slang-composite-component-type.h @@ -0,0 +1,76 @@ +#ifndef SLANG_COMPOSITE_COMPONENT_TYPE_H +#define SLANG_COMPOSITE_COMPONENT_TYPE_H + +#include "slang-com-ptr.h" +#include "slang.h" +#include "slang-com-helper.h" +#include "../../core/slang-smart-pointer.h" +#include "../../core/slang-dictionary.h" +#include "../../slang/slang-compiler.h" +#include "record-manager.h" + +namespace SlangRecord +{ + using namespace Slang; + class CompositeComponentTypeRecorder: public slang::IComponentType, public RefObject + { + public: + SLANG_REF_OBJECT_IUNKNOWN_ALL + ISlangUnknown* getInterface(const Guid& guid); + + explicit CompositeComponentTypeRecorder(slang::IComponentType* componentType, RecordManager* recordManager); + ~CompositeComponentTypeRecorder(); + + // Interfaces for `IComponentType` + virtual SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() override; + virtual SLANG_NO_THROW slang::ProgramLayout* SLANG_MCALL getLayout( + SlangInt targetIndex = 0, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangInt SLANG_MCALL getSpecializationParamCount() override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) override; + virtual SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL link( + slang::IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics = 0) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + + slang::IComponentType* getActualCompositeComponentType() const { return m_actualCompositeComponentType; } + private: + Slang::ComPtr<slang::IComponentType> m_actualCompositeComponentType; + uint64_t m_compositeComponentHandle = 0; + RecordManager* m_recordManager = nullptr; + + }; +} +#endif // SLANG_COMPOSITE_COMPONENT_TYPE_H diff --git a/source/slang-record-replay/record/slang-entrypoint.cpp b/source/slang-record-replay/record/slang-entrypoint.cpp new file mode 100644 index 000000000..d3bf3b47e --- /dev/null +++ b/source/slang-record-replay/record/slang-entrypoint.cpp @@ -0,0 +1,313 @@ +#include "../util/record-utility.h" +#include "slang-entrypoint.h" + +namespace SlangRecord +{ + EntryPointRecorder::EntryPointRecorder(slang::IEntryPoint* entryPoint, RecordManager* recordManager) + : m_actualEntryPoint(entryPoint), + m_recordManager(recordManager) + { + SLANG_RECORD_ASSERT(m_actualEntryPoint != nullptr); + SLANG_RECORD_ASSERT(m_recordManager != nullptr); + + m_entryPointHandle = reinterpret_cast<uint64_t>(m_actualEntryPoint.get()); + slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, entryPoint); + } + + EntryPointRecorder::~EntryPointRecorder() + { + m_actualEntryPoint->release(); + } + + ISlangUnknown* EntryPointRecorder::getInterface(const Guid& guid) + { + if(guid == EntryPointRecorder::getTypeGuid()) + return static_cast<ISlangUnknown*>(this); + else + return nullptr; + } + + SLANG_NO_THROW slang::ISession* EntryPointRecorder::getSession() + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_getSession, m_entryPointHandle); + recorder = m_recordManager->endMethodRecord(); + } + + slang::ISession* session = m_actualEntryPoint->getSession(); + + { + recorder->recordAddress(session); + m_recordManager->endMethodRecordAppendOutput(); + } + + return session; + } + + SLANG_NO_THROW slang::ProgramLayout* EntryPointRecorder::getLayout( + SlangInt targetIndex, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_getLayout, m_entryPointHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + slang::ProgramLayout* programLayout = m_actualEntryPoint->getLayout(targetIndex, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(programLayout); + m_recordManager->endMethodRecordAppendOutput(); + } + + return programLayout; + } + + SLANG_NO_THROW SlangInt EntryPointRecorder::getSpecializationParamCount() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + SlangInt res = m_actualEntryPoint->getSpecializationParamCount(); + return res; + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_getEntryPointCode, m_entryPointHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_getTargetCode, m_entryPointHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->getTargetCode(targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_getResultAsFileSystem, m_entryPointHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->getResultAsFileSystem(entryPointIndex, targetIndex, outFileSystem); + + { + recorder->recordAddress(*outFileSystem); + } + + // TODO: We might need to wrap the file system object. + return res; + } + + SLANG_NO_THROW void EntryPointRecorder::getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_getEntryPointHash, m_entryPointHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualEntryPoint->getEntryPointHash(entryPointIndex, targetIndex, outHash); + + { + recorder->recordAddress(*outHash); + m_recordManager->endMethodRecordAppendOutput(); + } + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_specialize, m_entryPointHandle); + recorder->recordInt64(specializationArgCount); + recorder->recordStructArray(specializationArgs, specializationArgCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->specialize(specializationArgs, specializationArgCount, outSpecializedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outSpecializedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::link( + slang::IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_link, m_entryPointHandle); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->link(outLinkedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_getEntryPointHostCallable, m_entryPointHandle); + recorder->recordInt32(entryPointIndex); + recorder->recordInt32(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->getEntryPointHostCallable(entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); + + { + recorder->recordAddress(*outSharedLibrary); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_renameEntryPoint, m_entryPointHandle); + recorder->recordString(newName); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->renameEntryPoint(newName, outEntryPoint); + + { + recorder->recordAddress(*outEntryPoint); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult EntryPointRecorder::linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IEntryPoint_linkWithOptions, m_entryPointHandle); + recorder->recordUint32(compilerOptionEntryCount); + recorder->recordStructArray(compilerOptionEntries, compilerOptionEntryCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualEntryPoint->linkWithOptions(outLinkedComponentType, compilerOptionEntryCount, compilerOptionEntries, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW slang::FunctionReflection* EntryPointRecorder::getFunctionReflection() + { + return m_actualEntryPoint->getFunctionReflection(); + } + +} diff --git a/source/slang-record-replay/record/slang-entrypoint.h b/source/slang-record-replay/record/slang-entrypoint.h new file mode 100644 index 000000000..17c6fab6f --- /dev/null +++ b/source/slang-record-replay/record/slang-entrypoint.h @@ -0,0 +1,77 @@ +#ifndef SLANG_ENTRY_POINT_H +#define SLANG_ENTRY_POINT_H + +#include "slang-com-ptr.h" +#include "slang.h" +#include "slang-com-helper.h" +#include "../../core/slang-smart-pointer.h" +#include "../../core/slang-dictionary.h" +#include "../../slang/slang-compiler.h" +#include "record-manager.h" + +namespace SlangRecord +{ + using namespace Slang; + class EntryPointRecorder : public slang::IEntryPoint, public RefObject + { + public: + SLANG_COM_INTERFACE(0xf4c1e23d, 0xb321, 0x4931, { 0x8f, 0x37, 0xf1, 0x22, 0x6a, 0xf9, 0x20, 0x85 }) + + SLANG_REF_OBJECT_IUNKNOWN_ALL + ISlangUnknown* getInterface(const Guid& guid); + + explicit EntryPointRecorder(slang::IEntryPoint* entryPoint, RecordManager* recordManager); + ~EntryPointRecorder(); + + // Interfaces for `IComponentType` + virtual SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() override; + virtual SLANG_NO_THROW slang::ProgramLayout* SLANG_MCALL getLayout( + SlangInt targetIndex = 0, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangInt SLANG_MCALL getSpecializationParamCount() override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) override; + virtual SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL link( + slang::IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics = 0) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW slang::FunctionReflection* SLANG_MCALL getFunctionReflection() override; + slang::IEntryPoint* getActualEntryPoint() const { return m_actualEntryPoint; } + private: + Slang::ComPtr<slang::IEntryPoint> m_actualEntryPoint; + uint64_t m_entryPointHandle = 0; + RecordManager* m_recordManager = nullptr; + }; +} +#endif // SLANG_ENTRY_POINT_H diff --git a/source/slang-record-replay/record/slang-filesystem.cpp b/source/slang-record-replay/record/slang-filesystem.cpp new file mode 100644 index 000000000..1187a9aa6 --- /dev/null +++ b/source/slang-record-replay/record/slang-filesystem.cpp @@ -0,0 +1,124 @@ +#include "slang-filesystem.h" +#include "../util/record-utility.h" +#include "output-stream.h" + +namespace SlangRecord +{ + // We don't actually need to record the methods of ISlangFileSystemExt, we just want to record the file content + // and save them into disk. + FileSystemRecorder::FileSystemRecorder(ISlangFileSystemExt* fileSystem, RecordManager* recordManager) + : m_actualFileSystem(fileSystem), + m_recordManager(recordManager) + { + SLANG_RECORD_ASSERT(m_actualFileSystem); + SLANG_RECORD_ASSERT(m_recordManager); + slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, m_actualFileSystem.get()); + } + + FileSystemRecorder::~FileSystemRecorder() + { + m_actualFileSystem->release(); + } + + void* FileSystemRecorder::castAs(const Slang::Guid& guid) + { + return getInterface(guid); + } + + ISlangUnknown* FileSystemRecorder::getInterface(const Slang::Guid& guid) + { + if(guid == ISlangUnknown::getTypeGuid() || guid == ISlangFileSystem::getTypeGuid()) + return static_cast<ISlangFileSystem*>(this); + return nullptr; + } + + // TODO: There could be a potential issue that could not be able to dump the generated file content correctly. + // Details: https://github.com/shader-slang/slang/issues/4423. + SLANG_NO_THROW SlangResult FileSystemRecorder::loadFile( + char const* path, + ISlangBlob** outBlob) + { + slangRecordLog(LogLevel::Verbose, "%p: %s, :%s\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__, path); + SlangResult res = m_actualFileSystem->loadFile(path, outBlob); + + // Since the loadFile method could be implemented by client, we can't guarantee the result is always as expected, + // we will check every thing to make sure we won't crash at writing file. + // + // We can only dump the file content after this 'loadFile' call, no matter this call crashes or file is not + // found, we can't save the file anyway, so we don't need to pay special care to the crash recovery. We will + // know something wrong with the loadFile call if we can't find the file in the record directory. + if ((res == SLANG_OK) && (*outBlob != nullptr) && ((*outBlob)->getBufferSize() != 0)) + { + std::filesystem::path filePath = m_recordManager->getRecordFileDirectory(); + filePath = filePath / path; + + FileOutputStream fileStream(filePath.string().c_str()); + + fileStream.write((*outBlob)->getBufferPointer(), (*outBlob)->getBufferSize()); + fileStream.flush(); + } + return res; + } + + SLANG_NO_THROW SlangResult FileSystemRecorder::getFileUniqueIdentity( + const char* path, + ISlangBlob** outUniqueIdentity) + { + slangRecordLog(LogLevel::Verbose, "%p: %s :\"%s\"\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__, path); + SlangResult res = m_actualFileSystem->getFileUniqueIdentity(path, outUniqueIdentity); + return res; + } + + SLANG_NO_THROW SlangResult FileSystemRecorder::calcCombinedPath( + SlangPathType fromPathType, + const char* fromPath, + const char* path, + ISlangBlob** pathOut) + { + slangRecordLog(LogLevel::Verbose, "%p: %s, :%s\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__, path); + SlangResult res = m_actualFileSystem->calcCombinedPath(fromPathType, fromPath, path, pathOut); + return res; + } + + SLANG_NO_THROW SlangResult FileSystemRecorder::getPathType( + const char* path, + SlangPathType* pathTypeOut) + { + slangRecordLog(LogLevel::Verbose, "%p: %s, :%s\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__, path); + SlangResult res = m_actualFileSystem->getPathType(path, pathTypeOut); + return res; + } + + SLANG_NO_THROW SlangResult FileSystemRecorder::getPath( + PathKind kind, + const char* path, + ISlangBlob** outPath) + { + slangRecordLog(LogLevel::Verbose, "%p: %s, :%s\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__, path); + SlangResult res = m_actualFileSystem->getPath(kind, path, outPath); + return res; + } + + SLANG_NO_THROW void FileSystemRecorder::clearCache() + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__); + m_actualFileSystem->clearCache(); + } + + SLANG_NO_THROW SlangResult FileSystemRecorder::enumeratePathContents( + const char* path, + FileSystemContentsCallBack callback, + void* userData) + { + slangRecordLog(LogLevel::Verbose, "%p: %s, :%s\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__, path); + SlangResult res = m_actualFileSystem->enumeratePathContents(path, callback, userData); + return res; + } + + SLANG_NO_THROW OSPathKind FileSystemRecorder::getOSPathKind() + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualFileSystem.get(), __PRETTY_FUNCTION__); + OSPathKind pathKind = m_actualFileSystem->getOSPathKind(); + return pathKind; + } +} diff --git a/source/slang-record-replay/record/slang-filesystem.h b/source/slang-record-replay/record/slang-filesystem.h new file mode 100644 index 000000000..ff7004fa1 --- /dev/null +++ b/source/slang-record-replay/record/slang-filesystem.h @@ -0,0 +1,71 @@ +#ifndef SLANG_FILE_SYSTEM_H +#define SLANG_FILE_SYSTEM_H + +#include "slang-com-helper.h" +#include "slang-com-ptr.h" +#include "../../core/slang-com-object.h" +#include "record-manager.h" + +namespace SlangRecord +{ + + using namespace Slang; + + // slang always requires ISlangFileSystemExt interface, even if user only provides ISlangFileSystem, + // slang will still wrap it with ISlangFileSystemExt. So we have to record ISlangFileSystemExt, even + // though we only need to record loadFile() function. + class FileSystemRecorder : public RefObject, public ISlangFileSystemExt + { + public: + explicit FileSystemRecorder(ISlangFileSystemExt* fileSystem, RecordManager* recordManager); + ~FileSystemRecorder(); + + // ISlangUnknown + SLANG_REF_OBJECT_IUNKNOWN_ALL + + ISlangUnknown* getInterface(const Slang::Guid& guid); + + // ISlangCastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Slang::Guid& guid) override; + + // ISlangFileSystem + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile( + char const* path, + ISlangBlob** outBlob) override; + + // ISlangFileSystemExt + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity( + const char* path, + ISlangBlob** outUniqueIdentity) override; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath( + SlangPathType fromPathType, + const char* fromPath, + const char* path, + ISlangBlob** pathOut) override; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType( + const char* path, + SlangPathType* pathTypeOut) override; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPath( + PathKind kind, + const char* path, + ISlangBlob** outPath) override; + + virtual SLANG_NO_THROW void SLANG_MCALL clearCache() override; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents( + const char* path, + FileSystemContentsCallBack callback, + void* userData) override; + + virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() override; + private: + Slang::ComPtr<ISlangFileSystemExt> m_actualFileSystem; + RecordManager* m_recordManager = nullptr; +}; + +} +#endif + diff --git a/source/slang-record-replay/record/slang-global-session.cpp b/source/slang-record-replay/record/slang-global-session.cpp new file mode 100644 index 000000000..78fa8aaa2 --- /dev/null +++ b/source/slang-record-replay/record/slang-global-session.cpp @@ -0,0 +1,452 @@ +#include "slang-global-session.h" +#include "slang-session.h" +#include "slang-filesystem.h" +#include "../../slang/slang-compiler.h" +#include "../util/record-utility.h" + +namespace SlangRecord +{ + // constructor is called in slang_createGlobalSession + GlobalSessionRecorder::GlobalSessionRecorder(slang::IGlobalSession* session): + m_actualGlobalSession(session) + { + SLANG_RECORD_ASSERT(m_actualGlobalSession != nullptr); + + m_globalSessionHandle = reinterpret_cast<SlangRecord::AddressFormat>(m_actualGlobalSession.get()); + m_recordManager = std::make_unique<RecordManager>(m_globalSessionHandle); + + // We will use the address of the global session as the filename for the record manager + // to make it unique for each global session. + // record slang::createGlobalSession + ParameterRecorder* recorder = m_recordManager->beginMethodRecord(ApiCallId::CreateGlobalSession, g_globalFunctionHandle); + recorder->recordAddress(m_actualGlobalSession); + m_recordManager->endMethodRecord(); + } + + GlobalSessionRecorder::~GlobalSessionRecorder() + { + m_actualGlobalSession->release(); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::queryInterface(SlangUUID const& uuid, void** outObject) + { + if (uuid == Session::getTypeGuid()) + { + // no add-ref here, the query will cause the inner session to handle the add-ref. + this->m_actualGlobalSession->queryInterface(uuid, outObject); + return SLANG_OK; + } + + if (uuid == ISlangUnknown::getTypeGuid() && uuid == IGlobalSession::getTypeGuid()) + { + addReference(); + *outObject = static_cast<slang::IGlobalSession*>(this); + return SLANG_OK; + } + + return SLANG_E_NO_INTERFACE; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::createSession(slang::SessionDesc const& desc, slang::ISession** outSession) + { + setLogLevel(); + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + slang::ISession* actualSession = nullptr; + + ParameterRecorder* recorder{}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_createSession, m_globalSessionHandle); + recorder->recordStruct(desc); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->createSession(desc, &actualSession); + + { // record output + recorder->recordAddress(actualSession); + m_recordManager->endMethodRecordAppendOutput(); + } + + if (actualSession != nullptr) + { + // reset the file system to our record file system. After createSession() call, + // the Linkage will set to user provided file system or slang default file system. + // We need to reset it to our record file system + Slang::Linkage* linkage = static_cast<Linkage*>(actualSession); + FileSystemRecorder* fileSystemRecord = new FileSystemRecorder(linkage->getFileSystemExt(), m_recordManager.get()); + + Slang::ComPtr<FileSystemRecorder> resultFileSystemRecorder(fileSystemRecord); + linkage->setFileSystem(resultFileSystemRecorder.detach()); + + SessionRecorder* sessionRecord = new SessionRecorder(actualSession, m_recordManager.get()); + Slang::ComPtr<SessionRecorder> result(sessionRecord); + *outSession = result.detach(); + } + + return res; + } + + SLANG_NO_THROW SlangProfileID SLANG_MCALL GlobalSessionRecorder::findProfile(char const* name) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_findProfile, m_globalSessionHandle); + recorder->recordString(name); + recorder = m_recordManager->endMethodRecord(); + } + + SlangProfileID profileId = m_actualGlobalSession->findProfile(name); + return profileId; + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::setDownstreamCompilerPath(SlangPassThrough passThrough, char const* path) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_setDownstreamCompilerPath, m_globalSessionHandle); + recorder->recordEnumValue(passThrough); + recorder->recordString(path); + m_recordManager->endMethodRecord(); + } + + m_actualGlobalSession->setDownstreamCompilerPath(passThrough, path); + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::setDownstreamCompilerPrelude(SlangPassThrough inPassThrough, char const* prelude) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_setDownstreamCompilerPrelude, m_globalSessionHandle); + recorder->recordEnumValue(inPassThrough); + recorder->recordString(prelude); + m_recordManager->endMethodRecord(); + } + + m_actualGlobalSession->setDownstreamCompilerPrelude(inPassThrough, prelude); + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::getDownstreamCompilerPrelude(SlangPassThrough inPassThrough, ISlangBlob** outPrelude) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_getDownstreamCompilerPrelude, m_globalSessionHandle); + recorder->recordEnumValue(inPassThrough); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualGlobalSession->getDownstreamCompilerPrelude(inPassThrough, outPrelude); + + { + recorder->recordAddress(*outPrelude); + m_recordManager->endMethodRecordAppendOutput(); + } + } + + SLANG_NO_THROW const char* SLANG_MCALL GlobalSessionRecorder::getBuildTagString() + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + // No need to record this function. It's just a query function and it won't impact the internal state. + const char* resStr = m_actualGlobalSession->getBuildTagString(); + return resStr; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::setDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_setDefaultDownstreamCompiler, m_globalSessionHandle); + recorder->recordEnumValue(sourceLanguage); + recorder->recordEnumValue(defaultCompiler); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->setDefaultDownstreamCompiler(sourceLanguage, defaultCompiler); + return res; + } + + SLANG_NO_THROW SlangPassThrough SLANG_MCALL GlobalSessionRecorder::getDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_getDefaultDownstreamCompiler, m_globalSessionHandle); + recorder->recordEnumValue(sourceLanguage); + recorder = m_recordManager->endMethodRecord(); + } + + SlangPassThrough passThrough = m_actualGlobalSession->getDefaultDownstreamCompiler(sourceLanguage); + return passThrough; + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::setLanguagePrelude(SlangSourceLanguage inSourceLanguage, char const* prelude) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_setLanguagePrelude, m_globalSessionHandle); + recorder->recordEnumValue(inSourceLanguage); + recorder->recordString(prelude); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualGlobalSession->setLanguagePrelude(inSourceLanguage, prelude); + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::getLanguagePrelude(SlangSourceLanguage inSourceLanguage, ISlangBlob** outPrelude) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_getLanguagePrelude, m_globalSessionHandle); + recorder->recordEnumValue(inSourceLanguage); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualGlobalSession->getLanguagePrelude(inSourceLanguage, outPrelude); + + { + recorder->recordAddress(*outPrelude); + m_recordManager->endMethodRecordAppendOutput(); + } + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::createCompileRequest(slang::ICompileRequest** outCompileRequest) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_createCompileRequest, m_globalSessionHandle); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->createCompileRequest(outCompileRequest); + + { + recorder->recordAddress(*outCompileRequest); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::addBuiltins(char const* sourcePath, char const* sourceString) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_addBuiltins, m_globalSessionHandle); + recorder->recordString(sourcePath); + recorder->recordString(sourceString); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualGlobalSession->addBuiltins(sourcePath, sourceString); + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::setSharedLibraryLoader(ISlangSharedLibraryLoader* loader) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + // TODO: Not sure if we need to record this function. Because this functions is something like the file system + // override, it's provided by user code. So capturing it makes no sense. The only way is to wrapper this interface + // by our own implementation, and record it there. + m_actualGlobalSession->setSharedLibraryLoader(loader); + } + + SLANG_NO_THROW ISlangSharedLibraryLoader* SLANG_MCALL GlobalSessionRecorder::getSharedLibraryLoader() + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_getSharedLibraryLoader, m_globalSessionHandle); + recorder = m_recordManager->endMethodRecord(); + } + + ISlangSharedLibraryLoader* loader = m_actualGlobalSession->getSharedLibraryLoader(); + + { + recorder->recordAddress(loader); + m_recordManager->endMethodRecordAppendOutput(); + } + return loader; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::checkCompileTargetSupport(SlangCompileTarget target) + { + // No need to record this function. It's just a query function and it won't impact the internal state. + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + SlangResult res = m_actualGlobalSession->checkCompileTargetSupport(target); + return res; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::checkPassThroughSupport(SlangPassThrough passThrough) + { + // No need to record this function. It's just a query function and it won't impact the internal state. + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + SlangResult res = m_actualGlobalSession->checkPassThroughSupport(passThrough); + return res; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::compileStdLib(slang::CompileStdLibFlags flags) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_compileStdLib, m_globalSessionHandle); + recorder->recordEnumValue(flags); + m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->compileStdLib(flags); + return res; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::loadStdLib(const void* stdLib, size_t stdLibSizeInBytes) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_loadStdLib, m_globalSessionHandle); + recorder->recordPointer(stdLib, false, stdLibSizeInBytes); + m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->loadStdLib(stdLib, stdLibSizeInBytes); + return res; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::saveStdLib(SlangArchiveType archiveType, ISlangBlob** outBlob) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_saveStdLib, m_globalSessionHandle); + recorder->recordEnumValue(archiveType); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->saveStdLib(archiveType, outBlob); + + { + recorder->recordAddress(*outBlob); + m_recordManager->endMethodRecordAppendOutput(); + } + return res; + } + + SLANG_NO_THROW SlangCapabilityID SLANG_MCALL GlobalSessionRecorder::findCapability(char const* name) + { + // No need to record this function. It's just a query function and it won't impact the internal state. + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + SlangCapabilityID capId = m_actualGlobalSession->findCapability(name); + return capId; + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::setDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_setDownstreamCompilerForTransition, m_globalSessionHandle); + recorder->recordEnumValue(source); + recorder->recordEnumValue(target); + recorder->recordEnumValue(compiler); + m_recordManager->endMethodRecord(); + } + + m_actualGlobalSession->setDownstreamCompilerForTransition(source, target, compiler); + } + + SLANG_NO_THROW SlangPassThrough SLANG_MCALL GlobalSessionRecorder::getDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target) + { + // No need to record this function. It's just a query function and it won't impact the internal state. + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + SlangPassThrough passThrough = m_actualGlobalSession->getDownstreamCompilerForTransition(source, target); + return passThrough; + } + + SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::getCompilerElapsedTime(double* outTotalTime, double* outDownstreamTime) + { + // No need to record this function. It's just a query function and it won't impact the internal state. + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + m_actualGlobalSession->getCompilerElapsedTime(outTotalTime, outDownstreamTime); + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::setSPIRVCoreGrammar(char const* jsonPath) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_setSPIRVCoreGrammar, m_globalSessionHandle); + recorder->recordString(jsonPath); + m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->setSPIRVCoreGrammar(jsonPath); + return res; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::parseCommandLineArguments( + int argc, const char* const* argv, slang::SessionDesc* outSessionDesc, ISlangUnknown** outAllocation) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_parseCommandLineArguments, m_globalSessionHandle); + recorder->recordInt32(argc); + recorder->recordStringArray(argv, argc); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->parseCommandLineArguments(argc, argv, outSessionDesc, outAllocation); + + { + recorder->recordAddress(outSessionDesc); + recorder->recordAddress(*outAllocation); + m_recordManager->endMethodRecordAppendOutput(); + } + return res; + } + + SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::getSessionDescDigest(slang::SessionDesc* sessionDesc, ISlangBlob** outBlob) + { + slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IGlobalSession_getSessionDescDigest, m_globalSessionHandle); + recorder->recordStruct(*sessionDesc); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualGlobalSession->getSessionDescDigest(sessionDesc, outBlob); + + { + recorder->recordAddress(*outBlob); + m_recordManager->endMethodRecordAppendOutput(); + } + return res; + } +} diff --git a/source/slang-record-replay/record/slang-global-session.h b/source/slang-record-replay/record/slang-global-session.h new file mode 100644 index 000000000..3fd584ef4 --- /dev/null +++ b/source/slang-record-replay/record/slang-global-session.h @@ -0,0 +1,85 @@ +#ifndef SLANG_GLOBAL_SESSION_H +#define SLANG_GLOBAL_SESSION_H + +#include "slang-com-ptr.h" +#include "slang.h" +#include "slang-com-helper.h" +#include "../../core/slang-smart-pointer.h" +#include "record-manager.h" + +namespace SlangRecord +{ + using namespace Slang; + + class GlobalSessionRecorder : public RefObject, public slang::IGlobalSession + { + public: + explicit GlobalSessionRecorder(slang::IGlobalSession* session); + virtual ~GlobalSessionRecorder(); + + SLANG_REF_OBJECT_IUNKNOWN_ADD_REF + SLANG_REF_OBJECT_IUNKNOWN_RELEASE + + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; + + // slang::IGlobalSession + SLANG_NO_THROW SlangResult SLANG_MCALL createSession(slang::SessionDesc const& desc, slang::ISession** outSession) override; + SLANG_NO_THROW SlangProfileID SLANG_MCALL findProfile(char const* name) override; + SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerPath(SlangPassThrough passThrough, char const* path) override; + SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerPrelude(SlangPassThrough inPassThrough, char const* prelude) override; + SLANG_NO_THROW void SLANG_MCALL getDownstreamCompilerPrelude(SlangPassThrough inPassThrough, ISlangBlob** outPrelude) override; + SLANG_NO_THROW const char* SLANG_MCALL getBuildTagString() override; + SLANG_NO_THROW SlangResult SLANG_MCALL setDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) override; + SLANG_NO_THROW SlangPassThrough SLANG_MCALL getDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage) override; + + SLANG_NO_THROW void SLANG_MCALL setLanguagePrelude(SlangSourceLanguage inSourceLanguage, char const* prelude) override; + SLANG_NO_THROW void SLANG_MCALL getLanguagePrelude(SlangSourceLanguage inSourceLanguage, ISlangBlob** outPrelude) override; + + SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest(slang::ICompileRequest** outCompileRequest) override; + + SLANG_NO_THROW void SLANG_MCALL addBuiltins(char const* sourcePath, char const* sourceString) override; + SLANG_NO_THROW void SLANG_MCALL setSharedLibraryLoader(ISlangSharedLibraryLoader* loader) override; + SLANG_NO_THROW ISlangSharedLibraryLoader* SLANG_MCALL getSharedLibraryLoader() override; + SLANG_NO_THROW SlangResult SLANG_MCALL checkCompileTargetSupport(SlangCompileTarget target) override; + SLANG_NO_THROW SlangResult SLANG_MCALL checkPassThroughSupport(SlangPassThrough passThrough) override; + + SLANG_NO_THROW SlangResult SLANG_MCALL compileStdLib(slang::CompileStdLibFlags flags) override; + SLANG_NO_THROW SlangResult SLANG_MCALL loadStdLib(const void* stdLib, size_t stdLibSizeInBytes) override; + SLANG_NO_THROW SlangResult SLANG_MCALL saveStdLib(SlangArchiveType archiveType, ISlangBlob** outBlob) override; + + SLANG_NO_THROW SlangCapabilityID SLANG_MCALL findCapability(char const* name) override; + + SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) override; + SLANG_NO_THROW SlangPassThrough SLANG_MCALL getDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target) override; + SLANG_NO_THROW void SLANG_MCALL getCompilerElapsedTime(double* outTotalTime, double* outDownstreamTime) override; + + SLANG_NO_THROW SlangResult SLANG_MCALL setSPIRVCoreGrammar(char const* jsonPath) override; + + SLANG_NO_THROW SlangResult SLANG_MCALL parseCommandLineArguments( + int argc, const char* const* argv, slang::SessionDesc* outSessionDesc, ISlangUnknown** outAllocation) override; + + SLANG_NO_THROW SlangResult SLANG_MCALL getSessionDescDigest(slang::SessionDesc* sessionDesc, ISlangBlob** outBlob) override; + + RecordManager* getRecordManager() { return m_recordManager.get(); } + + private: + SLANG_FORCE_INLINE slang::IGlobalSession* asExternal(GlobalSessionRecorder* session) + { + return static_cast<slang::IGlobalSession*>(session); + } + + Slang::ComPtr<slang::IGlobalSession> m_actualGlobalSession; + + // we will create one record file per IGlobalSession. + // We don't try to reproduce the user application's threading model, because it requires lots of effort and it's not necessary. + // Instead, we record all the compilation jobs associated with the session in the same record file, so that during replay, + // those jobs will be executed sequentially. This might violate the user application's threading model, because those jobs might + // be executed in different threads. But it's not a big problem, because slang doesn't allow multiple threads to access the same + // session at the same time. So even if there is one session used by multiple threads, those threads will execute the compile jobs + // sequentially. + std::unique_ptr<RecordManager> m_recordManager; + uint64_t m_globalSessionHandle = 0; + }; +} // namespace Slang + +#endif diff --git a/source/slang-record-replay/record/slang-module.cpp b/source/slang-record-replay/record/slang-module.cpp new file mode 100644 index 000000000..1457e7cf1 --- /dev/null +++ b/source/slang-record-replay/record/slang-module.cpp @@ -0,0 +1,496 @@ +#include "../util/record-utility.h" +#include "slang-module.h" + +namespace SlangRecord +{ + ModuleRecorder::ModuleRecorder(slang::IModule* module, RecordManager* recordManager) + : m_actualModule(module), + m_recordManager(recordManager) + { + SLANG_RECORD_ASSERT(m_actualModule != nullptr); + SLANG_RECORD_ASSERT(m_recordManager != nullptr); + + m_moduleHandle = reinterpret_cast<uint64_t>(m_actualModule.get()); + slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, module); + } + + ModuleRecorder::~ModuleRecorder() + { + m_actualModule->release(); + } + + ISlangUnknown* ModuleRecorder::getInterface(const Guid& guid) + { + if(guid == ModuleRecorder::getTypeGuid()) + return static_cast<ISlangUnknown*>(this); + else + return nullptr; + } + + SLANG_NO_THROW slang::DeclReflection* ModuleRecorder::getModuleReflection() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + slang::DeclReflection* res = (slang::DeclReflection*)m_actualModule->getModuleReflection(); + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::findEntryPointByName( + char const* name, + slang::IEntryPoint** outEntryPoint) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_findEntryPointByName, m_moduleHandle); + recorder->recordString(name); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->findEntryPointByName(name, outEntryPoint); + + { + recorder->recordAddress(*outEntryPoint); + m_recordManager->endMethodRecordAppendOutput(); + } + + if (SLANG_OK == res) + { + EntryPointRecorder* entryPointRecord = getEntryPointRecorder(*outEntryPoint); + *outEntryPoint = static_cast<slang::IEntryPoint*>(entryPointRecord); + } + return res; + } + + SLANG_NO_THROW SlangInt32 ModuleRecorder::getDefinedEntryPointCount() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + SlangInt32 res = m_actualModule->getDefinedEntryPointCount(); + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::getDefinedEntryPoint(SlangInt32 index, slang::IEntryPoint** outEntryPoint) + { + // This call is to find the existing entry point, so it has been created already. Therefore, we don't create a new one + // and assert the error if it is not found in our map. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_getDefinedEntryPoint, m_moduleHandle); + recorder->recordInt32(index); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->getDefinedEntryPoint(index, outEntryPoint); + + { + recorder->recordAddress(*outEntryPoint); + m_recordManager->endMethodRecordAppendOutput(); + } + + if (*outEntryPoint) + { + EntryPointRecorder* entryPointRecord = m_mapEntryPointToRecord.tryGetValue(*outEntryPoint); + if (!entryPointRecord) + { + SLANG_RECORD_ASSERT(!"Entrypoint not found in mapEntryPointToRecord"); + } + *outEntryPoint = static_cast<slang::IEntryPoint*>(entryPointRecord); + } + else + *outEntryPoint = nullptr; + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::serialize(ISlangBlob** outSerializedBlob) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_serialize, m_moduleHandle); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->serialize(outSerializedBlob); + + { + recorder->recordAddress(*outSerializedBlob); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::writeToFile(char const* fileName) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_writeToFile, m_moduleHandle); + recorder->recordString(fileName); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->writeToFile(fileName); + return res; + } + + SLANG_NO_THROW const char* ModuleRecorder::getName() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + const char* res = m_actualModule->getName(); + return res; + } + + SLANG_NO_THROW const char* ModuleRecorder::getFilePath() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + const char* res = m_actualModule->getFilePath(); + return res; + } + + SLANG_NO_THROW const char* ModuleRecorder::getUniqueIdentity() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + const char* res = m_actualModule->getUniqueIdentity(); + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::findAndCheckEntryPoint( + char const* name, + SlangStage stage, + slang::IEntryPoint** outEntryPoint, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_findAndCheckEntryPoint, m_moduleHandle); + recorder->recordString(name); + recorder->recordEnumValue(stage); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->findAndCheckEntryPoint(name, stage, outEntryPoint, outDiagnostics); + + { + recorder->recordAddress(*outEntryPoint); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + if (SLANG_OK == res) + { + EntryPointRecorder* entryPointRecord = getEntryPointRecorder(*outEntryPoint); + *outEntryPoint = static_cast<slang::IEntryPoint*>(entryPointRecord); + } + return res; + } + + SLANG_NO_THROW SlangInt32 ModuleRecorder::getDependencyFileCount() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + SlangInt32 res = m_actualModule->getDependencyFileCount(); + return res; + } + + SLANG_NO_THROW char const* ModuleRecorder::getDependencyFilePath(SlangInt32 index) + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + const char* res = m_actualModule->getDependencyFilePath(index); + return res; + } + + SLANG_NO_THROW slang::ISession* ModuleRecorder::getSession() + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + slang::ISession* session = m_actualModule->getSession(); + + return session; + } + + SLANG_NO_THROW slang::ProgramLayout* ModuleRecorder::getLayout( + SlangInt targetIndex, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_getLayout, m_moduleHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + slang::ProgramLayout* programLayout = m_actualModule->getLayout(targetIndex, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(programLayout); + m_recordManager->endMethodRecordAppendOutput(); + } + + return programLayout; + } + + SLANG_NO_THROW SlangInt ModuleRecorder::getSpecializationParamCount() + { + // No need to record this call as it is just a query. + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + SlangInt res = m_actualModule->getSpecializationParamCount(); + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_getEntryPointCode, m_moduleHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_getTargetCode, m_moduleHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->getTargetCode(targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_getResultAsFileSystem, m_moduleHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->getResultAsFileSystem(entryPointIndex, targetIndex, outFileSystem); + + { + recorder->recordAddress(*outFileSystem); + m_recordManager->endMethodRecordAppendOutput(); + } + + // TODO: We might need to wrap the file system object. + return res; + } + + SLANG_NO_THROW void ModuleRecorder::getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_getEntryPointHash, m_moduleHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualModule->getEntryPointHash(entryPointIndex, targetIndex, outHash); + + { + recorder->recordAddress(*outHash); + m_recordManager->endMethodRecordAppendOutput(); + } + } + + SLANG_NO_THROW SlangResult ModuleRecorder::specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_specialize, m_moduleHandle); + recorder->recordInt64(specializationArgCount); + recorder->recordStructArray(specializationArgs, specializationArgCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->specialize(specializationArgs, specializationArgCount, outSpecializedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outSpecializedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::link( + IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_link, m_moduleHandle); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->link(outLinkedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_getEntryPointHostCallable, m_moduleHandle); + recorder->recordInt32(entryPointIndex); + recorder->recordInt32(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->getEntryPointHostCallable(entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); + + { + recorder->recordAddress(*outSharedLibrary); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_renameEntryPoint, m_moduleHandle); + recorder->recordString(newName); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->renameEntryPoint(newName, outEntryPoint); + + { + recorder->recordAddress(*outEntryPoint); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult ModuleRecorder::linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::IModule_linkWithOptions, m_moduleHandle); + recorder->recordUint32(compilerOptionEntryCount); + recorder->recordStructArray(compilerOptionEntries, compilerOptionEntryCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualModule->linkWithOptions(outLinkedComponentType, compilerOptionEntryCount, compilerOptionEntries, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + EntryPointRecorder* ModuleRecorder::getEntryPointRecorder(slang::IEntryPoint* entryPoint) + { + EntryPointRecorder* entryPointRecord = nullptr; + entryPointRecord = m_mapEntryPointToRecord.tryGetValue(entryPoint); + if (!entryPointRecord) + { + entryPointRecord = new EntryPointRecorder(entryPoint, m_recordManager); + Slang::ComPtr<EntryPointRecorder> result(entryPointRecord); + m_mapEntryPointToRecord.add(entryPoint, *result.detach()); + } + return entryPointRecord; + } +} diff --git a/source/slang-record-replay/record/slang-module.h b/source/slang-record-replay/record/slang-module.h new file mode 100644 index 000000000..ca0403c2d --- /dev/null +++ b/source/slang-record-replay/record/slang-module.h @@ -0,0 +1,102 @@ +#ifndef SLANG_MODULE_H +#define SLANG_MODULE_H + +#include "slang-com-ptr.h" +#include "slang.h" +#include "slang-com-helper.h" +#include "../../core/slang-smart-pointer.h" +#include "../../slang/slang-compiler.h" +#include "slang-entrypoint.h" +#include "record-manager.h" + +namespace SlangRecord +{ + using namespace Slang; + class ModuleRecorder : public slang::IModule, public RefObject + { + public: + SLANG_COM_INTERFACE(0xb1802991, 0x185a, 0x4a03, { 0xa7, 0x7e, 0x0c, 0x86, 0xe0, 0x68, 0x2a, 0xab }) + + SLANG_REF_OBJECT_IUNKNOWN_ALL + ISlangUnknown* getInterface(const Guid& guid); + + explicit ModuleRecorder(slang::IModule* module, RecordManager* recordManager); + ~ModuleRecorder(); + + // Interfaces for `IModule` + virtual SLANG_NO_THROW SlangResult SLANG_MCALL findEntryPointByName( + char const* name, slang::IEntryPoint** outEntryPoint) override; + virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDefinedEntryPointCount() override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getDefinedEntryPoint(SlangInt32 index, slang::IEntryPoint** outEntryPoint) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL serialize(ISlangBlob** outSerializedBlob) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToFile(char const* fileName) override; + virtual SLANG_NO_THROW const char* SLANG_MCALL getName() override; + virtual SLANG_NO_THROW const char* SLANG_MCALL getFilePath() override; + virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL findAndCheckEntryPoint( + char const* name, SlangStage stage, slang::IEntryPoint** outEntryPoint, ISlangBlob** outDiagnostics) override; + virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDependencyFileCount() override; + virtual SLANG_NO_THROW char const* SLANG_MCALL getDependencyFilePath( + SlangInt32 index) override; + + // Interfaces for `IComponentType` + virtual SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() override; + virtual SLANG_NO_THROW slang::ProgramLayout* SLANG_MCALL getLayout( + SlangInt targetIndex = 0, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangInt SLANG_MCALL getSpecializationParamCount() override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) override; + virtual SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL link( + slang::IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics = 0) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW slang::DeclReflection* getModuleReflection() override; + + slang::IModule* getActualModule() const { return m_actualModule; } + private: + EntryPointRecorder* getEntryPointRecorder(slang::IEntryPoint* entryPoint); + Slang::ComPtr<slang::IModule> m_actualModule; + uint64_t m_moduleHandle = 0; + RecordManager* m_recordManager = nullptr; + + // `IEntryPoint` can only be created from 'IModule', so we need to record it in + // this class, and create a map such that we don't create new `EntryPointRecorder` + // for the same `IEntryPoint`. + Dictionary<slang::IEntryPoint*, EntryPointRecorder> m_mapEntryPointToRecord; + }; +} // namespace SlangRecord + +#endif // SLANG_MODULE_H 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 diff --git a/source/slang-record-replay/record/slang-session.h b/source/slang-record-replay/record/slang-session.h new file mode 100644 index 000000000..ca06e25a0 --- /dev/null +++ b/source/slang-record-replay/record/slang-session.h @@ -0,0 +1,110 @@ +#ifndef SLANG_SESSION_H +#define SLANG_SESSION_H + +#include "slang-com-ptr.h" +#include "slang.h" +#include "slang-com-helper.h" +#include "../../core/slang-smart-pointer.h" +#include "../../core/slang-dictionary.h" +#include "../../slang/slang-compiler.h" +#include "slang-module.h" +#include "record-manager.h" + +namespace SlangRecord +{ + using namespace Slang; + class SessionRecorder: public RefObject, public slang::ISession + { + public: + SLANG_REF_OBJECT_IUNKNOWN_ALL + ISlangUnknown* getInterface(const Guid& guid); + + explicit SessionRecorder(slang::ISession* session, RecordManager* recordManager); + ~SessionRecorder(); + + SLANG_NO_THROW slang::IGlobalSession* SLANG_MCALL getGlobalSession() override; + SLANG_NO_THROW slang::IModule* SLANG_MCALL loadModule( + const char* moduleName, + slang::IBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW slang::IModule* SLANG_MCALL loadModuleFromIRBlob( + const char* moduleName, + const char* path, + slang::IBlob* source, + slang::IBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW slang::IModule* SLANG_MCALL loadModuleFromSource( + const char* moduleName, + const char* path, + slang::IBlob* source, + slang::IBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW slang::IModule* SLANG_MCALL loadModuleFromSourceString( + const char* moduleName, + const char* path, + const char* string, + slang::IBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW SlangResult SLANG_MCALL createCompositeComponentType( + slang::IComponentType* const* componentTypes, + SlangInt componentTypeCount, + slang::IComponentType** outCompositeComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL specializeType( + slang::TypeReflection* type, + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + ISlangBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL getTypeLayout( + slang::TypeReflection* type, + SlangInt targetIndex = 0, + slang::LayoutRules rules = slang::LayoutRules::Default, + ISlangBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL getContainerType( + slang::TypeReflection* elementType, + slang::ContainerType containerType, + ISlangBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL getDynamicType() override; + SLANG_NO_THROW SlangResult SLANG_MCALL getTypeRTTIMangledName( + slang::TypeReflection* type, + ISlangBlob** outNameBlob) override; + SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessMangledName( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + ISlangBlob** outNameBlob) override; + SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessSequentialID( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + uint32_t* outId) override; + SLANG_NO_THROW SlangResult SLANG_MCALL createTypeConformanceComponentType( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + slang::ITypeConformance** outConformance, + SlangInt conformanceIdOverride, + ISlangBlob** outDiagnostics) override; + SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest( + SlangCompileRequest** outCompileRequest) override; + SLANG_NO_THROW SlangInt SLANG_MCALL getLoadedModuleCount() override; + SLANG_NO_THROW slang::IModule* SLANG_MCALL getLoadedModule(SlangInt index) override; + SLANG_NO_THROW bool SLANG_MCALL isBinaryModuleUpToDate(const char* modulePath, slang::IBlob* binaryModuleBlob) override; + + private: + SLANG_FORCE_INLINE slang::ISession* asExternal(SessionRecorder* session) + { + return static_cast<slang::ISession*>(session); + } + + // The IComponentType object is the record target, therefore `componentTypes` will not be + // the actual component types, we have to use the COM interface to get the actual objects. + SlangResult getActualComponentTypes( + slang::IComponentType* const* componentTypes, + SlangInt componentTypeCount, + List<slang::IComponentType*>& outActualComponentTypes); + + ModuleRecorder* getModuleRecorder(slang::IModule* module); + + Slang::ComPtr<slang::ISession> m_actualSession; + uint64_t m_sessionHandle = 0; + + Dictionary<slang::IModule*, ModuleRecorder> m_mapModuleToRecord; + RecordManager* m_recordManager = nullptr; + }; +} + +#endif // SLANG_SESSION_H diff --git a/source/slang-record-replay/record/slang-type-conformance.cpp b/source/slang-record-replay/record/slang-type-conformance.cpp new file mode 100644 index 000000000..b9b652e9e --- /dev/null +++ b/source/slang-record-replay/record/slang-type-conformance.cpp @@ -0,0 +1,310 @@ +#include "../util/record-utility.h" +#include "slang-type-conformance.h" + +namespace SlangRecord +{ + TypeConformanceRecorder::TypeConformanceRecorder(slang::ITypeConformance* typeConformance, RecordManager* recordManager) + : m_actualTypeConformance(typeConformance), + m_recordManager(recordManager) + { + SLANG_RECORD_ASSERT(m_actualTypeConformance != nullptr); + SLANG_RECORD_ASSERT(m_recordManager != nullptr); + + m_typeConformanceHandle = reinterpret_cast<uint64_t>(m_actualTypeConformance.get()); + slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, typeConformance); + } + + TypeConformanceRecorder::~TypeConformanceRecorder() + { + m_actualTypeConformance->release(); + } + + ISlangUnknown* TypeConformanceRecorder::getInterface(const Guid& guid) + { + if (guid == TypeConformanceRecorder::getTypeGuid()) + { + return static_cast<ISlangUnknown*>(this); + } + else + { + return nullptr; + } + } + + SLANG_NO_THROW slang::ISession* TypeConformanceRecorder::getSession() + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_getSession, m_typeConformanceHandle); + recorder = m_recordManager->endMethodRecord(); + } + + slang::ISession* res = m_actualTypeConformance->getSession(); + + { + recorder->recordAddress(res); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW slang::ProgramLayout* TypeConformanceRecorder::getLayout( + SlangInt targetIndex, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ICompositeComponentType_getLayout, m_typeConformanceHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + slang::ProgramLayout* programLayout = m_actualTypeConformance->getLayout(targetIndex, outDiagnostics); + + { + recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(programLayout); + m_recordManager->endMethodRecordAppendOutput(); + } + + return programLayout; + } + + SLANG_NO_THROW SlangInt TypeConformanceRecorder::getSpecializationParamCount() + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + SlangInt res = m_actualTypeConformance->getSpecializationParamCount(); + return res; + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_getEntryPointCode, m_typeConformanceHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_getTargetCode, m_typeConformanceHandle); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->getTargetCode(targetIndex, outCode, outDiagnostics); + + { + recorder->recordAddress(*outCode); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_getResultAsFileSystem, m_typeConformanceHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->getResultAsFileSystem(entryPointIndex, targetIndex, outFileSystem); + + { + recorder->recordAddress(*outFileSystem); + } + + // TODO: We might need to wrap the file system object. + return res; + } + + SLANG_NO_THROW void TypeConformanceRecorder::getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_getEntryPointHash, m_typeConformanceHandle); + recorder->recordInt64(entryPointIndex); + recorder->recordInt64(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + m_actualTypeConformance->getEntryPointHash(entryPointIndex, targetIndex, outHash); + + { + recorder->recordAddress(*outHash); + m_recordManager->endMethodRecordAppendOutput(); + } + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_specialize, m_typeConformanceHandle); + recorder->recordInt64(specializationArgCount); + recorder->recordStructArray(specializationArgs, specializationArgCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->specialize(specializationArgs, specializationArgCount, outSpecializedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outSpecializedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::link( + slang::IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_link, m_typeConformanceHandle); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->link(outLinkedComponentType, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_getEntryPointHostCallable, m_typeConformanceHandle); + recorder->recordInt32(entryPointIndex); + recorder->recordInt32(targetIndex); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->getEntryPointHostCallable(entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); + + { + recorder->recordAddress(*outSharedLibrary); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_renameEntryPoint, m_typeConformanceHandle); + recorder->recordString(newName); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->renameEntryPoint(newName, outEntryPoint); + + { + recorder->recordAddress(*outEntryPoint); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } + + SLANG_NO_THROW SlangResult TypeConformanceRecorder::linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics) + { + slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__); + + ParameterRecorder* recorder {}; + { + recorder = m_recordManager->beginMethodRecord(ApiCallId::ITypeConformance_linkWithOptions, m_typeConformanceHandle); + recorder->recordUint32(compilerOptionEntryCount); + recorder->recordStructArray(compilerOptionEntries, compilerOptionEntryCount); + recorder = m_recordManager->endMethodRecord(); + } + + SlangResult res = m_actualTypeConformance->linkWithOptions(outLinkedComponentType, compilerOptionEntryCount, compilerOptionEntries, outDiagnostics); + + { + recorder->recordAddress(*outLinkedComponentType); + recorder->recordAddress(*outDiagnostics); + m_recordManager->endMethodRecordAppendOutput(); + } + + return res; + } +} diff --git a/source/slang-record-replay/record/slang-type-conformance.h b/source/slang-record-replay/record/slang-type-conformance.h new file mode 100644 index 000000000..7bcae0d15 --- /dev/null +++ b/source/slang-record-replay/record/slang-type-conformance.h @@ -0,0 +1,77 @@ +#ifndef SLANG_TYPE_CONFORMANCE_H +#define SLANG_TYPE_CONFORMANCE_H + +#include "slang-com-ptr.h" +#include "slang.h" +#include "slang-com-helper.h" +#include "../../core/slang-smart-pointer.h" +#include "../../core/slang-dictionary.h" +#include "../../slang/slang-compiler.h" +#include "record-manager.h" + +namespace SlangRecord +{ + using namespace Slang; + class TypeConformanceRecorder: public slang::ITypeConformance, public RefObject + { + public: + SLANG_COM_INTERFACE(0x0e67d05d, 0xee0a, 0x41e1, { 0xb5, 0xa3, 0x23, 0xe3, 0xb0, 0xec, 0x33, 0xf1 }) + + SLANG_REF_OBJECT_IUNKNOWN_ALL + ISlangUnknown* getInterface(const Guid& guid); + + explicit TypeConformanceRecorder(slang::ITypeConformance* typeConformance, RecordManager* recordManager); + ~TypeConformanceRecorder(); + + // Interfaces for `IComponentType` + virtual SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() override; + virtual SLANG_NO_THROW slang::ProgramLayout* SLANG_MCALL getLayout( + SlangInt targetIndex = 0, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangInt SLANG_MCALL getSpecializationParamCount() override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCode( + SlangInt targetIndex, + slang::IBlob** outCode, + slang::IBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) override; + virtual SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( + SlangInt entryPointIndex, + SlangInt targetIndex, + slang::IBlob** outHash) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL specialize( + slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + slang::IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL link( + slang::IComponentType** outLinkedComponentType, + ISlangBlob** outDiagnostics = nullptr) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics = 0) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint( + const char* newName, IComponentType** outEntryPoint) override; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + slang::CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics = nullptr) override; + + slang::ITypeConformance* getActualTypeConformance() const { return m_actualTypeConformance; } + private: + Slang::ComPtr<slang::ITypeConformance> m_actualTypeConformance; + uint64_t m_typeConformanceHandle = 0; + RecordManager* m_recordManager = nullptr; + }; +} +#endif // SLANG_TYPE_CONFORMANCE_H diff --git a/source/slang-record-replay/replay/decoder-consumer.cpp b/source/slang-record-replay/replay/decoder-consumer.cpp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/source/slang-record-replay/replay/decoder-consumer.cpp diff --git a/source/slang-record-replay/replay/decoder-consumer.h b/source/slang-record-replay/replay/decoder-consumer.h new file mode 100644 index 000000000..f79d9aa5e --- /dev/null +++ b/source/slang-record-replay/replay/decoder-consumer.h @@ -0,0 +1,178 @@ +#ifndef DECODER_CONSUMER_H +#define DECODER_CONSUMER_H + +#include "slang.h" +// #include "../../slang/slang-compiler.h" +#include "../util/record-format.h" + +namespace SlangRecord +{ + class IDecoderConsumer + { + public: + virtual void CreateGlobalSession(ObjectID objectId, const uint8_t* parameterBuffer, int64_t bufferSize) = 0; + virtual void IGlobalSession_createSession(ObjectID objectId, slang::SessionDesc const& desc, ObjectID outSessionId) = 0; + virtual void IGlobalSession_findProfile(ObjectID objectId, char const* name) = 0; + virtual void IGlobalSession_setDownstreamCompilerPath(ObjectID objectId, SlangPassThrough passThrough, char const* path) = 0; + virtual void IGlobalSession_setDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, char const* prelude) = 0; + virtual void IGlobalSession_getDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, ObjectID outPreludeId) = 0; + + virtual void IGlobalSession_getBuildTagString(ObjectID objectId) { (void) objectId; } + + virtual void IGlobalSession_setDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) = 0; + virtual void IGlobalSession_getDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage) = 0; + virtual void IGlobalSession_setLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, char const* prelude) = 0; + virtual void IGlobalSession_getLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, ObjectID outPreludeId) = 0; + virtual void IGlobalSession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequest) = 0; + virtual void IGlobalSession_addBuiltins(ObjectID objectId, char const* sourcePath, char const* sourceString) = 0; + virtual void IGlobalSession_setSharedLibraryLoader(ObjectID objectId, ObjectID loaderId) = 0; + virtual void IGlobalSession_getSharedLibraryLoader(ObjectID objectId, ObjectID outLoaderId) = 0; + virtual void IGlobalSession_checkCompileTargetSupport(ObjectID objectId, SlangCompileTarget target) = 0; + virtual void IGlobalSession_checkPassThroughSupport(ObjectID objectId, SlangPassThrough passThrough) = 0; + virtual void IGlobalSession_compileStdLib(ObjectID objectId, slang::CompileStdLibFlags flags) = 0; + virtual void IGlobalSession_loadStdLib(ObjectID objectId, const void* stdLib, size_t stdLibSizeInBytes) = 0; + virtual void IGlobalSession_saveStdLib(ObjectID objectId, SlangArchiveType archiveType, ObjectID outBlobId) = 0; + virtual void IGlobalSession_findCapability(ObjectID objectId, char const* name) = 0; + virtual void IGlobalSession_setDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) = 0; + virtual void IGlobalSession_getDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target) = 0; + + virtual void IGlobalSession_getCompilerElapsedTime(ObjectID objectId) { (void) objectId; } + + virtual void IGlobalSession_setSPIRVCoreGrammar(ObjectID objectId, char const* jsonPath) = 0; + virtual void IGlobalSession_parseCommandLineArguments(ObjectID objectId, int argc, const char* const* argv, ObjectID outSessionDescId, ObjectID outAllocationId) = 0; + virtual void IGlobalSession_getSessionDescDigest(ObjectID objectId, slang::SessionDesc* sessionDesc, ObjectID outBlobId) = 0; + + // ISession + virtual void ISession_getGlobalSession(ObjectID objectId, ObjectID outGlobalSessionId) = 0; + virtual void ISession_loadModule(ObjectID objectId, const char* moduleName, ObjectID outDiagnostics, ObjectID outModuleId) = 0; + + virtual void ISession_loadModuleFromIRBlob(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_loadModuleFromSource(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_loadModuleFromSourceString(ObjectID objectId, const char* moduleName, + const char* path, const char* string, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_createCompositeComponentType(ObjectID objectId, ObjectID* componentTypeIds, + SlangInt componentTypeCount, ObjectID outCompositeComponentTypeIds, ObjectID outDiagnosticsId) = 0; + + virtual void ISession_specializeType(ObjectID objectId, ObjectID typeId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getTypeLayout(ObjectID objectId, ObjectID typeId, SlangInt targetIndex, + slang::LayoutRules rules, ObjectID outDiagnosticsId, ObjectID outTypeLayoutReflection) = 0; + + virtual void ISession_getContainerType(ObjectID objectId, ObjectID elementType, + slang::ContainerType containerType, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getDynamicType(ObjectID objectId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getTypeRTTIMangledName(ObjectID objectId, ObjectID typeId, ObjectID outNameBlobId) = 0; + + virtual void ISession_getTypeConformanceWitnessMangledName(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outNameBlobId) = 0; + + virtual void ISession_getTypeConformanceWitnessSequentialID(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, uint32_t outId) = 0; + + virtual void ISession_createTypeConformanceComponentType(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outConformanceId, + SlangInt conformanceIdOverride, ObjectID outDiagnosticsId) = 0; + + virtual void ISession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequestId) = 0; + + virtual void ISession_getLoadedModuleCount(ObjectID objectId) { (void) objectId; } + + virtual void ISession_getLoadedModule(ObjectID objectId, SlangInt index, ObjectID outModuleId) = 0; + + virtual void ISession_isBinaryModuleUpToDate(ObjectID objectId) { (void) objectId; } + + // IModule + virtual void IModule_findEntryPointByName(ObjectID objectId, char const* name, ObjectID outEntryPointId) = 0; + + virtual void IModule_getDefinedEntryPointCount(ObjectID objectId) { (void) objectId; } + + virtual void IModule_getDefinedEntryPoint(ObjectID objectId, SlangInt32 index, ObjectID outEntryPointId) = 0; + virtual void IModule_serialize(ObjectID objectId, ObjectID outSerializedBlobId) = 0; + virtual void IModule_writeToFile(ObjectID objectId, char const* fileName) = 0; + + virtual void IModule_getName(ObjectID objectId) { (void) objectId; } + virtual void IModule_getFilePath(ObjectID objectId) { (void) objectId; } + virtual void IModule_getUniqueIdentity(ObjectID objectId) { (void) objectId; } + + virtual void IModule_findAndCheckEntryPoint(ObjectID objectId, char const* name, SlangStage stage, ObjectID outEntryPointId, ObjectID outDiagnostics) = 0; + + virtual void IModule_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void IModule_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void IModule_getSpecializationParamCount(ObjectID objectId) { (void) objectId; } + + virtual void IModule_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IModule_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IModule_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void IModule_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void IModule_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IModule_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IModule_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void IModule_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void IModule_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // IEntryPoint + virtual void IEntryPoint_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void IEntryPoint_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void IEntryPoint_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void IEntryPoint_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void IEntryPoint_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void IEntryPoint_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IEntryPoint_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IEntryPoint_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void IEntryPoint_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // ICompositeComponentType + virtual void ICompositeComponentType_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void ICompositeComponentType_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void ICompositeComponentType_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void ICompositeComponentType_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void ICompositeComponentType_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void ICompositeComponentType_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ICompositeComponentType_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void ICompositeComponentType_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // ITypeConformance + virtual void ITypeConformance_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void ITypeConformance_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void ITypeConformance_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void ITypeConformance_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void ITypeConformance_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void ITypeConformance_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ITypeConformance_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ITypeConformance_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void ITypeConformance_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + }; +} + + +#endif // DECODER_CONSUMER_H diff --git a/source/slang-record-replay/replay/decoder-helper.cpp b/source/slang-record-replay/replay/decoder-helper.cpp new file mode 100644 index 000000000..c9252bbc6 --- /dev/null +++ b/source/slang-record-replay/replay/decoder-helper.cpp @@ -0,0 +1,60 @@ +#include <cstdlib> +#include <vector> +#include "decoder-helper.h" +#include "parameter-decoder.h" + +namespace SlangRecord +{ + DecoderAllocatorSingleton* DecoderAllocatorSingleton::getInstance() + { + thread_local DecoderAllocatorSingleton instance; + return &instance; + } + + void* DecoderAllocatorSingleton::allocate(size_t size) + { + void* data = calloc(1, size); + + if (!data) + { + slangRecordLog(LogLevel::Error, "Failed to allocate memory\n"); + std::abort(); + } + + m_allocations.add(data); + return data; + } + + DecoderAllocatorSingleton::~DecoderAllocatorSingleton() + { + for (auto allocation : m_allocations) + { + free(allocation); + } + } + + template <typename T, typename U> + size_t StructDecoder<T, U>::decode(const uint8_t* buffer, int64_t bufferSize) + { + return ParameterDecoder::decodeStruct(buffer, bufferSize, *this); + } + + size_t BlobDecoder::decode(const uint8_t* buffer, int64_t bufferSize) + { + size_t readByte = 0; + readByte = ParameterDecoder::decodeAddress(buffer, bufferSize, m_address); + + if (!m_address) + { + readByte += ParameterDecoder::decodePointer(buffer + readByte, bufferSize - readByte, m_blobData); + } + return readByte; + } + + template class StructDecoder<slang::SessionDesc>; + template class StructDecoder<slang::PreprocessorMacroDesc>; + template class StructDecoder<slang::CompilerOptionEntry>; + template class StructDecoder<slang::CompilerOptionValue>; + template class StructDecoder<slang::TargetDesc>; + template class StructDecoder<slang::SpecializationArg>; +} diff --git a/source/slang-record-replay/replay/decoder-helper.h b/source/slang-record-replay/replay/decoder-helper.h new file mode 100644 index 000000000..c109348e9 --- /dev/null +++ b/source/slang-record-replay/replay/decoder-helper.h @@ -0,0 +1,109 @@ +#ifndef SLANG_DECODER_HELPER_H +#define SLANG_DECODER_HELPER_H + +#include <stdint.h> +#include "slang.h" +#include "slang-com-helper.h" +#include "../util/record-format.h" +#include "../../core/slang-list.h" + +namespace SlangRecord { + + // This class is used to allocate memory for the type decoder + class DecoderAllocatorSingleton + { + public: + static DecoderAllocatorSingleton* getInstance(); + void* allocate(size_t size); + ~DecoderAllocatorSingleton(); + private: + DecoderAllocatorSingleton() = default; + Slang::List<void*> m_allocations; + }; + + class DecoderBase + { + public: + virtual ~DecoderBase() = default; + void* allocate(size_t size) { return m_allocator->allocate(size); } + protected: + DecoderAllocatorSingleton* m_allocator = DecoderAllocatorSingleton::getInstance(); + }; + + // We don't allow pointer type to be used as a template parameter + template <typename T, typename U = typename std::enable_if< !std::is_pointer<T>::value >::type> + class ValueDecoder : public DecoderBase + { + public: + T& getValue() { return m_value;} + + protected: + T m_value {}; + }; + + template <typename T, typename = typename std::enable_if< !std::is_pointer<T>::value >::type> + class StructDecoder : public ValueDecoder<T> + { + public: + using Super = ValueDecoder<T>; + size_t decode(const uint8_t* buffer, int64_t bufferSize); + }; + + // We only allow pointer type to be used as a template parameter + template <typename T, typename U = typename std::enable_if< std::is_pointer<T>::value >::type> + class PointerDecoder : public DecoderBase + { + public: + void setPointer(void* data) { m_pointer = static_cast<T>(data); } + T getPointer() const { return m_pointer; } + void setPointerAddress(uint64_t address) { m_pointerAddress = address; } + void setDataSize(size_t size) { m_dataSize = size; } + size_t getDataSize() const { return m_dataSize; } + private: + T m_pointer {nullptr}; + uint64_t m_pointerAddress = 0; + size_t m_dataSize = 0; + }; + + class BlobDecoder + { + private: + PointerDecoder<void*> m_blobData; + + class BlobImpl : public slang::IBlob + { + public: + // ISlangUnknown + virtual SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) override + { + if (uuid == ISlangUnknown::getTypeGuid() || + uuid == ISlangBlob::getTypeGuid()) + { + *outObject = static_cast<ISlangBlob*>(this); + return SLANG_OK; + } + *outObject = nullptr; + return SLANG_E_NO_INTERFACE; + } + + virtual uint32_t SLANG_MCALL addRef() override { return 1; } + virtual uint32_t SLANG_MCALL release() override { return 1; } + + BlobImpl(const PointerDecoder<void*>* blobData) : m_pBlobData(blobData) {} + virtual const void* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_pBlobData->getPointer();} + virtual size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_pBlobData->getDataSize(); } + private: + const PointerDecoder<void*>* m_pBlobData; + }; + + BlobImpl m_blobImpl {&m_blobData}; + AddressFormat m_address {0}; + public: + size_t decode(const uint8_t* buffer, int64_t bufferSize); + slang::IBlob* getBlob() { return &m_blobImpl; } + }; + + using StringDecoder = PointerDecoder<char*>; +} // namespace SlangRecord + +#endif // SLANG_RECORD_DECODER_HELPER_H diff --git a/source/slang-record-replay/replay/json-consumer.cpp b/source/slang-record-replay/replay/json-consumer.cpp new file mode 100644 index 000000000..a3ea0c31f --- /dev/null +++ b/source/slang-record-replay/replay/json-consumer.cpp @@ -0,0 +1,477 @@ +#include "json-consumer.h" + +namespace SlangRecord +{ + void JsonConsumer::CreateGlobalSession(ObjectID objectId, const uint8_t* parameterBuffer, int64_t bufferSize) + { + } + + void JsonConsumer::IGlobalSession_createSession(ObjectID objectId, slang::SessionDesc const& desc, ObjectID outSessionId) + { + } + + + void JsonConsumer::IGlobalSession_findProfile(ObjectID objectId, char const* name) + { + } + + + void JsonConsumer::IGlobalSession_setDownstreamCompilerPath(ObjectID objectId, SlangPassThrough passThrough, char const* path) + { + } + + + void JsonConsumer::IGlobalSession_setDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, char const* prelude) + { + } + + + void JsonConsumer::IGlobalSession_getDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, ObjectID outPreludeId) + { + } + + + void JsonConsumer::IGlobalSession_setDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) + { + } + + + void JsonConsumer::IGlobalSession_getDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage) + { + } + + + void JsonConsumer::IGlobalSession_setLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, char const* prelude) + { + } + + + void JsonConsumer::IGlobalSession_getLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, ObjectID outPreludeId) + { + } + + + void JsonConsumer::IGlobalSession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequest) + { + } + + + void JsonConsumer::IGlobalSession_addBuiltins(ObjectID objectId, char const* sourcePath, char const* sourceString) + { + } + + + void JsonConsumer::IGlobalSession_setSharedLibraryLoader(ObjectID objectId, ObjectID loaderId) + { + } + + + void JsonConsumer::IGlobalSession_getSharedLibraryLoader(ObjectID objectId, ObjectID outLoaderId) + { + } + + + void JsonConsumer::IGlobalSession_checkCompileTargetSupport(ObjectID objectId, SlangCompileTarget target) + { + } + + + void JsonConsumer::IGlobalSession_checkPassThroughSupport(ObjectID objectId, SlangPassThrough passThrough) + { + } + + + void JsonConsumer::IGlobalSession_compileStdLib(ObjectID objectId, slang::CompileStdLibFlags flags) + { + } + + + void JsonConsumer::IGlobalSession_loadStdLib(ObjectID objectId, const void* stdLib, size_t stdLibSizeInBytes) + { + } + + + void JsonConsumer::IGlobalSession_saveStdLib(ObjectID objectId, SlangArchiveType archiveType, ObjectID outBlobId) + { + } + + + void JsonConsumer::IGlobalSession_findCapability(ObjectID objectId, char const* name) + { + } + + + void JsonConsumer::IGlobalSession_setDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) + { + } + + + void JsonConsumer::IGlobalSession_getDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target) + { + } + + + void JsonConsumer::IGlobalSession_setSPIRVCoreGrammar(ObjectID objectId, char const* jsonPath) + { + } + + + void JsonConsumer::IGlobalSession_parseCommandLineArguments(ObjectID objectId, int argc, const char* const* argv, ObjectID outSessionDescId, ObjectID outAllocationId) + { + } + + + void JsonConsumer::IGlobalSession_getSessionDescDigest(ObjectID objectId, slang::SessionDesc* sessionDesc, ObjectID outBlobId) + { + } + + + + // ISession + void JsonConsumer::ISession_getGlobalSession(ObjectID objectId, ObjectID outGlobalSessionId) + { + } + + + void JsonConsumer::ISession_loadModule(ObjectID objectId, const char* moduleName, ObjectID outDiagnostics, ObjectID outModuleId) + { + } + + void JsonConsumer::ISession_loadModuleFromIRBlob(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) + { + } + + + void JsonConsumer::ISession_loadModuleFromSource(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) + { + } + + + void JsonConsumer::ISession_loadModuleFromSourceString(ObjectID objectId, const char* moduleName, + const char* path, const char* string, ObjectID outDiagnosticsId, ObjectID outModuleId) + { + } + + + void JsonConsumer::ISession_createCompositeComponentType(ObjectID objectId, ObjectID* componentTypeIds, + SlangInt componentTypeCount, ObjectID outCompositeComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::ISession_specializeType(ObjectID objectId, ObjectID typeId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) + { + } + + void JsonConsumer::ISession_getTypeLayout(ObjectID objectId, ObjectID typeId, SlangInt targetIndex, + slang::LayoutRules rules, ObjectID outDiagnosticsId, ObjectID outTypeLayoutReflection) + { + } + + void JsonConsumer::ISession_getContainerType(ObjectID objectId, ObjectID elementType, + slang::ContainerType containerType, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) + { + } + + void JsonConsumer::ISession_getDynamicType(ObjectID objectId, ObjectID outTypeReflectionId) + { + } + + void JsonConsumer::ISession_getTypeRTTIMangledName(ObjectID objectId, ObjectID typeId, ObjectID outNameBlobId) + { + } + + void JsonConsumer::ISession_getTypeConformanceWitnessMangledName(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outNameBlobId) + { + } + + + void JsonConsumer::ISession_getTypeConformanceWitnessSequentialID(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, uint32_t outId) + { + } + + void JsonConsumer::ISession_createTypeConformanceComponentType(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outConformanceId, + SlangInt conformanceIdOverride, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::ISession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequestId) + { + } + + + void JsonConsumer::ISession_getLoadedModule(ObjectID objectId, SlangInt index, ObjectID outModuleId) + { + } + + + + // IModule + void JsonConsumer::IModule_findEntryPointByName(ObjectID objectId, char const* name, ObjectID outEntryPointId) + { + } + + + void JsonConsumer::IModule_getDefinedEntryPoint(ObjectID objectId, SlangInt32 index, ObjectID outEntryPointId) + { + } + + + void JsonConsumer::IModule_serialize(ObjectID objectId, ObjectID outSerializedBlobId) + { + } + + + void JsonConsumer::IModule_writeToFile(ObjectID objectId, char const* fileName) + { + } + + + void JsonConsumer::IModule_findAndCheckEntryPoint(ObjectID objectId, char const* name, SlangStage stage, ObjectID outEntryPointId, ObjectID outDiagnostics) + { + } + + + + void JsonConsumer::IModule_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void JsonConsumer::IModule_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void JsonConsumer::IModule_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::IModule_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::IModule_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void JsonConsumer::IModule_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void JsonConsumer::IModule_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::IModule_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::IModule_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::IModule_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void JsonConsumer::IModule_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + + + // IEntryPoint + void JsonConsumer::IEntryPoint_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void JsonConsumer::IEntryPoint_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void JsonConsumer::IEntryPoint_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::IEntryPoint_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::IEntryPoint_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void JsonConsumer::IEntryPoint_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void JsonConsumer::IEntryPoint_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::IEntryPoint_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::IEntryPoint_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::IEntryPoint_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void JsonConsumer::IEntryPoint_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + + + // ICompositeComponentType + void JsonConsumer::ICompositeComponentType_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void JsonConsumer::ICompositeComponentType_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void JsonConsumer::ICompositeComponentType_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::ICompositeComponentType_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::ICompositeComponentType_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void JsonConsumer::ICompositeComponentType_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void JsonConsumer::ICompositeComponentType_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::ICompositeComponentType_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::ICompositeComponentType_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void JsonConsumer::ICompositeComponentType_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + + + // ITypeConformance + void JsonConsumer::ITypeConformance_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void JsonConsumer::ITypeConformance_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void JsonConsumer::ITypeConformance_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::ITypeConformance_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::ITypeConformance_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void JsonConsumer::ITypeConformance_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void JsonConsumer::ITypeConformance_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::ITypeConformance_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void JsonConsumer::ITypeConformance_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void JsonConsumer::ITypeConformance_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void JsonConsumer::ITypeConformance_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + +}; // namespace SlangRecord diff --git a/source/slang-record-replay/replay/json-consumer.h b/source/slang-record-replay/replay/json-consumer.h new file mode 100644 index 000000000..e638a833b --- /dev/null +++ b/source/slang-record-replay/replay/json-consumer.h @@ -0,0 +1,174 @@ +#ifndef JSON_CONSUMER_H +#define JSON_CONSUMER_H + +#include "decoder-consumer.h" + +namespace SlangRecord +{ + class JsonConsumer : public IDecoderConsumer + { + public: + virtual void CreateGlobalSession(ObjectID objectId, const uint8_t* parameterBuffer, int64_t bufferSize) = 0; + virtual void IGlobalSession_createSession(ObjectID objectId, slang::SessionDesc const& desc, ObjectID outSessionId) = 0; + virtual void IGlobalSession_findProfile(ObjectID objectId, char const* name) = 0; + virtual void IGlobalSession_setDownstreamCompilerPath(ObjectID objectId, SlangPassThrough passThrough, char const* path) = 0; + virtual void IGlobalSession_setDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, char const* prelude) = 0; + virtual void IGlobalSession_getDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, ObjectID outPreludeId) = 0; + + virtual void IGlobalSession_getBuildTagString(ObjectID objectId) { (void) objectId; } + + virtual void IGlobalSession_setDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) = 0; + virtual void IGlobalSession_getDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage) = 0; + virtual void IGlobalSession_setLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, char const* prelude) = 0; + virtual void IGlobalSession_getLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, ObjectID outPreludeId) = 0; + virtual void IGlobalSession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequest) = 0; + virtual void IGlobalSession_addBuiltins(ObjectID objectId, char const* sourcePath, char const* sourceString) = 0; + virtual void IGlobalSession_setSharedLibraryLoader(ObjectID objectId, ObjectID loaderId) = 0; + virtual void IGlobalSession_getSharedLibraryLoader(ObjectID objectId, ObjectID outLoaderId) = 0; + virtual void IGlobalSession_checkCompileTargetSupport(ObjectID objectId, SlangCompileTarget target) = 0; + virtual void IGlobalSession_checkPassThroughSupport(ObjectID objectId, SlangPassThrough passThrough) = 0; + virtual void IGlobalSession_compileStdLib(ObjectID objectId, slang::CompileStdLibFlags flags) = 0; + virtual void IGlobalSession_loadStdLib(ObjectID objectId, const void* stdLib, size_t stdLibSizeInBytes) = 0; + virtual void IGlobalSession_saveStdLib(ObjectID objectId, SlangArchiveType archiveType, ObjectID outBlobId) = 0; + virtual void IGlobalSession_findCapability(ObjectID objectId, char const* name) = 0; + virtual void IGlobalSession_setDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) = 0; + virtual void IGlobalSession_getDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target) = 0; + + virtual void IGlobalSession_getCompilerElapsedTime(ObjectID objectId) { (void) objectId; } + + virtual void IGlobalSession_setSPIRVCoreGrammar(ObjectID objectId, char const* jsonPath) = 0; + virtual void IGlobalSession_parseCommandLineArguments(ObjectID objectId, int argc, const char* const* argv, ObjectID outSessionDescId, ObjectID outAllocationId) = 0; + virtual void IGlobalSession_getSessionDescDigest(ObjectID objectId, slang::SessionDesc* sessionDesc, ObjectID outBlobId) = 0; + + // ISession + virtual void ISession_getGlobalSession(ObjectID objectId, ObjectID outGlobalSessionId) = 0; + virtual void ISession_loadModule(ObjectID objectId, const char* moduleName, ObjectID outDiagnostics, ObjectID outModuleId) = 0; + + virtual void ISession_loadModuleFromIRBlob(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_loadModuleFromSource(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_loadModuleFromSourceString(ObjectID objectId, const char* moduleName, + const char* path, const char* string, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_createCompositeComponentType(ObjectID objectId, ObjectID* componentTypeIds, + SlangInt componentTypeCount, ObjectID outCompositeComponentTypeIds, ObjectID outDiagnosticsId) = 0; + + virtual void ISession_specializeType(ObjectID objectId, ObjectID typeId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getTypeLayout(ObjectID objectId, ObjectID typeId, SlangInt targetIndex, + slang::LayoutRules rules, ObjectID outDiagnosticsId, ObjectID outTypeLayoutReflection) = 0; + + virtual void ISession_getContainerType(ObjectID objectId, ObjectID elementType, + slang::ContainerType containerType, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getDynamicType(ObjectID objectId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getTypeRTTIMangledName(ObjectID objectId, ObjectID typeId, ObjectID outNameBlobId) = 0; + + virtual void ISession_getTypeConformanceWitnessMangledName(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outNameBlobId) = 0; + + virtual void ISession_getTypeConformanceWitnessSequentialID(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, uint32_t outId) = 0; + + virtual void ISession_createTypeConformanceComponentType(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outConformanceId, + SlangInt conformanceIdOverride, ObjectID outDiagnosticsId) = 0; + + virtual void ISession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequestId) = 0; + + virtual void ISession_getLoadedModuleCount(ObjectID objectId) { (void) objectId; } + + virtual void ISession_getLoadedModule(ObjectID objectId, SlangInt index, ObjectID outModuleId) = 0; + + virtual void ISession_isBinaryModuleUpToDate(ObjectID objectId) { (void) objectId; } + + // IModule + virtual void IModule_findEntryPointByName(ObjectID objectId, char const* name, ObjectID outEntryPointId) = 0; + + virtual void IModule_getDefinedEntryPointCount(ObjectID objectId) { (void) objectId; } + + virtual void IModule_getDefinedEntryPoint(ObjectID objectId, SlangInt32 index, ObjectID outEntryPointId) = 0; + virtual void IModule_serialize(ObjectID objectId, ObjectID outSerializedBlobId) = 0; + virtual void IModule_writeToFile(ObjectID objectId, char const* fileName) = 0; + + virtual void IModule_getName(ObjectID objectId) { (void) objectId; } + virtual void IModule_getFilePath(ObjectID objectId) { (void) objectId; } + virtual void IModule_getUniqueIdentity(ObjectID objectId) { (void) objectId; } + + virtual void IModule_findAndCheckEntryPoint(ObjectID objectId, char const* name, SlangStage stage, ObjectID outEntryPointId, ObjectID outDiagnostics) = 0; + + virtual void IModule_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void IModule_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void IModule_getSpecializationParamCount(ObjectID objectId) { (void) objectId; } + + virtual void IModule_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IModule_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IModule_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void IModule_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void IModule_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IModule_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IModule_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void IModule_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void IModule_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // IEntryPoint + virtual void IEntryPoint_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void IEntryPoint_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void IEntryPoint_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void IEntryPoint_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void IEntryPoint_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void IEntryPoint_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IEntryPoint_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IEntryPoint_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void IEntryPoint_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // ICompositeComponentType + virtual void ICompositeComponentType_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void ICompositeComponentType_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void ICompositeComponentType_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void ICompositeComponentType_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void ICompositeComponentType_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void ICompositeComponentType_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ICompositeComponentType_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void ICompositeComponentType_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // ITypeConformance + virtual void ITypeConformance_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void ITypeConformance_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void ITypeConformance_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void ITypeConformance_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void ITypeConformance_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void ITypeConformance_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ITypeConformance_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ITypeConformance_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void ITypeConformance_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + }; +} +#endif // JSON_CONSUMER_H diff --git a/source/slang-record-replay/replay/parameter-decoder.cpp b/source/slang-record-replay/replay/parameter-decoder.cpp new file mode 100644 index 000000000..ed1c1dfe2 --- /dev/null +++ b/source/slang-record-replay/replay/parameter-decoder.cpp @@ -0,0 +1,215 @@ +#include <string.h> +#include "parameter-decoder.h" + +namespace SlangRecord +{ + size_t ParameterDecoder::decodeString(const uint8_t* buffer, int64_t bufferSize, PointerDecoder<char*>& typeDecoder) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + if (bufferSize < (int64_t)sizeof(uint32_t)) + { + return 0; + } + + uint32_t stringLength = 0; + size_t readByte = 0; + readByte += decodeUint32(buffer, bufferSize - readByte, stringLength); + + SLANG_RECORD_ASSERT(bufferSize >= (int64_t)(readByte + stringLength)); + + if (stringLength == 0) + { + return readByte; + } + + uint8_t* data = (uint8_t*)typeDecoder.allocate(stringLength + 1); + memcpy(data, buffer + readByte, stringLength); + typeDecoder.setPointer(data); + typeDecoder.setDataSize(stringLength + 1); + return readByte + stringLength; + } + + size_t ParameterDecoder::decodePointer(const uint8_t* buffer, int64_t bufferSize, PointerDecoder<void*>& pointerDecoder) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + if (bufferSize < (int64_t)sizeof(uint32_t)) + { + return 0; + } + + uint64_t address = 0; + size_t readByte = decodeAddress(buffer, bufferSize, address); + pointerDecoder.setPointerAddress(address); + + uint64_t dataSize = 0; + readByte += decodeUint64(buffer + readByte, bufferSize - readByte, dataSize); + + // return if the data size is 0 + if (dataSize == 0) + { + return readByte; + } + + SLANG_RECORD_ASSERT(bufferSize >= (int64_t)(readByte + dataSize)); + + uint8_t* data = (uint8_t*)pointerDecoder.allocate(dataSize); + memcpy(data, buffer + readByte, dataSize); + pointerDecoder.setPointer(data); + pointerDecoder.setDataSize(dataSize); + return readByte + dataSize; + } + + size_t ParameterDecoder::decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::SessionDesc>& sessionDesc) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + if(bufferSize < (int64_t)sizeof(uint64_t)) + { + return 0; + } + + size_t readByte = 0; + slang::SessionDesc& desc = sessionDesc.getValue(); + + uint64_t structSize = 0; + readByte = decodeUint64(buffer, bufferSize, structSize); + desc.structureSize = structSize; + + readByte += decodeInt64(buffer + readByte, bufferSize - readByte, desc.targetCount); + + if (desc.targetCount > 0) + { + slang::TargetDesc* targets = (slang::TargetDesc*)sessionDesc.allocate(sizeof(slang::TargetDesc) * desc.targetCount); + readByte += decodeStructArray(buffer + readByte, bufferSize - readByte, targets, desc.targetCount); + desc.targets = targets; + } + + readByte += decodeUint32(buffer + readByte, bufferSize - readByte, desc.flags); + readByte += decodeEnumValue(buffer + readByte, bufferSize - readByte, desc.defaultMatrixLayoutMode); + readByte += decodeInt64(buffer + readByte, bufferSize - readByte, desc.searchPathCount); + + if (desc.searchPathCount > 0) + { + char** searchPaths = (char**)sessionDesc.allocate(sizeof(char*) * desc.searchPathCount); + decodeStringArray(buffer + readByte, bufferSize - readByte, searchPaths, desc.searchPathCount); + desc.searchPaths = searchPaths; + } + + readByte += decodeInt64(buffer + readByte, bufferSize - readByte, desc.preprocessorMacroCount); + if (desc.preprocessorMacroCount > 0) + { + slang::PreprocessorMacroDesc* macros = (slang::PreprocessorMacroDesc*) + sessionDesc.allocate(sizeof(slang::PreprocessorMacroDesc) * desc.preprocessorMacroCount); + readByte += decodeStructArray(buffer + readByte, bufferSize - readByte, macros, desc.preprocessorMacroCount); + desc.preprocessorMacros = macros; + } + + readByte += decodeBool(buffer + readByte, bufferSize - readByte, desc.enableEffectAnnotations); + readByte += decodeBool(buffer + readByte, bufferSize - readByte, desc.allowGLSLSyntax); + readByte += decodeUint32(buffer + readByte, bufferSize - readByte, desc.compilerOptionEntryCount); + + if (desc.compilerOptionEntryCount > 0) + { + slang::CompilerOptionEntry* entries = (slang::CompilerOptionEntry*) + sessionDesc.allocate(sizeof(slang::CompilerOptionEntry) * desc.compilerOptionEntryCount); + readByte += decodeStructArray(buffer + readByte, bufferSize - readByte, entries, desc.compilerOptionEntryCount); + desc.compilerOptionEntries = entries; + } + + return readByte; + } + + size_t ParameterDecoder::decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::PreprocessorMacroDesc>& desc) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t readByte = 0; + PointerDecoder<char*> name; + PointerDecoder<char*> value; + + readByte = decodeString(buffer, bufferSize, name); + readByte += decodeString(buffer + readByte, bufferSize - readByte, value); + + desc.getValue().name = name.getPointer(); + desc.getValue().value = value.getPointer(); + + return readByte; + } + + size_t ParameterDecoder::decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::CompilerOptionEntry>& entry) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t readByte = 0; + readByte = decodeEnumValue(buffer, bufferSize, entry.getValue().name); + + ValueDecoder<slang::CompilerOptionValue> value; + readByte += decodeStruct(buffer + readByte, bufferSize - readByte, value); + entry.getValue().value = value.getValue(); + + return readByte; + } + + size_t ParameterDecoder::decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::CompilerOptionValue>& value) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t readByte = 0; + readByte = decodeEnumValue(buffer, bufferSize, value.getValue().kind); + readByte += decodeInt32(buffer + readByte, bufferSize - readByte, value.getValue().intValue0); + + PointerDecoder<char*> stringValue0; + readByte += decodeString(buffer + readByte, bufferSize - readByte, stringValue0); + value.getValue().stringValue0 = stringValue0.getPointer(); + + PointerDecoder<char*> stringValue1; + readByte += decodeString(buffer + readByte, bufferSize - readByte, stringValue1); + value.getValue().stringValue1 = stringValue1.getPointer(); + return 0; + } + + size_t ParameterDecoder::decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::TargetDesc>& targetDesc) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t readByte = 0; + uint64_t structSize = 0; + readByte = decodeUint64(buffer, bufferSize, structSize); + targetDesc.getValue().structureSize = structSize; + + readByte += decodeEnumValue(buffer + readByte, bufferSize - readByte, targetDesc.getValue().format); + readByte += decodeEnumValue(buffer + readByte, bufferSize - readByte, targetDesc.getValue().profile); + readByte += decodeEnumValue(buffer + readByte, bufferSize - readByte, targetDesc.getValue().flags); + readByte += decodeEnumValue(buffer + readByte, bufferSize - readByte, targetDesc.getValue().floatingPointMode); + readByte += decodeEnumValue(buffer + readByte, bufferSize - readByte, targetDesc.getValue().lineDirectiveMode); + readByte += decodeBool(buffer + readByte, bufferSize - readByte, targetDesc.getValue().forceGLSLScalarBufferLayout); + readByte += decodeUint32(buffer + readByte, bufferSize - readByte, targetDesc.getValue().compilerOptionEntryCount); + + if (targetDesc.getValue().compilerOptionEntryCount > 0) + { + slang::CompilerOptionEntry* entries = (slang::CompilerOptionEntry*) + targetDesc.allocate(sizeof(slang::CompilerOptionEntry) * targetDesc.getValue().compilerOptionEntryCount); + readByte += decodeStructArray(buffer + readByte, bufferSize - readByte, entries, targetDesc.getValue().compilerOptionEntryCount); + targetDesc.getValue().compilerOptionEntries = entries; + } + + return readByte; + } + + size_t ParameterDecoder::decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::SpecializationArg>& specializationArg) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t readByte = 0; + readByte = decodeEnumValue(buffer, bufferSize, specializationArg.getValue().kind); + + // TODO: Special handle to address decode is needed. + uint64_t address = 0; + readByte += decodeAddress(buffer + readByte, bufferSize - readByte, address); + (void)address; + + return readByte; + } +} diff --git a/source/slang-record-replay/replay/parameter-decoder.h b/source/slang-record-replay/replay/parameter-decoder.h new file mode 100644 index 000000000..5d6f40987 --- /dev/null +++ b/source/slang-record-replay/replay/parameter-decoder.h @@ -0,0 +1,131 @@ +#ifndef PARAMETER_DECODER_H +#define PARAMETER_DECODER_H + +#include <cinttypes> +#include <cstring> +#include <cstdlib> +#include <vector> +#include "../util/record-format.h" +#include "../util/record-utility.h" +#include "slang.h" +#include "decoder-helper.h" + +namespace SlangRecord +{ + class ParameterDecoder + { + public: + static size_t decodeInt8(const uint8_t* buffer, int64_t bufferSize, int8_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeUint8(const uint8_t* buffer, int64_t bufferSize, uint8_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeInt16(const uint8_t* buffer, int64_t bufferSize, int16_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeUint16(const uint8_t* buffer, int64_t bufferSize, uint16_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeInt32(const uint8_t* buffer, int64_t bufferSize, int32_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeUint32(const uint8_t* buffer, int64_t bufferSize, uint32_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeInt64(const uint8_t* buffer, int64_t bufferSize, int64_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeUint64(const uint8_t* buffer, int64_t bufferSize, uint64_t& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeFloat(const uint8_t* buffer, int64_t bufferSize, float& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeDouble(const uint8_t* buffer, int64_t bufferSize, double& value) { return decodeValue(buffer, bufferSize, value); } + static size_t decodeBool(const uint8_t* buffer, int64_t bufferSize, bool& value) { return decodeValue(buffer, bufferSize, value); } + + template<typename T> + static size_t decodeEnumValue(const uint8_t* buffer, size_t bufferSize, T& value) + { + uint32_t decodedValue; + size_t readByte = decodeValue(buffer, bufferSize, decodedValue); + value = static_cast<T>(decodedValue); + return readByte; + } + + static size_t decodeString(const uint8_t* buffer, int64_t bufferSize, PointerDecoder<char*>& typeDecoder); + + static size_t decodePointer(const uint8_t* buffer, int64_t bufferSize, PointerDecoder<void*>& pointerDecoder); + + static size_t decodeAddress(const uint8_t* buffer, int64_t bufferSize, SlangRecord::AddressFormat& address) + { + return decodeValue(buffer, bufferSize, address); + } + static size_t decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::SessionDesc>& sessionDesc); + static size_t decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::PreprocessorMacroDesc>& desc); + static size_t decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::CompilerOptionEntry>& entry); + static size_t decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::CompilerOptionValue>& value); + static size_t decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::TargetDesc>& targetDesc); + static size_t decodeStruct(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<slang::SpecializationArg>& specializationArg); + + template <typename T> + static size_t decodeValueArray(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<T>* valueArray, size_t count) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t readByte = 0; + for (size_t i = 0; i < count; ++i) + { + readByte += decodeValue(buffer + readByte, bufferSize - readByte, valueArray[i]); + } + return readByte; + } + + static size_t decodeStringArray(const uint8_t* buffer, int64_t bufferSize, char** outputArray, size_t count) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t readByte = 0; + for (uint32_t i = 0; i < count; i++) + { + PointerDecoder<char*> item; + readByte += decodeString(buffer + readByte, bufferSize - readByte, item); + + // Copy the search path + outputArray[i] = item.getPointer(); + } + return readByte; + } + + template <typename T> + static size_t decodeStructArray(const uint8_t* buffer, int64_t bufferSize, T* outputArray, size_t count) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t bufferRead = 0; + for (size_t i = 0; i < count; ++i) + { + ValueDecoder<T> item; + bufferRead += decodeStruct(buffer + bufferRead, bufferSize - bufferRead, item); + outputArray[i] = item.getValue(); + } + return bufferRead; + } + + static size_t decodeAddressArray(const uint8_t* buffer, int64_t bufferSize, uint64_t* addressArray, size_t count) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + size_t bufferRead = 0; + for (size_t i = 0; i < count; ++i) + { + bufferRead += decodeAddress(buffer + bufferRead, bufferSize - bufferRead, addressArray[i]); + } + + return bufferRead; + } + + + private: + template <typename T> + static size_t decodeValue(const uint8_t* buffer, int64_t bufferSize, T& value) + { + SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + + int64_t dataSize = sizeof(T); + + SLANG_RECORD_ASSERT(bufferSize >= dataSize); + + size_t bytesRead = 0; + bytesRead = dataSize; + memcpy(&value, buffer, dataSize); + + return bytesRead; + } + }; +} // namespace SlangRecord + +#endif // PARAMETER_DECODER_H diff --git a/source/slang-record-replay/replay/recordFile-processor.cpp b/source/slang-record-replay/replay/recordFile-processor.cpp new file mode 100644 index 000000000..bf9cec435 --- /dev/null +++ b/source/slang-record-replay/replay/recordFile-processor.cpp @@ -0,0 +1,132 @@ +#include "recordFile-processor.h" +#include "../util/record-utility.h" +#include "parameter-decoder.h" + +namespace SlangRecord +{ + RecordFileProcessor::RecordFileProcessor(const std::string& filename) + { + Slang::String path(filename.c_str()); + Slang::FileMode fileMode = Slang::FileMode::Open; + Slang::FileAccess fileAccess = Slang::FileAccess::Read; + Slang::FileShare fileShare = Slang::FileShare::None; + + // Open the record file with read-only access + SlangResult res = m_inputStream.init(path, fileMode, fileAccess, fileShare); + + if (res != SLANG_OK) + { + SlangRecord::slangRecordLog(SlangRecord::LogLevel::Error, "Failed to open file %s\n", filename.c_str()); + std::abort(); + } + } + + bool RecordFileProcessor::processNextBlock() + { + FunctionHeader header {}; + if (!processHeader(header)) + { + return false; + } + + ApiClassId classId = static_cast<ApiClassId>(getClassId(header.callId)); + + // capacity comparison will be performed in the reserve call, so we can safely call reserve + m_parameterBuffer.reserve(header.dataSizeInBytes); + + size_t readBytes = 0; + SlangResult res = SLANG_OK; + + if (header.dataSizeInBytes) + { + res = m_inputStream.read(m_parameterBuffer.getBuffer(), header.dataSizeInBytes, readBytes); + } + + if (res != SLANG_OK || readBytes != header.dataSizeInBytes) + { + return false; + } + + FunctionTailer tailer {}; + if (!processTailer(tailer)) + { + return false; + } + + if (tailer.dataSizeInBytes) + { + m_outputBuffer.reserve(tailer.dataSizeInBytes); + res = m_inputStream.read(m_outputBuffer.getBuffer(), tailer.dataSizeInBytes, readBytes); + + if (res != SLANG_OK || readBytes != tailer.dataSizeInBytes) + { + return false; + } + } + + bool ret = false; + SlangDecoder::ParameterBlock paramBlock {}; + paramBlock.parameterBuffer = m_parameterBuffer.getBuffer(); + paramBlock.parameterBufferSize = header.dataSizeInBytes; + paramBlock.outputBuffer = m_outputBuffer.getBuffer(); + paramBlock.outputBufferSize = tailer.dataSizeInBytes; + + if (classId == GlobalFunction) + { + ret = m_decoder.processFunctionCall(header, paramBlock); + } + else + { + ret = m_decoder.processMethodCall(header, paramBlock); + } + + m_parameterBuffer.clear(); + return ret; + } + + bool RecordFileProcessor::processHeader(FunctionHeader& header) + { + size_t readBytes = 0; + SlangResult res = m_inputStream.read(&header, sizeof(FunctionHeader), readBytes); + + if (res != SLANG_OK || readBytes != sizeof(FunctionHeader)) + { + return false; + } + + if (header.magic != MAGIC_HEADER || header.callId == ApiCallId::InvalidCallId) + { + return false; + } + + return true; + } + + bool RecordFileProcessor::processTailer(FunctionTailer& tailer) + { + size_t readBytes = 0; + SlangResult res = m_inputStream.read(&tailer, sizeof(FunctionTailer), readBytes); + + if (res != SLANG_OK || readBytes != sizeof(FunctionTailer)) + { + return false; + } + + if (tailer.magic != MAGIC_TAILER) + { + return false; + } + + return true; + } + + bool RecordFileProcessor::processMethod(FunctionHeader const& header, const uint8_t* parameterBuffer, int64_t bufferSize) + { + return false; + } + + bool RecordFileProcessor::processFunction(FunctionHeader const& header, const uint8_t* parameterBuffer, int64_t bufferSize) + { + return false; + } +}; // namespace SlangRecord diff --git a/source/slang-record-replay/replay/recordFile-processor.h b/source/slang-record-replay/replay/recordFile-processor.h new file mode 100644 index 000000000..b9570a259 --- /dev/null +++ b/source/slang-record-replay/replay/recordFile-processor.h @@ -0,0 +1,30 @@ +#ifndef FILE_PROCESSOR_H +#define FILE_PROCESSOR_H + +#include <string> +#include "../../core/slang-stream.h" +#include "../util/record-format.h" +#include "slang-decoder.h" + +namespace SlangRecord +{ + class RecordFileProcessor + { + public: + RecordFileProcessor(const std::string& filePath); + bool processNextBlock(); + bool processHeader(FunctionHeader& header); + bool processTailer(FunctionTailer& tailer); + bool processMethod(FunctionHeader const& header, const uint8_t* buffer, int64_t bufferSize); + bool processFunction(FunctionHeader const& header, const uint8_t* buffer, int64_t bufferSize); + private: + Slang::FileStream m_inputStream; + Slang::List<uint8_t> m_parameterBuffer; + Slang::List<uint8_t> m_outputBuffer; + + SlangDecoder m_decoder; + }; + +} // namespace SlangRecord; + +#endif // FILE_PROCESSOR_H diff --git a/source/slang-record-replay/replay/replay-consumer.cpp b/source/slang-record-replay/replay/replay-consumer.cpp new file mode 100644 index 000000000..51aa2d1b1 --- /dev/null +++ b/source/slang-record-replay/replay/replay-consumer.cpp @@ -0,0 +1,481 @@ +#include "replay-consumer.h" + +namespace SlangRecord +{ + void ReplayConsumer::CreateGlobalSession(ObjectID objectId, const uint8_t* parameterBuffer, int64_t bufferSize) + { + } + + void ReplayConsumer::IGlobalSession_createSession(ObjectID objectId, slang::SessionDesc const& desc, ObjectID outSessionId) + { + } + + + void ReplayConsumer::IGlobalSession_findProfile(ObjectID objectId, char const* name) + { + } + + + void ReplayConsumer::IGlobalSession_setDownstreamCompilerPath(ObjectID objectId, SlangPassThrough passThrough, char const* path) + { + } + + + void ReplayConsumer::IGlobalSession_setDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, char const* prelude) + { + } + + + void ReplayConsumer::IGlobalSession_getDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, ObjectID outPreludeId) + { + } + + + void ReplayConsumer::IGlobalSession_setDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) + { + } + + + void ReplayConsumer::IGlobalSession_getDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage) + { + } + + + void ReplayConsumer::IGlobalSession_setLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, char const* prelude) + { + } + + + void ReplayConsumer::IGlobalSession_getLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, ObjectID outPreludeId) + { + } + + + void ReplayConsumer::IGlobalSession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequest) + { + } + + + void ReplayConsumer::IGlobalSession_addBuiltins(ObjectID objectId, char const* sourcePath, char const* sourceString) + { + } + + + void ReplayConsumer::IGlobalSession_setSharedLibraryLoader(ObjectID objectId, ObjectID loaderId) + { + } + + + void ReplayConsumer::IGlobalSession_getSharedLibraryLoader(ObjectID objectId, ObjectID outLoaderId) + { + } + + + void ReplayConsumer::IGlobalSession_checkCompileTargetSupport(ObjectID objectId, SlangCompileTarget target) + { + } + + + void ReplayConsumer::IGlobalSession_checkPassThroughSupport(ObjectID objectId, SlangPassThrough passThrough) + { + } + + + void ReplayConsumer::IGlobalSession_compileStdLib(ObjectID objectId, slang::CompileStdLibFlags flags) + { + } + + + void ReplayConsumer::IGlobalSession_loadStdLib(ObjectID objectId, const void* stdLib, size_t stdLibSizeInBytes) + { + } + + + void ReplayConsumer::IGlobalSession_saveStdLib(ObjectID objectId, SlangArchiveType archiveType, ObjectID outBlobId) + { + } + + + void ReplayConsumer::IGlobalSession_findCapability(ObjectID objectId, char const* name) + { + } + + + void ReplayConsumer::IGlobalSession_setDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) + { + } + + + void ReplayConsumer::IGlobalSession_getDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target) + { + } + + + void ReplayConsumer::IGlobalSession_setSPIRVCoreGrammar(ObjectID objectId, char const* jsonPath) + { + } + + + void ReplayConsumer::IGlobalSession_parseCommandLineArguments(ObjectID objectId, int argc, const char* const* argv, ObjectID outSessionDescId, ObjectID outAllocationId) + { + } + + + void ReplayConsumer::IGlobalSession_getSessionDescDigest(ObjectID objectId, slang::SessionDesc* sessionDesc, ObjectID outBlobId) + { + } + + + + // ISession + void ReplayConsumer::ISession_getGlobalSession(ObjectID objectId, ObjectID outGlobalSessionId) + { + } + + + void ReplayConsumer::ISession_loadModule(ObjectID objectId, const char* moduleName, ObjectID outDiagnostics, ObjectID outModuleId) + { + } + + + void ReplayConsumer::ISession_loadModuleFromIRBlob(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) + { + } + + + void ReplayConsumer::ISession_loadModuleFromSource(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) + { + } + + + void ReplayConsumer::ISession_loadModuleFromSourceString(ObjectID objectId, const char* moduleName, + const char* path, const char* string, ObjectID outDiagnosticsId, ObjectID outModuleId) + { + } + + + void ReplayConsumer::ISession_createCompositeComponentType(ObjectID objectId, ObjectID* componentTypeIds, + SlangInt componentTypeCount, ObjectID outCompositeComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::ISession_specializeType(ObjectID objectId, ObjectID typeId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) + { + } + + + + void ReplayConsumer::ISession_getTypeLayout(ObjectID objectId, ObjectID typeId, SlangInt targetIndex, + slang::LayoutRules rules, ObjectID outDiagnosticsId, ObjectID outTypeLayoutReflection) + { + } + + void ReplayConsumer::ISession_getContainerType(ObjectID objectId, ObjectID elementType, + slang::ContainerType containerType, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) + { + } + + void ReplayConsumer::ISession_getDynamicType(ObjectID objectId, ObjectID outTypeReflectionId) + { + } + + void ReplayConsumer::ISession_getTypeRTTIMangledName(ObjectID objectId, ObjectID typeId, ObjectID outNameBlobId) + { + } + + void ReplayConsumer::ISession_getTypeConformanceWitnessMangledName(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outNameBlobId) + { + } + + + void ReplayConsumer::ISession_getTypeConformanceWitnessSequentialID(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, uint32_t outId) + { + } + + void ReplayConsumer::ISession_createTypeConformanceComponentType(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outConformanceId, + SlangInt conformanceIdOverride, ObjectID outDiagnosticsId) + { + } + + + + void ReplayConsumer::ISession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequestId) + { + } + + + void ReplayConsumer::ISession_getLoadedModule(ObjectID objectId, SlangInt index, ObjectID outModuleId) + { + } + + + + // IModule + void ReplayConsumer::IModule_findEntryPointByName(ObjectID objectId, char const* name, ObjectID outEntryPointId) + { + } + + + void ReplayConsumer::IModule_getDefinedEntryPoint(ObjectID objectId, SlangInt32 index, ObjectID outEntryPointId) + { + } + + + void ReplayConsumer::IModule_serialize(ObjectID objectId, ObjectID outSerializedBlobId) + { + } + + + void ReplayConsumer::IModule_writeToFile(ObjectID objectId, char const* fileName) + { + } + + + void ReplayConsumer::IModule_findAndCheckEntryPoint(ObjectID objectId, char const* name, SlangStage stage, ObjectID outEntryPointId, ObjectID outDiagnostics) + { + } + + + + void ReplayConsumer::IModule_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void ReplayConsumer::IModule_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void ReplayConsumer::IModule_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::IModule_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::IModule_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void ReplayConsumer::IModule_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void ReplayConsumer::IModule_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::IModule_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::IModule_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::IModule_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void ReplayConsumer::IModule_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + + + // IEntryPoint + void ReplayConsumer::IEntryPoint_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void ReplayConsumer::IEntryPoint_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void ReplayConsumer::IEntryPoint_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::IEntryPoint_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::IEntryPoint_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void ReplayConsumer::IEntryPoint_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void ReplayConsumer::IEntryPoint_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::IEntryPoint_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::IEntryPoint_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::IEntryPoint_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void ReplayConsumer::IEntryPoint_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + + + // ICompositeComponentType + void ReplayConsumer::ICompositeComponentType_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void ReplayConsumer::ICompositeComponentType_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void ReplayConsumer::ICompositeComponentType_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::ICompositeComponentType_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::ICompositeComponentType_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void ReplayConsumer::ICompositeComponentType_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void ReplayConsumer::ICompositeComponentType_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::ICompositeComponentType_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::ICompositeComponentType_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void ReplayConsumer::ICompositeComponentType_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + + + // ITypeConformance + void ReplayConsumer::ITypeConformance_getSession(ObjectID objectId, ObjectID outSessionId) + { + } + + + void ReplayConsumer::ITypeConformance_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) + { + } + + + void ReplayConsumer::ITypeConformance_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::ITypeConformance_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::ITypeConformance_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) + { + } + + + void ReplayConsumer::ITypeConformance_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) + { + } + + + void ReplayConsumer::ITypeConformance_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::ITypeConformance_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) + { + } + + + void ReplayConsumer::ITypeConformance_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) + { + } + + + void ReplayConsumer::ITypeConformance_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) + { + } + + + void ReplayConsumer::ITypeConformance_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) + { + } + + +}; // namespace SlangRecord diff --git a/source/slang-record-replay/replay/replay-consumer.h b/source/slang-record-replay/replay/replay-consumer.h new file mode 100644 index 000000000..6ac733f90 --- /dev/null +++ b/source/slang-record-replay/replay/replay-consumer.h @@ -0,0 +1,196 @@ +#ifndef REPLAY_CONSUMER_H +#define REPLAY_CONSUMER_H + +#include <unordered_map> +#include "../util/record-format.h" +#include "decoder-consumer.h" + +namespace SlangRecord +{ + class ReplayConsumer : public IDecoderConsumer + { + public: + virtual void CreateGlobalSession(ObjectID objectId, const uint8_t* parameterBuffer, int64_t bufferSize) = 0; + virtual void IGlobalSession_createSession(ObjectID objectId, slang::SessionDesc const& desc, ObjectID outSessionId) = 0; + virtual void IGlobalSession_findProfile(ObjectID objectId, char const* name) = 0; + virtual void IGlobalSession_setDownstreamCompilerPath(ObjectID objectId, SlangPassThrough passThrough, char const* path) = 0; + virtual void IGlobalSession_setDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, char const* prelude) = 0; + virtual void IGlobalSession_getDownstreamCompilerPrelude(ObjectID objectId, SlangPassThrough inPassThrough, ObjectID outPreludeId) = 0; + + virtual void IGlobalSession_getBuildTagString(ObjectID objectId) { (void) objectId; } + + virtual void IGlobalSession_setDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage, SlangPassThrough defaultCompiler) = 0; + virtual void IGlobalSession_getDefaultDownstreamCompiler(ObjectID objectId, SlangSourceLanguage sourceLanguage) = 0; + virtual void IGlobalSession_setLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, char const* prelude) = 0; + virtual void IGlobalSession_getLanguagePrelude(ObjectID objectId, SlangSourceLanguage inSourceLanguage, ObjectID outPreludeId) = 0; + virtual void IGlobalSession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequest) = 0; + virtual void IGlobalSession_addBuiltins(ObjectID objectId, char const* sourcePath, char const* sourceString) = 0; + virtual void IGlobalSession_setSharedLibraryLoader(ObjectID objectId, ObjectID loaderId) = 0; + virtual void IGlobalSession_getSharedLibraryLoader(ObjectID objectId, ObjectID outLoaderId) = 0; + virtual void IGlobalSession_checkCompileTargetSupport(ObjectID objectId, SlangCompileTarget target) = 0; + virtual void IGlobalSession_checkPassThroughSupport(ObjectID objectId, SlangPassThrough passThrough) = 0; + virtual void IGlobalSession_compileStdLib(ObjectID objectId, slang::CompileStdLibFlags flags) = 0; + virtual void IGlobalSession_loadStdLib(ObjectID objectId, const void* stdLib, size_t stdLibSizeInBytes) = 0; + virtual void IGlobalSession_saveStdLib(ObjectID objectId, SlangArchiveType archiveType, ObjectID outBlobId) = 0; + virtual void IGlobalSession_findCapability(ObjectID objectId, char const* name) = 0; + virtual void IGlobalSession_setDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) = 0; + virtual void IGlobalSession_getDownstreamCompilerForTransition(ObjectID objectId, SlangCompileTarget source, SlangCompileTarget target) = 0; + + virtual void IGlobalSession_getCompilerElapsedTime(ObjectID objectId) { (void) objectId; } + + virtual void IGlobalSession_setSPIRVCoreGrammar(ObjectID objectId, char const* jsonPath) = 0; + virtual void IGlobalSession_parseCommandLineArguments(ObjectID objectId, int argc, const char* const* argv, ObjectID outSessionDescId, ObjectID outAllocationId) = 0; + virtual void IGlobalSession_getSessionDescDigest(ObjectID objectId, slang::SessionDesc* sessionDesc, ObjectID outBlobId) = 0; + + // ISession + virtual void ISession_getGlobalSession(ObjectID objectId, ObjectID outGlobalSessionId) = 0; + virtual void ISession_loadModule(ObjectID objectId, const char* moduleName, ObjectID outDiagnostics, ObjectID outModuleId) = 0; + + virtual void ISession_loadModuleFromIRBlob(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_loadModuleFromSource(ObjectID objectId, const char* moduleName, + const char* path, slang::IBlob* source, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_loadModuleFromSourceString(ObjectID objectId, const char* moduleName, + const char* path, const char* string, ObjectID outDiagnosticsId, ObjectID outModuleId) = 0; + virtual void ISession_createCompositeComponentType(ObjectID objectId, ObjectID* componentTypeIds, + SlangInt componentTypeCount, ObjectID outCompositeComponentTypeIds, ObjectID outDiagnosticsId) = 0; + + virtual void ISession_specializeType(ObjectID objectId, ObjectID typeId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getTypeLayout(ObjectID objectId, ObjectID typeId, SlangInt targetIndex, + slang::LayoutRules rules, ObjectID outDiagnosticsId, ObjectID outTypeLayoutReflection) = 0; + + virtual void ISession_getContainerType(ObjectID objectId, ObjectID elementType, + slang::ContainerType containerType, ObjectID outDiagnosticsId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getDynamicType(ObjectID objectId, ObjectID outTypeReflectionId) = 0; + + virtual void ISession_getTypeRTTIMangledName(ObjectID objectId, ObjectID typeId, ObjectID outNameBlobId) = 0; + + virtual void ISession_getTypeConformanceWitnessMangledName(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outNameBlobId) = 0; + + virtual void ISession_getTypeConformanceWitnessSequentialID(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, uint32_t outId) = 0; + + virtual void ISession_createTypeConformanceComponentType(ObjectID objectId, ObjectID typeId, + ObjectID interfaceTypeId, ObjectID outConformanceId, + SlangInt conformanceIdOverride, ObjectID outDiagnosticsId) = 0; + + virtual void ISession_createCompileRequest(ObjectID objectId, ObjectID outCompileRequestId) = 0; + + virtual void ISession_getLoadedModuleCount(ObjectID objectId) { (void) objectId; } + + virtual void ISession_getLoadedModule(ObjectID objectId, SlangInt index, ObjectID outModuleId) = 0; + + virtual void ISession_isBinaryModuleUpToDate(ObjectID objectId) { (void) objectId; } + + // IModule + virtual void IModule_findEntryPointByName(ObjectID objectId, char const* name, ObjectID outEntryPointId) = 0; + + virtual void IModule_getDefinedEntryPointCount(ObjectID objectId) { (void) objectId; } + + virtual void IModule_getDefinedEntryPoint(ObjectID objectId, SlangInt32 index, ObjectID outEntryPointId) = 0; + virtual void IModule_serialize(ObjectID objectId, ObjectID outSerializedBlobId) = 0; + virtual void IModule_writeToFile(ObjectID objectId, char const* fileName) = 0; + + virtual void IModule_getName(ObjectID objectId) { (void) objectId; } + virtual void IModule_getFilePath(ObjectID objectId) { (void) objectId; } + virtual void IModule_getUniqueIdentity(ObjectID objectId) { (void) objectId; } + + virtual void IModule_findAndCheckEntryPoint(ObjectID objectId, char const* name, SlangStage stage, ObjectID outEntryPointId, ObjectID outDiagnostics) = 0; + + virtual void IModule_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void IModule_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void IModule_getSpecializationParamCount(ObjectID objectId) { (void) objectId; } + + virtual void IModule_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IModule_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IModule_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void IModule_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void IModule_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IModule_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IModule_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void IModule_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void IModule_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // IEntryPoint + virtual void IEntryPoint_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void IEntryPoint_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void IEntryPoint_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void IEntryPoint_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void IEntryPoint_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void IEntryPoint_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IEntryPoint_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void IEntryPoint_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void IEntryPoint_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void IEntryPoint_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // ICompositeComponentType + virtual void ICompositeComponentType_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void ICompositeComponentType_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void ICompositeComponentType_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void ICompositeComponentType_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void ICompositeComponentType_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void ICompositeComponentType_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ICompositeComponentType_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void ICompositeComponentType_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void ICompositeComponentType_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + + // ITypeConformance + virtual void ITypeConformance_getSession(ObjectID objectId, ObjectID outSessionId) = 0; + virtual void ITypeConformance_getLayout(ObjectID objectId, SlangInt targetIndex, ObjectID outDiagnosticsId, ObjectID retProgramLayoutId) = 0; + + virtual void ITypeConformance_getSpecializationParamCount(ObjectID objectId) { (void) objectId; }; + + virtual void ITypeConformance_getEntryPointCode(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_getTargetCode(ObjectID objectId, SlangInt targetIndex, ObjectID outCode, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_getResultAsFileSystem(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outFileSystem) = 0; + virtual void ITypeConformance_getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) = 0; + virtual void ITypeConformance_specialize(ObjectID objectId, slang::SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, ObjectID outSpecializedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ITypeConformance_link(ObjectID objectId, ObjectID outLinkedComponentTypeId, ObjectID outDiagnosticsId) = 0; + virtual void ITypeConformance_getEntryPointHostCallable(ObjectID objectId, int entryPointIndex, int targetIndex, ObjectID outSharedLibrary, ObjectID outDiagnostics) = 0; + virtual void ITypeConformance_renameEntryPoint(ObjectID objectId, const char* newName, ObjectID outEntryPointId) = 0; + virtual void ITypeConformance_linkWithOptions(ObjectID objectId, ObjectID outLinkedComponentTypeId, + uint32_t compilerOptionEntryCount, slang::CompilerOptionEntry* compilerOptionEntries, ObjectID outDiagnosticsId) = 0; + private: + // Map of the address of the object allocated by slang during record to + // the address of the object allocated by the replay. + // We need to have this map because we never save the content of the object + // allocated by slang, because those are just opaque objects or handles, we + // only need to provide them to the corresponding replay function or call the + // methods on the correct object. + std::unordered_map<ObjectID, void*> m_objectMap; + + inline void* getObjectPointer(ObjectID objectId) + { + if (m_objectMap.find(objectId) == m_objectMap.end()) + { + return nullptr; + } + else + { + return m_objectMap[objectId]; + } + } + }; +} +#endif // REPLAY_CONSUMER_H diff --git a/source/slang-record-replay/replay/slang-decoder.cpp b/source/slang-record-replay/replay/slang-decoder.cpp new file mode 100644 index 000000000..561a2c9e3 --- /dev/null +++ b/source/slang-record-replay/replay/slang-decoder.cpp @@ -0,0 +1,1974 @@ +#include "slang-decoder.h" +#include "parameter-decoder.h" +#include "decoder-helper.h" +#include "../util/record-utility.h" + +namespace SlangRecord +{ + + bool SlangDecoder::processMethodCall(FunctionHeader const& header, ParameterBlock const& parameterBlock) + { + ApiClassId classId = static_cast<ApiClassId>(getClassId(header.callId)); + ObjectID objectId = header.handleId; + switch(classId) + { + default: + slangRecordLog(LogLevel::Error, "Unhandled Slang Class Id: %d\n", classId); + return false; + case ApiClassId::Class_IGlobalSession: + return processIGlobalSessionMethods(header.callId, objectId, parameterBlock); + break; + case ApiClassId::Class_ISession: + return processISessionMethods(header.callId, objectId, parameterBlock); + break; + case ApiClassId::Class_IModule: + return processIModuleMethods(header.callId, objectId, parameterBlock); + break; + case ApiClassId::Class_IEntryPoint: + return processIEntryPointMethods(header.callId, objectId, parameterBlock); + break; + case ApiClassId::Class_ICompositeComponentType: + return processICompositeComponentTypeMethods(header.callId, objectId, parameterBlock); + break; + case ApiClassId::Class_ITypeConformance: + return processITypeConformanceMethods(header.callId, objectId, parameterBlock); + break; + } + } + + bool SlangDecoder::processIGlobalSessionMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock) + { + switch(callId) + { + default: + slangRecordLog(LogLevel::Error, "Unhandled Slang API call: %d\n", callId); + break; + case ApiCallId::CreateGlobalSession: + CreateGlobalSession(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_createSession: + IGlobalSession_createSession(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_findProfile: + IGlobalSession_findProfile(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_setDownstreamCompilerPath: + IGlobalSession_setDownstreamCompilerPath(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_setDownstreamCompilerPrelude: + IGlobalSession_setDownstreamCompilerPrelude(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getDownstreamCompilerPrelude: + IGlobalSession_getDownstreamCompilerPrelude(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getBuildTagString: + IGlobalSession_getBuildTagString(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_setDefaultDownstreamCompiler: + IGlobalSession_setDefaultDownstreamCompiler(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getDefaultDownstreamCompiler: + IGlobalSession_getDefaultDownstreamCompiler(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_setLanguagePrelude: + IGlobalSession_setLanguagePrelude(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getLanguagePrelude: + IGlobalSession_getLanguagePrelude(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_createCompileRequest: + IGlobalSession_createCompileRequest(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_addBuiltins: + IGlobalSession_addBuiltins(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_setSharedLibraryLoader: + IGlobalSession_setSharedLibraryLoader(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getSharedLibraryLoader: + IGlobalSession_getSharedLibraryLoader(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_checkCompileTargetSupport: + IGlobalSession_checkCompileTargetSupport(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_checkPassThroughSupport: + IGlobalSession_checkPassThroughSupport(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_compileStdLib: + IGlobalSession_compileStdLib(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_loadStdLib: + IGlobalSession_loadStdLib(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_saveStdLib: + IGlobalSession_saveStdLib(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_findCapability: + IGlobalSession_findCapability(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_setDownstreamCompilerForTransition: + IGlobalSession_setDownstreamCompilerForTransition(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getDownstreamCompilerForTransition: + IGlobalSession_getDownstreamCompilerForTransition(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getCompilerElapsedTime: + IGlobalSession_getCompilerElapsedTime(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_setSPIRVCoreGrammar: + IGlobalSession_setSPIRVCoreGrammar(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_parseCommandLineArguments: + IGlobalSession_parseCommandLineArguments(objectId, parameterBlock); + break; + case ApiCallId::IGlobalSession_getSessionDescDigest: + IGlobalSession_getSessionDescDigest(objectId, parameterBlock); + break; + } + return true; + } + + + bool SlangDecoder::processISessionMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock) + { + switch(callId) + { + default: + slangRecordLog(LogLevel::Error, "Unhandled Slang API call: %d\n", callId); + return false; + case ApiCallId::ISession_getGlobalSession: + ISession_getGlobalSession(objectId, parameterBlock); + break; + case ApiCallId::ISession_loadModule: + ISession_loadModule(objectId, parameterBlock); + break; + case ApiCallId::ISession_loadModuleFromIRBlob: + ISession_loadModuleFromIRBlob(objectId, parameterBlock); + break; + case ApiCallId::ISession_loadModuleFromSource: + ISession_loadModuleFromSource(objectId, parameterBlock); + break; + case ApiCallId::ISession_loadModuleFromSourceString: + ISession_loadModuleFromSourceString(objectId, parameterBlock); + break; + case ApiCallId::ISession_createCompositeComponentType: + ISession_createCompositeComponentType(objectId, parameterBlock); + break; + case ApiCallId::ISession_specializeType: + ISession_specializeType(objectId, parameterBlock); + break; + case ApiCallId::ISession_getTypeLayout: + ISession_getTypeLayout(objectId, parameterBlock); + break; + case ApiCallId::ISession_getContainerType: + ISession_getContainerType(objectId, parameterBlock); + break; + case ApiCallId::ISession_getDynamicType: + ISession_getDynamicType(objectId, parameterBlock); + break; + case ApiCallId::ISession_getTypeRTTIMangledName: + ISession_getTypeRTTIMangledName(objectId, parameterBlock); + break; + case ApiCallId::ISession_getTypeConformanceWitnessMangledName: + ISession_getTypeConformanceWitnessMangledName(objectId, parameterBlock); + break; + case ApiCallId::ISession_getTypeConformanceWitnessSequentialID: + ISession_getTypeConformanceWitnessSequentialID(objectId, parameterBlock); + break; + case ApiCallId::ISession_createTypeConformanceComponentType: + ISession_createTypeConformanceComponentType(objectId, parameterBlock); + break; + case ApiCallId::ISession_createCompileRequest: + ISession_createCompileRequest(objectId, parameterBlock); + break; + case ApiCallId::ISession_getLoadedModuleCount: + ISession_getLoadedModuleCount(objectId, parameterBlock); + break; + case ApiCallId::ISession_getLoadedModule: + ISession_getLoadedModule(objectId, parameterBlock); + break; + case ApiCallId::ISession_isBinaryModuleUpToDate: + ISession_isBinaryModuleUpToDate(objectId, parameterBlock); + break; + } + return true; + } + + bool SlangDecoder::processIModuleMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock) + { + switch(callId) + { + default: + slangRecordLog(LogLevel::Error, "Unhandled Slang API call: %d\n", callId); + return false; + case ApiCallId::IModule_findEntryPointByName: + IModule_findEntryPointByName(objectId, parameterBlock); + break; + case ApiCallId::IModule_getDefinedEntryPointCount: + IModule_getDefinedEntryPointCount(objectId, parameterBlock); + break; + case ApiCallId::IModule_getDefinedEntryPoint: + IModule_getDefinedEntryPoint(objectId, parameterBlock); + break; + case ApiCallId::IModule_serialize: + IModule_serialize(objectId, parameterBlock); + break; + case ApiCallId::IModule_writeToFile: + IModule_writeToFile(objectId, parameterBlock); + break; + case ApiCallId::IModule_getName: + IModule_getName(objectId, parameterBlock); + break; + case ApiCallId::IModule_getFilePath: + IModule_getFilePath(objectId, parameterBlock); + break; + case ApiCallId::IModule_getUniqueIdentity: + IModule_getUniqueIdentity(objectId, parameterBlock); + break; + case ApiCallId::IModule_findAndCheckEntryPoint: + IModule_findAndCheckEntryPoint(objectId, parameterBlock); + break; + case ApiCallId::IModule_getSession: + IModule_getSession(objectId, parameterBlock); + break; + case ApiCallId::IModule_getLayout: + IModule_getLayout(objectId, parameterBlock); + break; + case ApiCallId::IModule_getSpecializationParamCount: + IModule_getSpecializationParamCount(objectId, parameterBlock); + break; + case ApiCallId::IModule_getEntryPointCode: + IModule_getEntryPointCode(objectId, parameterBlock); + break; + case ApiCallId::IModule_getTargetCode: + IModule_getTargetCode(objectId, parameterBlock); + break; + case ApiCallId::IModule_getResultAsFileSystem: + IModule_getResultAsFileSystem(objectId, parameterBlock); + break; + case ApiCallId::IModule_getEntryPointHash: + IModule_getEntryPointHash(objectId, parameterBlock); + break; + case ApiCallId::IModule_specialize: + IModule_specialize(objectId, parameterBlock); + break; + case ApiCallId::IModule_link: + IModule_link(objectId, parameterBlock); + break; + case ApiCallId::IModule_getEntryPointHostCallable: + IModule_getEntryPointHostCallable(objectId, parameterBlock); + break; + case ApiCallId::IModule_renameEntryPoint: + IModule_renameEntryPoint(objectId, parameterBlock); + break; + case ApiCallId::IModule_linkWithOptions: + IModule_linkWithOptions(objectId, parameterBlock); + break; + } + return true; + } + + bool SlangDecoder::processIEntryPointMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock) + { + switch(callId) + { + default: + slangRecordLog(LogLevel::Error, "Unhandled Slang API call: %d\n", callId); + return false; + case ApiCallId::IEntryPoint_getSession: + IEntryPoint_getSession(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_getLayout: + IEntryPoint_getLayout(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_getSpecializationParamCount: + IEntryPoint_getSpecializationParamCount(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_getEntryPointCode: + IEntryPoint_getEntryPointCode(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_getTargetCode: + IEntryPoint_getTargetCode(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_getResultAsFileSystem: + IEntryPoint_getResultAsFileSystem(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_getEntryPointHash: + IEntryPoint_getEntryPointHash(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_specialize: + IEntryPoint_specialize(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_link: + IEntryPoint_link(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_getEntryPointHostCallable: + IEntryPoint_getEntryPointHostCallable(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_renameEntryPoint: + IEntryPoint_renameEntryPoint(objectId, parameterBlock); + break; + case ApiCallId::IEntryPoint_linkWithOptions: + IEntryPoint_linkWithOptions(objectId, parameterBlock); + break; + } + return true; + } + + bool SlangDecoder::processICompositeComponentTypeMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock) + { + switch(callId) + { + default: + slangRecordLog(LogLevel::Error, "Unhandled Slang API call: %d\n", callId); + break; + case ApiCallId::ICompositeComponentType_getSession: + ICompositeComponentType_getSession(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_getLayout: + ICompositeComponentType_getLayout(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_getSpecializationParamCount: + ICompositeComponentType_getSpecializationParamCount(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_getEntryPointCode: + ICompositeComponentType_getEntryPointCode(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_getTargetCode: + ICompositeComponentType_getTargetCode(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_getResultAsFileSystem: + ICompositeComponentType_getResultAsFileSystem(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_getEntryPointHash: + ICompositeComponentType_getEntryPointHash(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_specialize: + ICompositeComponentType_specialize(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_link: + ICompositeComponentType_link(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_getEntryPointHostCallable: + ICompositeComponentType_getEntryPointHostCallable(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_renameEntryPoint: + ICompositeComponentType_renameEntryPoint(objectId, parameterBlock); + break; + case ApiCallId::ICompositeComponentType_linkWithOptions: + ICompositeComponentType_linkWithOptions(objectId, parameterBlock); + break; + } + return true; + } + + bool SlangDecoder::processITypeConformanceMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock) + { + switch(callId) + { + default: + slangRecordLog(LogLevel::Error, "Unhandled Slang API call: %d\n", callId); + return false; + case ApiCallId::ITypeConformance_getSession: + ITypeConformance_getSession(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_getLayout: + ITypeConformance_getLayout(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_getSpecializationParamCount: + ITypeConformance_getSpecializationParamCount(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_getEntryPointCode: + ITypeConformance_getEntryPointCode(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_getTargetCode: + ITypeConformance_getTargetCode(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_getResultAsFileSystem: + ITypeConformance_getResultAsFileSystem(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_getEntryPointHash: + ITypeConformance_getEntryPointHash(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_specialize: + ITypeConformance_specialize(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_link: + ITypeConformance_link(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_getEntryPointHostCallable: + ITypeConformance_getEntryPointHostCallable(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_renameEntryPoint: + ITypeConformance_renameEntryPoint(objectId, parameterBlock); + break; + case ApiCallId::ITypeConformance_linkWithOptions: + ITypeConformance_linkWithOptions(objectId, parameterBlock); + break; + } + return true; + } + + bool SlangDecoder::processFunctionCall(FunctionHeader const& header, ParameterBlock const& parameterBlock) + { + return false; + } + + + bool SlangDecoder::CreateGlobalSession(ObjectID objectId, ParameterBlock const& parameterBlock) + { + return false; + } + + bool SlangDecoder::IGlobalSession_createSession(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StructDecoder<slang::SessionDesc> sessionDesc; + sessionDesc.decode(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize); + + ObjectID outSessionId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSessionId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_createSession(objectId, sessionDesc.getValue(), outSessionId); + } + + return true; + } + + void SlangDecoder::IGlobalSession_findProfile(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder name; + ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, name); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_findProfile(objectId, name.getPointer()); + } + } + + void SlangDecoder::IGlobalSession_setDownstreamCompilerPath(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + SlangPassThrough passThrough {}; + readByte = ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, passThrough); + StringDecoder path; + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, path); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_setDownstreamCompilerPath(objectId, passThrough, path.getPointer()); + } + } + + void SlangDecoder::IGlobalSession_setDownstreamCompilerPrelude(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + SlangPassThrough passThrough {}; + readByte = ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, passThrough); + StringDecoder prelude; + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, prelude); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_setDownstreamCompilerPrelude(objectId, passThrough, prelude.getPointer()); + } + } + + void SlangDecoder::IGlobalSession_getDownstreamCompilerPrelude(ObjectID objectId, ParameterBlock const& parameterBlock) + { + SlangPassThrough passThrough {}; + ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, passThrough); + + ObjectID outPreludeId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outPreludeId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_getDownstreamCompilerPrelude(objectId, passThrough, outPreludeId); + } + } + + void SlangDecoder::IGlobalSession_getBuildTagString(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_setDefaultDownstreamCompiler(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + SlangSourceLanguage sourceLanguage {}; + SlangPassThrough defaultCompiler {}; + readByte = ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, sourceLanguage); + readByte += ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, defaultCompiler); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_setDefaultDownstreamCompiler(objectId, sourceLanguage, defaultCompiler); + } + } + + void SlangDecoder::IGlobalSession_getDefaultDownstreamCompiler(ObjectID objectId, ParameterBlock const& parameterBlock) + { + SlangSourceLanguage sourceLanguage {}; + ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, sourceLanguage); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_getDefaultDownstreamCompiler(objectId, sourceLanguage); + } + } + + void SlangDecoder::IGlobalSession_setLanguagePrelude(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + SlangSourceLanguage sourceLanguage {}; + StringDecoder prelude; + readByte = ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, sourceLanguage); + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, prelude); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_setLanguagePrelude(objectId, sourceLanguage, prelude.getPointer()); + } + } + + void SlangDecoder::IGlobalSession_getLanguagePrelude(ObjectID objectId, ParameterBlock const& parameterBlock) + { + SlangSourceLanguage sourceLanguage {}; + ObjectID outPreludeId = 0; + ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, sourceLanguage); + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outPreludeId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_getLanguagePrelude(objectId, sourceLanguage, outPreludeId); + } + } + + void SlangDecoder::IGlobalSession_createCompileRequest(ObjectID objectId, ParameterBlock const& parameterBlock) + { + ObjectID outCompileRequestId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCompileRequestId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_createCompileRequest(objectId, outCompileRequestId); + } + } + + void SlangDecoder::IGlobalSession_addBuiltins(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readBytes = 0; + StringDecoder sourcePath; + StringDecoder sourceString; + readBytes = ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, sourcePath); + readBytes += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readBytes, parameterBlock.parameterBufferSize - readBytes, sourceString); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_addBuiltins(objectId, sourcePath.getPointer(), sourceString.getPointer()); + } + } + + void SlangDecoder::IGlobalSession_setSharedLibraryLoader(ObjectID objectId, ParameterBlock const& parameterBlock) + { + // TODO: Not sure if we need to record this function. Because this functions is something like the file system + // override, it's provided by user code. So capturing it makes no sense. The only way is to wrapper this interface + // by our own implementation, and record it there. + slangRecordLog(LogLevel::Error, "%s should not be called\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_getSharedLibraryLoader(ObjectID objectId, ParameterBlock const& parameterBlock) + { + ObjectID outLoaderId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLoaderId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_getSharedLibraryLoader(objectId, outLoaderId); + } + } + + void SlangDecoder::IGlobalSession_checkCompileTargetSupport(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_checkPassThroughSupport(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_compileStdLib(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slang::CompileStdLibFlags flags {}; + ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, flags); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_compileStdLib(objectId, flags); + } + } + + void SlangDecoder::IGlobalSession_loadStdLib(ObjectID objectId, ParameterBlock const& parameterBlock) + { + PointerDecoder<void*> stdLib; + ParameterDecoder::decodePointer(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, stdLib); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_loadStdLib(objectId, stdLib.getPointer(), stdLib.getDataSize()); + } + } + + void SlangDecoder::IGlobalSession_saveStdLib(ObjectID objectId, ParameterBlock const& parameterBlock) + { + SlangArchiveType archiveType {}; + ObjectID outBlobId = 0; + ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, archiveType); + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outBlobId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_saveStdLib(objectId, archiveType, outBlobId); + } + } + + void SlangDecoder::IGlobalSession_findCapability(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_setDownstreamCompilerForTransition(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + SlangCompileTarget source {}; + SlangCompileTarget target {}; + SlangPassThrough compiler {}; + + readByte = ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, source); + readByte += ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, target); + readByte += ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, compiler); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_setDownstreamCompilerForTransition(objectId, source, target, compiler); + } + } + + void SlangDecoder::IGlobalSession_getDownstreamCompilerForTransition(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_getCompilerElapsedTime(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_setSPIRVCoreGrammar(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IGlobalSession_parseCommandLineArguments(ObjectID objectId, ParameterBlock const& parameterBlock) + { + int argc = 0; + size_t readByte = 0; + readByte = ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, argc); + std::vector<char*> argv; + + if (argc > 0) + { + uint32_t arrayCount = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, arrayCount); + + SLANG_RECORD_ASSERT(arrayCount == (uint32_t)argc); + argv.resize(arrayCount); + + readByte += ParameterDecoder::decodeStringArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, argv.data(), arrayCount); + } + + ObjectID outSessionDescId = 0; + ObjectID outAllocationId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSessionDescId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outAllocationId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_parseCommandLineArguments(objectId, argc, argv.data(), outSessionDescId, outAllocationId); + } + } + + void SlangDecoder::IGlobalSession_getSessionDescDigest(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StructDecoder<slang::SessionDesc> sessionDesc; + ObjectID outBlobId = 0; + size_t readByte = 0; + sessionDesc.decode(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize); + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outBlobId); + + for (auto consumer: m_consumers) + { + consumer->IGlobalSession_getSessionDescDigest(objectId, &sessionDesc.getValue(), outBlobId); + } + } + + + void SlangDecoder::ISession_getGlobalSession(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::ISession_loadModule(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + StringDecoder moduleName; + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, moduleName); + + ObjectID outDiagnosticsId = 0; + ObjectID outModuleId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outModuleId); + + for (auto consumer: m_consumers) + { + consumer->ISession_loadModule(objectId, moduleName.getPointer(), outDiagnosticsId, outModuleId); + } + } + + void SlangDecoder::ISession_loadModuleFromIRBlob(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + StringDecoder moduleName; + StringDecoder path; + BlobDecoder source; + readByte = ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, moduleName); + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, path); + readByte += source.decode(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte); + + ObjectID outDiagnosticsId = 0; + ObjectID outModuleId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outModuleId); + + for (auto consumer: m_consumers) + { + consumer->ISession_loadModuleFromIRBlob(objectId, moduleName.getPointer(), path.getPointer(), source.getBlob(), outDiagnosticsId, outModuleId); + } + } + + void SlangDecoder::ISession_loadModuleFromSource(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + StringDecoder moduleName; + StringDecoder path; + BlobDecoder source; + readByte = ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, moduleName); + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, path); + readByte += source.decode(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte); + + ObjectID outDiagnosticsId = 0; + ObjectID outModuleId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outModuleId); + + for (auto consumer: m_consumers) + { + consumer->ISession_loadModuleFromSource(objectId, moduleName.getPointer(), path.getPointer(), source.getBlob(), outDiagnosticsId, outModuleId); + } + } + + void SlangDecoder::ISession_loadModuleFromSourceString(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + StringDecoder moduleName; + StringDecoder path; + StringDecoder source; + readByte = ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, moduleName); + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, path); + readByte += ParameterDecoder::decodeString(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, source); + + ObjectID outDiagnosticsId = 0; + ObjectID outModuleId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outModuleId); + + for (auto consumer: m_consumers) + { + consumer->ISession_loadModuleFromSourceString(objectId, moduleName.getPointer(), path.getPointer(), source.getPointer(), outDiagnosticsId, outModuleId); + } + } + + void SlangDecoder::ISession_createCompositeComponentType(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + std::vector<ObjectID> componentTypeIdList; + uint32_t arrayCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, arrayCount); + + componentTypeIdList.resize(arrayCount); + readByte += ParameterDecoder::decodeAddressArray(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, componentTypeIdList.data(), arrayCount); + + ObjectID outCompositeComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCompositeComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ISession_createCompositeComponentType(objectId, componentTypeIdList.data(), componentTypeIdList.size(), outCompositeComponentTypeId, outDiagnosticsId); + } + + } + + // TODO: See https://github.com/shader-slang/slang/issues/4624 for more details + void SlangDecoder::ISession_specializeType(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + ObjectID typeId = 0; + uint32_t arrayCount = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, typeId); + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, arrayCount); + + std::vector<slang::SpecializationArg> specializationArgs; + specializationArgs.resize(arrayCount); + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, specializationArgs.data(), arrayCount); + + ObjectID outDiagnosticsId = 0; + ObjectID outTypeReflectionId = 0; + + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outTypeReflectionId); + + for (auto consumer: m_consumers) + { + consumer->ISession_specializeType(objectId, typeId, specializationArgs.data(), specializationArgs.size(), outDiagnosticsId, outTypeReflectionId); + } + } + + void SlangDecoder::ISession_getTypeLayout(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + ObjectID typeId = 0; + int64_t targetIndex = 0; + slang::LayoutRules rules {}; + readByte = ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, typeId); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + readByte += ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, rules); + + ObjectID outDiagnosticsId = 0; + ObjectID outTypeLayoutReflectionId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outTypeLayoutReflectionId); + + for (auto consumer: m_consumers) + { + consumer->ISession_getTypeLayout(objectId, typeId, targetIndex, rules, outDiagnosticsId, outTypeLayoutReflectionId); + } + } + + void SlangDecoder::ISession_getContainerType(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + ObjectID elementType = 0; + slang::ContainerType containerType {}; + readByte = ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, elementType); + readByte += ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, containerType); + + ObjectID outDiagnosticsId = 0; + ObjectID outTypeReflectionId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outTypeReflectionId); + + for (auto consumer: m_consumers) + { + consumer->ISession_getContainerType(objectId, elementType, containerType, outDiagnosticsId, outTypeReflectionId); + } + } + + void SlangDecoder::ISession_getDynamicType(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + ObjectID outTypeReflectionId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outTypeReflectionId); + + for (auto consumer: m_consumers) + { + consumer->ISession_getDynamicType(objectId, outTypeReflectionId); + } + } + + void SlangDecoder::ISession_getTypeRTTIMangledName(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + ObjectID typeId = 0; + ObjectID outNameBlobId = 0; + ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, typeId); + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outNameBlobId); + + for (auto consumer: m_consumers) + { + consumer->ISession_getTypeRTTIMangledName(objectId, typeId, outNameBlobId); + } + } + + void SlangDecoder::ISession_getTypeConformanceWitnessMangledName(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + ObjectID typeId = 0; + ObjectID interfaceTypeId = 0; + ObjectID outNameBlobId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, typeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, interfaceTypeId); + + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outNameBlobId); + + for (auto consumer: m_consumers) + { + consumer->ISession_getTypeConformanceWitnessMangledName(objectId, typeId, interfaceTypeId, outNameBlobId); + } + } + + void SlangDecoder::ISession_getTypeConformanceWitnessSequentialID(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + + ObjectID typeId = 0; + ObjectID interfaceTypeId = 0; + + readByte = ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, typeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, interfaceTypeId); + + uint32_t outSequentialId = 0; + for (auto consumer: m_consumers) + { + consumer->ISession_getTypeConformanceWitnessSequentialID(objectId, typeId, interfaceTypeId, outSequentialId); + } + } + + void SlangDecoder::ISession_createTypeConformanceComponentType(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection app is not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + ObjectID typeId = 0; + ObjectID interfaceTypeId = 0; + int64_t conformanceIdOverride = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, typeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, interfaceTypeId); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, conformanceIdOverride); + + ObjectID outDiagnosticsId = 0; + ObjectID outConformanceId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outConformanceId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ISession_createTypeConformanceComponentType(objectId, typeId, interfaceTypeId, conformanceIdOverride, outConformanceId, outDiagnosticsId); + } + } + + void SlangDecoder::ISession_createCompileRequest(ObjectID objectId, ParameterBlock const& parameterBlock) + { + ObjectID outCompileRequestId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCompileRequestId); + + for (auto consumer: m_consumers) + { + consumer->ISession_createCompileRequest(objectId, outCompileRequestId); + } + } + + void SlangDecoder::ISession_getLoadedModuleCount(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::ISession_getLoadedModule(ObjectID objectId, ParameterBlock const& parameterBlock) + { + int64_t index = 0; + ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, index); + + ObjectID outModuleId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outModuleId); + + for (auto consumer: m_consumers) + { + consumer->ISession_getLoadedModule(objectId, index, outModuleId); + } + } + + void SlangDecoder::ISession_isBinaryModuleUpToDate(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + + void SlangDecoder::IModule_findEntryPointByName(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder name; + ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, name); + + ObjectID outEntryPointId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outEntryPointId); + + for (auto consumer: m_consumers) + { + consumer->IModule_findEntryPointByName(objectId, name.getPointer(), outEntryPointId); + } + } + + void SlangDecoder::IModule_getDefinedEntryPointCount(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IModule_getDefinedEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock) + { + int32_t index; + ObjectID outEntryPointId = 0; + ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, index); + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outEntryPointId); + + for (auto consumer: m_consumers) + { + consumer->IModule_getDefinedEntryPoint(objectId, index, outEntryPointId); + } + } + + void SlangDecoder::IModule_serialize(ObjectID objectId, ParameterBlock const& parameterBlock) + { + ObjectID outSerializedBlobId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSerializedBlobId); + + for (auto consumer: m_consumers) + { + consumer->IModule_serialize(objectId, outSerializedBlobId); + } + } + + void SlangDecoder::IModule_writeToFile(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder fileName; + ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, fileName); + + for (auto consumer: m_consumers) + { + consumer->IModule_writeToFile(objectId, fileName.getPointer()); + } + } + + void SlangDecoder::IModule_getName(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IModule_getFilePath(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IModule_getUniqueIdentity(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IModule_findAndCheckEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder name; + SlangStage stage {}; + size_t readByte = 0; + readByte = ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, name); + readByte += ParameterDecoder::decodeEnumValue(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, stage); + + ObjectID outEntryPointId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outEntryPointId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_findAndCheckEntryPoint(objectId, name.getPointer(), stage, outEntryPointId, outDiagnosticsId); + } + } + + void SlangDecoder::IModule_getSession(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IModule_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock) + { + int64_t targetIndex = 0; + ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + ObjectID outDiagnosticsId = 0; + ObjectID programLayoutId = 0; + + size_t readByte = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, programLayoutId); + + for (auto consumer: m_consumers) + { + consumer->IModule_getLayout(objectId, targetIndex, outDiagnosticsId, programLayoutId); + } + } + + void SlangDecoder::IModule_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IModule_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_getEntryPointCode(objectId, entryPointIndex, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::IModule_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_getTargetCode(objectId, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::IModule_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outFileSystemId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outFileSystemId); + + for (auto consumer: m_consumers) + { + consumer->IModule_getResultAsFileSystem(objectId, entryPointIndex, targetIndex, outFileSystemId); + } + } + + void SlangDecoder::IModule_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outBlobId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outBlobId); + + for (auto consumer: m_consumers) + { + consumer->IModule_getEntryPointHash(objectId, entryPointIndex, targetIndex, outBlobId); + } + } + + void SlangDecoder::IModule_specialize(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + uint32_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + + std::vector<slang::SpecializationArg> specializationArgs; + + uint32_t arraySize = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arraySize); + + SLANG_RECORD_ASSERT(arraySize == specializationArgCount); + + specializationArgs.resize(specializationArgCount); + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, specializationArgs.data(), specializationArgCount); + + ObjectID outSpecializedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSpecializedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_specialize(objectId, specializationArgs.data(), specializationArgCount, outSpecializedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::IModule_link(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_link(objectId, outLinkedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::IModule_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outSharedLibraryId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_getEntryPointHostCallable(objectId, entryPointIndex, targetIndex, outSharedLibraryId, outDiagnosticsId); + } + } + + void SlangDecoder::IModule_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder newName; + ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, newName); + + ObjectID outEntryPointId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outEntryPointId); + + for (auto consumer: m_consumers) + { + consumer->IModule_renameEntryPoint(objectId, newName.getPointer(), outEntryPointId); + } + } + + void SlangDecoder::IModule_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + uint32_t compilerOptionEntryCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, compilerOptionEntryCount); + + std::vector<slang::CompilerOptionEntry> compilerOptionEntries; + + uint32_t arrayCount = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arrayCount); + + SLANG_RECORD_ASSERT(arrayCount == compilerOptionEntryCount); + compilerOptionEntries.resize(compilerOptionEntryCount); + + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, compilerOptionEntries.data(), compilerOptionEntryCount); + + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_linkWithOptions(objectId, outLinkedComponentTypeId, compilerOptionEntryCount, compilerOptionEntries.data(), outDiagnosticsId); + } + } + + void SlangDecoder::IEntryPoint_getSession(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IEntryPoint_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock) + { + int64_t targetIndex = 0; + ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + + ObjectID outDiagnosticsId = 0; + ObjectID programLayoutId = 0; + + size_t readByte = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, programLayoutId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_getLayout(objectId, targetIndex, outDiagnosticsId, programLayoutId); + } + } + + void SlangDecoder::IEntryPoint_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::IEntryPoint_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_getEntryPointCode(objectId, entryPointIndex, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::IEntryPoint_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_getTargetCode(objectId, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::IEntryPoint_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outFileSystemId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outFileSystemId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_getResultAsFileSystem(objectId, entryPointIndex, targetIndex, outFileSystemId); + } + } + + void SlangDecoder::IEntryPoint_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outBlobId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outBlobId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_getEntryPointHash(objectId, entryPointIndex, targetIndex, outBlobId); + } + } + + void SlangDecoder::IEntryPoint_specialize(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + uint32_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + + std::vector<slang::SpecializationArg> specializationArgs; + + uint32_t arraySize = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arraySize); + + SLANG_RECORD_ASSERT(arraySize == specializationArgCount); + + specializationArgs.resize(specializationArgCount); + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, specializationArgs.data(), specializationArgCount); + + ObjectID outSpecializedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSpecializedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_specialize(objectId, specializationArgs.data(), specializationArgCount, outSpecializedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::IEntryPoint_link(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_link(objectId, outLinkedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::IEntryPoint_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outSharedLibraryId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_getEntryPointHostCallable(objectId, entryPointIndex, targetIndex, outSharedLibraryId, outDiagnosticsId); + } + } + + void SlangDecoder::IEntryPoint_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder newName; + ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, newName); + + ObjectID outEntryPointId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outEntryPointId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_renameEntryPoint(objectId, newName.getPointer(), outEntryPointId); + } + } + + void SlangDecoder::IEntryPoint_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + uint32_t compilerOptionEntryCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, compilerOptionEntryCount); + + std::vector<slang::CompilerOptionEntry> compilerOptionEntries; + + uint32_t arrayCount = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arrayCount); + + SLANG_RECORD_ASSERT(arrayCount == compilerOptionEntryCount); + compilerOptionEntries.resize(compilerOptionEntryCount); + + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, compilerOptionEntries.data(), compilerOptionEntryCount); + + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IEntryPoint_linkWithOptions(objectId, outLinkedComponentTypeId, compilerOptionEntryCount, compilerOptionEntries.data(), outDiagnosticsId); + } + } + + + void SlangDecoder::ICompositeComponentType_getSession(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::ICompositeComponentType_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock) + { + int64_t targetIndex = 0; + ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + ObjectID outDiagnosticsId = 0; + ObjectID programLayoutId = 0; + + size_t readByte = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, programLayoutId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_getLayout(objectId, targetIndex, outDiagnosticsId, programLayoutId); + } + } + + void SlangDecoder::ICompositeComponentType_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::ICompositeComponentType_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_getEntryPointCode(objectId, entryPointIndex, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::ICompositeComponentType_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_getTargetCode(objectId, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::ICompositeComponentType_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outFileSystemId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outFileSystemId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_getResultAsFileSystem(objectId, entryPointIndex, targetIndex, outFileSystemId); + } + } + + void SlangDecoder::ICompositeComponentType_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outBlobId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outBlobId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_getEntryPointHash(objectId, entryPointIndex, targetIndex, outBlobId); + } + } + + void SlangDecoder::ICompositeComponentType_specialize(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + uint32_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + + std::vector<slang::SpecializationArg> specializationArgs; + + uint32_t arraySize = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arraySize); + + SLANG_RECORD_ASSERT(arraySize == specializationArgCount); + + specializationArgs.resize(specializationArgCount); + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, specializationArgs.data(), specializationArgCount); + + ObjectID outSpecializedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSpecializedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_specialize(objectId, specializationArgs.data(), specializationArgCount, outSpecializedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::ICompositeComponentType_link(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_link(objectId, outLinkedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outSharedLibraryId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_getEntryPointHostCallable(objectId, entryPointIndex, targetIndex, outSharedLibraryId, outDiagnosticsId); + } + } + + void SlangDecoder::ICompositeComponentType_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder newName; + ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, newName); + + ObjectID outEntryPointId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outEntryPointId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_renameEntryPoint(objectId, newName.getPointer(), outEntryPointId); + } + } + + void SlangDecoder::ICompositeComponentType_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + uint32_t compilerOptionEntryCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, compilerOptionEntryCount); + + std::vector<slang::CompilerOptionEntry> compilerOptionEntries; + + uint32_t arrayCount = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arrayCount); + + SLANG_RECORD_ASSERT(arrayCount == compilerOptionEntryCount); + compilerOptionEntries.resize(compilerOptionEntryCount); + + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, compilerOptionEntries.data(), compilerOptionEntryCount); + + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ICompositeComponentType_linkWithOptions(objectId, outLinkedComponentTypeId, compilerOptionEntryCount, compilerOptionEntries.data(), outDiagnosticsId); + } + } + + + void SlangDecoder::ITypeConformance_getSession(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::ITypeConformance_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock) + { + int64_t targetIndex = 0; + ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + ObjectID outDiagnosticsId = 0; + ObjectID programLayoutId = 0; + + size_t readByte = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, programLayoutId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_getLayout(objectId, targetIndex, outDiagnosticsId, programLayoutId); + } + } + + void SlangDecoder::ITypeConformance_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock) + { + (void)objectId; + (void)parameterBlock; + slangRecordLog(LogLevel::Debug, "%s should not be called, it'a not recordd\n", __PRETTY_FUNCTION__); + } + + void SlangDecoder::ITypeConformance_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_getEntryPointCode(objectId, entryPointIndex, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::ITypeConformance_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, targetIndex); + + ObjectID outCodeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outCodeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_getTargetCode(objectId, targetIndex, outCodeId, outDiagnosticsId); + } + } + + void SlangDecoder::ITypeConformance_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outFileSystemId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outFileSystemId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_getResultAsFileSystem(objectId, entryPointIndex, targetIndex, outFileSystemId); + } + } + + void SlangDecoder::ITypeConformance_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outBlobId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outBlobId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_getEntryPointHash(objectId, entryPointIndex, targetIndex, outBlobId); + } + } + + void SlangDecoder::ITypeConformance_specialize(ObjectID objectId, ParameterBlock const& parameterBlock) + { + slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); + + size_t readByte = 0; + uint32_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + + std::vector<slang::SpecializationArg> specializationArgs; + + uint32_t arraySize = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arraySize); + + SLANG_RECORD_ASSERT(arraySize == specializationArgCount); + + specializationArgs.resize(specializationArgCount); + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, specializationArgs.data(), specializationArgCount); + + ObjectID outSpecializedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSpecializedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->IModule_specialize(objectId, specializationArgs.data(), specializationArgCount, outSpecializedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::ITypeConformance_link(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_link(objectId, outLinkedComponentTypeId, outDiagnosticsId); + } + } + + void SlangDecoder::ITypeConformance_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + int64_t entryPointIndex = 0; + int64_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + + ObjectID outSharedLibraryId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_getEntryPointHostCallable(objectId, entryPointIndex, targetIndex, outSharedLibraryId, outDiagnosticsId); + } + } + + void SlangDecoder::ITypeConformance_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock) + { + StringDecoder newName; + ParameterDecoder::decodeString(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, newName); + + ObjectID outEntryPointId = 0; + ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outEntryPointId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_renameEntryPoint(objectId, newName.getPointer(), outEntryPointId); + } + } + + void SlangDecoder::ITypeConformance_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock) + { + size_t readByte = 0; + uint32_t compilerOptionEntryCount = 0; + readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, compilerOptionEntryCount); + + std::vector<slang::CompilerOptionEntry> compilerOptionEntries; + + uint32_t arrayCount = 0; + readByte += ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, arrayCount); + + SLANG_RECORD_ASSERT(arrayCount == compilerOptionEntryCount); + compilerOptionEntries.resize(compilerOptionEntryCount); + + readByte += ParameterDecoder::decodeStructArray(parameterBlock.parameterBuffer + readByte, + parameterBlock.parameterBufferSize - readByte, compilerOptionEntries.data(), compilerOptionEntryCount); + + ObjectID outLinkedComponentTypeId = 0; + ObjectID outDiagnosticsId = 0; + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outLinkedComponentTypeId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + + for (auto consumer: m_consumers) + { + consumer->ITypeConformance_linkWithOptions(objectId, outLinkedComponentTypeId, compilerOptionEntryCount, compilerOptionEntries.data(), outDiagnosticsId); + } + } +} diff --git a/source/slang-record-replay/replay/slang-decoder.h b/source/slang-record-replay/replay/slang-decoder.h new file mode 100644 index 000000000..f127ebc85 --- /dev/null +++ b/source/slang-record-replay/replay/slang-decoder.h @@ -0,0 +1,154 @@ +#ifndef SLANG_DECODER_H +#define SLANG_DECODER_H + +#include <vector> +#include <unordered_map> +#include "../util/record-format.h" +#include "decoder-consumer.h" +#include "../../core/slang-list.h" + +namespace SlangRecord +{ + class SlangDecoder { + public: + struct ParameterBlock + { + const uint8_t* parameterBuffer = nullptr; + int64_t parameterBufferSize = 0; + + const uint8_t* outputBuffer = nullptr; + int64_t outputBufferSize = 0; + }; + + struct OutputObject + { + ObjectID recorddObjectId; + }; + + SlangDecoder() {}; + ~SlangDecoder() {}; + + bool processMethodCall(FunctionHeader const& header, ParameterBlock const& parameterBlock); + bool processFunctionCall(FunctionHeader const& header, ParameterBlock const& parameterBlock); + + bool processIGlobalSessionMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock); + bool processISessionMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock); + bool processIModuleMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock); + bool processIEntryPointMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock); + bool processICompositeComponentTypeMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock); + bool processITypeConformanceMethods(ApiCallId callId, ObjectID objectId, ParameterBlock const& parameterBlock); + + bool CreateGlobalSession(ObjectID objectId, ParameterBlock const& parameterBlock); + bool IGlobalSession_createSession(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_findProfile(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_setDownstreamCompilerPath(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_setDownstreamCompilerPrelude(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getDownstreamCompilerPrelude(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getBuildTagString(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_setDefaultDownstreamCompiler(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getDefaultDownstreamCompiler(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_setLanguagePrelude(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getLanguagePrelude(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_createCompileRequest(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_addBuiltins(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_setSharedLibraryLoader(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getSharedLibraryLoader(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_checkCompileTargetSupport(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_checkPassThroughSupport(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_compileStdLib(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_loadStdLib(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_saveStdLib(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_findCapability(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_setDownstreamCompilerForTransition(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getDownstreamCompilerForTransition(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getCompilerElapsedTime(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_setSPIRVCoreGrammar(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_parseCommandLineArguments(ObjectID objectId, ParameterBlock const& parameterBlock); + void IGlobalSession_getSessionDescDigest(ObjectID objectId, ParameterBlock const& parameterBlock); + + void ISession_getGlobalSession(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_loadModule(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_loadModuleFromBlob(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_loadModuleFromIRBlob(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_loadModuleFromSource(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_loadModuleFromSourceString(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_createCompositeComponentType(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_specializeType(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getTypeLayout(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getContainerType(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getDynamicType(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getTypeRTTIMangledName(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getTypeConformanceWitnessMangledName(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getTypeConformanceWitnessSequentialID(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_createTypeConformanceComponentType(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_createCompileRequest(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getLoadedModuleCount(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_getLoadedModule(ObjectID objectId, ParameterBlock const& parameterBlock); + void ISession_isBinaryModuleUpToDate(ObjectID objectId, ParameterBlock const& parameterBlock); + + void IModule_findEntryPointByName(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getDefinedEntryPointCount(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getDefinedEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_serialize(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_writeToFile(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getName(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getFilePath(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getUniqueIdentity(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_findAndCheckEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getSession(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_specialize(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_link(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock); + void IModule_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock); + + void IEntryPoint_getSession(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_specialize(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_link(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock); + void IEntryPoint_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock); + + void ICompositeComponentType_getSession(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_specialize(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_link(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock); + void ICompositeComponentType_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock); + + void ITypeConformance_getSession(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_getLayout(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_getSpecializationParamCount(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_getEntryPointCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_getTargetCode(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_getResultAsFileSystem(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_getEntryPointHash(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_specialize(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_link(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_renameEntryPoint(ObjectID objectId, ParameterBlock const& parameterBlock); + void ITypeConformance_linkWithOptions(ObjectID objectId, ParameterBlock const& parameterBlock); + + private: + Slang::List<IDecoderConsumer*> m_consumers; + }; +} +#endif // SLANG_DECODER_H diff --git a/source/slang-record-replay/util/record-format.h b/source/slang-record-replay/util/record-format.h new file mode 100644 index 000000000..d796abec6 --- /dev/null +++ b/source/slang-record-replay/util/record-format.h @@ -0,0 +1,172 @@ +#ifndef API_CALL_ID_H +#define API_CALL_ID_H + +#include <cstdint> + +namespace SlangRecord +{ + 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, + }; + + // Store the pointer value in a 64-bit integer + typedef uint64_t AddressFormat; + + // Use the address directly to represent the slang object. + typedef AddressFormat ObjectID; + + constexpr uint64_t g_globalFunctionHandle = 0; + constexpr uint32_t MAGIC_HEADER = 0x44414548; + constexpr uint32_t MAGIC_TAILER = 0x4C494154; + + enum ApiCallId : uint32_t + { + InvalidCallId = 0x00000000, + CreateGlobalSession = 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_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_getTargetCode = makeApiCallId(Class_IModule, 0x000E), + IModule_getResultAsFileSystem = makeApiCallId(Class_IModule, 0x000F), + IModule_getEntryPointHash = makeApiCallId(Class_IModule, 0x0010), + IModule_specialize = makeApiCallId(Class_IModule, 0x0011), + IModule_link = makeApiCallId(Class_IModule, 0x0012), + IModule_getEntryPointHostCallable = makeApiCallId(Class_IModule, 0x0013), + IModule_renameEntryPoint = makeApiCallId(Class_IModule, 0x0014), + IModule_linkWithOptions = makeApiCallId(Class_IModule, 0x0015), + + 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_getTargetCode = makeApiCallId(Class_IEntryPoint, 0x0005), + IEntryPoint_getResultAsFileSystem = makeApiCallId(Class_IEntryPoint, 0x0006), + IEntryPoint_getEntryPointHash = makeApiCallId(Class_IEntryPoint, 0x0007), + IEntryPoint_specialize = makeApiCallId(Class_IEntryPoint, 0x0008), + IEntryPoint_link = makeApiCallId(Class_IEntryPoint, 0x0009), + IEntryPoint_getEntryPointHostCallable = makeApiCallId(Class_IEntryPoint, 0x000A), + IEntryPoint_renameEntryPoint = makeApiCallId(Class_IEntryPoint, 0x000B), + IEntryPoint_linkWithOptions = makeApiCallId(Class_IEntryPoint, 0x000C), + + 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_getTargetCode = makeApiCallId(Class_ICompositeComponentType, 0x0005), + ICompositeComponentType_getResultAsFileSystem = makeApiCallId(Class_ICompositeComponentType, 0x0006), + ICompositeComponentType_getEntryPointHash = makeApiCallId(Class_ICompositeComponentType, 0x0007), + ICompositeComponentType_specialize = makeApiCallId(Class_ICompositeComponentType, 0x0008), + ICompositeComponentType_link = makeApiCallId(Class_ICompositeComponentType, 0x0009), + ICompositeComponentType_getEntryPointHostCallable = makeApiCallId(Class_ICompositeComponentType, 0x000A), + ICompositeComponentType_renameEntryPoint = makeApiCallId(Class_ICompositeComponentType, 0x000B), + ICompositeComponentType_linkWithOptions = makeApiCallId(Class_ICompositeComponentType, 0x000C), + + 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_getTargetCode = makeApiCallId(Class_ITypeConformance, 0x0005), + ITypeConformance_getResultAsFileSystem = makeApiCallId(Class_ITypeConformance, 0x0006), + ITypeConformance_getEntryPointHash = makeApiCallId(Class_ITypeConformance, 0x0007), + ITypeConformance_specialize = makeApiCallId(Class_ITypeConformance, 0x0008), + ITypeConformance_link = makeApiCallId(Class_ITypeConformance, 0x0009), + ITypeConformance_getEntryPointHostCallable = makeApiCallId(Class_ITypeConformance, 0x000A), + ITypeConformance_renameEntryPoint = makeApiCallId(Class_ITypeConformance, 0x000B), + ITypeConformance_linkWithOptions = makeApiCallId(Class_ITypeConformance, 0x000C) + }; + + struct FunctionHeader + { + uint32_t magic {MAGIC_HEADER}; + ApiCallId callId {InvalidCallId}; + ObjectID handleId {0}; + uint64_t dataSizeInBytes {0}; + uint64_t threadId {0}; + }; + + struct FunctionTailer + { + uint32_t magic {MAGIC_TAILER}; + uint32_t dataSizeInBytes {0}; + }; + +} +#endif diff --git a/source/slang-record-replay/util/record-utility.cpp b/source/slang-record-replay/util/record-utility.cpp new file mode 100644 index 000000000..8bf89ea67 --- /dev/null +++ b/source/slang-record-replay/util/record-utility.cpp @@ -0,0 +1,82 @@ + +#include <cstring> +#include <string> +#include <stdlib.h> +#include <stdarg.h> +#include <mutex> + +#include "record-utility.h" + +constexpr const char* kRecordLayerEnvVar = "SLANG_RECORD_LAYER"; +constexpr const char* kRecordLayerLogLevel = "SLANG_RECORD_LOG_LEVEL"; + +namespace SlangRecord +{ + static thread_local unsigned int g_logLevel = LogLevel::Silent; + + static bool getEnvironmentVariable(const char* name, std::string& out) + { +#ifdef _WIN32 + char* envVar = nullptr; + size_t sz = 0; + if (_dupenv_s(&envVar, &sz, name) == 0 && envVar != nullptr) + { + out = envVar; + free(envVar); + } +#else + if (const char* envVar = std::getenv(name)) + { + out = envVar; + } +#endif + return out.empty() == false; + } + + bool isRecordLayerEnabled() + { + std::string envVarStr; + if(getEnvironmentVariable(kRecordLayerEnvVar, envVarStr)) + { + if (envVarStr == "1") + { + return true; + } + } + return false; + } + + void setLogLevel() + { + // We only want to set the log level once + if (g_logLevel != LogLevel::Silent) + { + return; + } + + std::string envVarStr; + if (getEnvironmentVariable(kRecordLayerLogLevel, envVarStr)) + { + char* end = nullptr; + unsigned int logLevel = std::strtol(envVarStr.c_str(), &end, 10); + if (end && (*end == 0)) + { + g_logLevel = std::min((unsigned int)(LogLevel::Verbose), logLevel); + return; + } + } + } + + void slangRecordLog(LogLevel logLevel, const char* fmt, ...) + { + if (logLevel > g_logLevel) + { + return; + } + + va_list args; + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); + } +} diff --git a/source/slang-record-replay/util/record-utility.h b/source/slang-record-replay/util/record-utility.h new file mode 100644 index 000000000..33156a1f6 --- /dev/null +++ b/source/slang-record-replay/util/record-utility.h @@ -0,0 +1,37 @@ +#ifndef RECORD_UTILITY_H +#define RECORD_UTILITY_H + +// in gcc and clang, __PRETTY_FUNCTION__ is the function signature, +// while MSVC uses __FUNCSIG__ +#ifdef _MSC_VER +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif + +namespace SlangRecord +{ + enum LogLevel: unsigned int + { + Silent = 0, + Error = 1, + Debug = 2, + Verbose = 3, + }; + + bool isRecordLayerEnabled(); + void slangRecordLog(LogLevel logLevel, const char* fmt, ...); + void setLogLevel(); +} + +#define SLANG_RECORD_ASSERT(VALUE) \ + do { \ + if (!(VALUE)) { \ + SlangRecord::slangRecordLog(SlangRecord::LogLevel::Error, "Assertion failed: %s, %s, %d\n", #VALUE, __FILE__, __LINE__);\ + std::abort(); \ + } \ + } while(0) + +#define SLANG_RECORD_CHECK(VALUE) \ + do { \ + SLANG_RECORD_ASSERT((VALUE) == SLANG_OK); \ + } while(0) +#endif // RECORD_UTILITY_H |
