summaryrefslogtreecommitdiffstats
path: root/source/slang-record-replay
diff options
context:
space:
mode:
authorkaizhangNV <149626564+kaizhangNV@users.noreply.github.com>2024-07-23 10:45:26 -0500
committerGitHub <noreply@github.com>2024-07-23 08:45:26 -0700
commit986256ffb92ab7c8fc7cf9f2c424919a439a824f (patch)
tree260e37bd439275e3398d16fe238b20cd00d08cb7 /source/slang-record-replay
parentc28d8b6aec721fa3350fc52647f1572a353f6151 (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')
-rw-r--r--source/slang-record-replay/record/output-stream.cpp52
-rw-r--r--source/slang-record-replay/record/output-stream.h46
-rw-r--r--source/slang-record-replay/record/parameter-recorder.cpp123
-rw-r--r--source/slang-record-replay/record/parameter-recorder.h94
-rw-r--r--source/slang-record-replay/record/record-manager.cpp97
-rw-r--r--source/slang-record-replay/record/record-manager.h35
-rw-r--r--source/slang-record-replay/record/slang-composite-component-type.cpp309
-rw-r--r--source/slang-record-replay/record/slang-composite-component-type.h76
-rw-r--r--source/slang-record-replay/record/slang-entrypoint.cpp313
-rw-r--r--source/slang-record-replay/record/slang-entrypoint.h77
-rw-r--r--source/slang-record-replay/record/slang-filesystem.cpp124
-rw-r--r--source/slang-record-replay/record/slang-filesystem.h71
-rw-r--r--source/slang-record-replay/record/slang-global-session.cpp452
-rw-r--r--source/slang-record-replay/record/slang-global-session.h85
-rw-r--r--source/slang-record-replay/record/slang-module.cpp496
-rw-r--r--source/slang-record-replay/record/slang-module.h102
-rw-r--r--source/slang-record-replay/record/slang-session.cpp517
-rw-r--r--source/slang-record-replay/record/slang-session.h110
-rw-r--r--source/slang-record-replay/record/slang-type-conformance.cpp310
-rw-r--r--source/slang-record-replay/record/slang-type-conformance.h77
-rw-r--r--source/slang-record-replay/replay/decoder-consumer.cpp0
-rw-r--r--source/slang-record-replay/replay/decoder-consumer.h178
-rw-r--r--source/slang-record-replay/replay/decoder-helper.cpp60
-rw-r--r--source/slang-record-replay/replay/decoder-helper.h109
-rw-r--r--source/slang-record-replay/replay/json-consumer.cpp477
-rw-r--r--source/slang-record-replay/replay/json-consumer.h174
-rw-r--r--source/slang-record-replay/replay/parameter-decoder.cpp215
-rw-r--r--source/slang-record-replay/replay/parameter-decoder.h131
-rw-r--r--source/slang-record-replay/replay/recordFile-processor.cpp132
-rw-r--r--source/slang-record-replay/replay/recordFile-processor.h30
-rw-r--r--source/slang-record-replay/replay/replay-consumer.cpp481
-rw-r--r--source/slang-record-replay/replay/replay-consumer.h196
-rw-r--r--source/slang-record-replay/replay/slang-decoder.cpp1974
-rw-r--r--source/slang-record-replay/replay/slang-decoder.h154
-rw-r--r--source/slang-record-replay/util/record-format.h172
-rw-r--r--source/slang-record-replay/util/record-utility.cpp82
-rw-r--r--source/slang-record-replay/util/record-utility.h37
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