summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-stream.h5
-rw-r--r--source/slang-capture-replay/api_callId.h147
-rw-r--r--source/slang-capture-replay/capture-manager.cpp53
-rw-r--r--source/slang-capture-replay/capture-manager.h30
-rw-r--r--source/slang-capture-replay/output-stream.cpp52
-rw-r--r--source/slang-capture-replay/output-stream.h46
-rw-r--r--source/slang-capture-replay/parameter-encoder.cpp72
-rw-r--r--source/slang-capture-replay/parameter-encoder.h51
-rw-r--r--source/slang-capture-replay/slang-global-session.cpp13
-rw-r--r--source/slang-capture-replay/slang-global-session.h13
10 files changed, 479 insertions, 3 deletions
diff --git a/source/core/slang-stream.h b/source/core/slang-stream.h
index 9f405dbb0..a62c18838 100644
--- a/source/core/slang-stream.h
+++ b/source/core/slang-stream.h
@@ -138,7 +138,10 @@ public:
void setContent(const void* contents, size_t contentsSize)
{
m_ownedContents.setCount(contentsSize);
- ::memcpy(m_ownedContents.getBuffer(), contents, contentsSize);
+ if (contentsSize > 0)
+ {
+ ::memcpy(m_ownedContents.getBuffer(), contents, contentsSize);
+ }
_setContents(m_ownedContents.getBuffer(), m_ownedContents.getCount());
}
diff --git a/source/slang-capture-replay/api_callId.h b/source/slang-capture-replay/api_callId.h
new file mode 100644
index 000000000..0a96ef4a7
--- /dev/null
+++ b/source/slang-capture-replay/api_callId.h
@@ -0,0 +1,147 @@
+#ifndef API_CALL_ID_H
+#define API_CALL_ID_H
+
+#include <cstdint>
+
+namespace SlangCapture
+{
+ constexpr uint32_t makeApiCallId(uint16_t classId, uint16_t memberFunctionId)
+ {
+ return ((static_cast<uint32_t>(classId) << 16) & 0xffff0000) | (static_cast<uint32_t>(memberFunctionId) & 0x0000ffff);
+ }
+
+ constexpr uint16_t getClassId(uint32_t callId)
+ {
+ return static_cast<uint16_t>((callId >> 16) & 0x0000ffff);
+ }
+
+ constexpr uint16_t getMemberFunctionId(uint32_t callId)
+ {
+ return static_cast<uint16_t>(callId & 0x0000ffff);
+ }
+
+ enum ApiClassId : uint16_t
+ {
+ GlobalFunction = 1,
+ Class_IGlobalSession = 2,
+ Class_ISession = 3,
+ Class_IModule = 4,
+ Class_IEntryPoint = 5,
+ Class_ICompositeComponentType = 6,
+ Class_ITypeConformance = 7,
+ };
+
+ typedef uint64_t AddressFormat;
+
+ constexpr uint64_t g_globalFunctionHandle = 0;
+
+ enum ApiCallId : uint32_t
+ {
+ InvalidCallId = 0x00000000,
+ ICreateGlobalSession = makeApiCallId(GlobalFunction, 0x0000),
+ IGlobalSession_createSession = makeApiCallId(Class_IGlobalSession, 0x0001),
+ IGlobalSession_findProfile = makeApiCallId(Class_IGlobalSession, 0x0002),
+ IGlobalSession_setDownstreamCompilerPath = makeApiCallId(Class_IGlobalSession, 0x0003),
+ IGlobalSession_setDownstreamCompilerPrelude = makeApiCallId(Class_IGlobalSession, 0x0004),
+ IGlobalSession_getDownstreamCompilerPrelude = makeApiCallId(Class_IGlobalSession, 0x0005),
+ IGlobalSession_getBuildTagString = makeApiCallId(Class_IGlobalSession, 0x0006),
+ IGlobalSession_setDefaultDownstreamCompiler = makeApiCallId(Class_IGlobalSession, 0x0007),
+ IGlobalSession_getDefaultDownstreamCompiler = makeApiCallId(Class_IGlobalSession, 0x0008),
+ IGlobalSession_setLanguagePrelude = makeApiCallId(Class_IGlobalSession, 0x0009),
+ IGlobalSession_getLanguagePrelude = makeApiCallId(Class_IGlobalSession, 0x000A),
+ IGlobalSession_createCompileRequest = makeApiCallId(Class_IGlobalSession, 0x000B),
+ IGlobalSession_addBuiltins = makeApiCallId(Class_IGlobalSession, 0x000C),
+ IGlobalSession_setSharedLibraryLoader = makeApiCallId(Class_IGlobalSession, 0x000D),
+ IGlobalSession_getSharedLibraryLoader = makeApiCallId(Class_IGlobalSession, 0x000E),
+ IGlobalSession_checkCompileTargetSupport = makeApiCallId(Class_IGlobalSession, 0x000F),
+ IGlobalSession_checkPassThroughSupport = makeApiCallId(Class_IGlobalSession, 0x0010),
+ IGlobalSession_compileStdLib = makeApiCallId(Class_IGlobalSession, 0x0011),
+ IGlobalSession_loadStdLib = makeApiCallId(Class_IGlobalSession, 0x0012),
+ IGlobalSession_saveStdLib = makeApiCallId(Class_IGlobalSession, 0x0013),
+ IGlobalSession_findCapability = makeApiCallId(Class_IGlobalSession, 0x0014),
+ IGlobalSession_setDownstreamCompilerForTransition = makeApiCallId(Class_IGlobalSession, 0x0015),
+ IGlobalSession_getDownstreamCompilerForTransition = makeApiCallId(Class_IGlobalSession, 0x0016),
+ IGlobalSession_getCompilerElapsedTime = makeApiCallId(Class_IGlobalSession, 0x0017),
+ IGlobalSession_setSPIRVCoreGrammar = makeApiCallId(Class_IGlobalSession, 0x0018),
+ IGlobalSession_parseCommandLineArguments = makeApiCallId(Class_IGlobalSession, 0x0019),
+ IGlobalSession_getSessionDescDigest = makeApiCallId(Class_IGlobalSession, 0x001A),
+
+ ISession_getGlobalSession = makeApiCallId(Class_ISession, 0x0001),
+ ISession_loadModule = makeApiCallId(Class_ISession, 0x0002),
+ ISession_loadModuleFromBlob = makeApiCallId(Class_ISession, 0x0003),
+ ISession_loadModuleFromIRBlob = makeApiCallId(Class_ISession, 0x0004),
+ ISession_loadModuleFromSource = makeApiCallId(Class_ISession, 0x0005),
+ ISession_loadModuleFromSourceString = makeApiCallId(Class_ISession, 0x0006),
+ ISession_createCompositeComponentType = makeApiCallId(Class_ISession, 0x0007),
+ ISession_specializeType = makeApiCallId(Class_ISession, 0x0008),
+ ISession_getTypeLayout = makeApiCallId(Class_ISession, 0x0009),
+ ISession_getContainerType = makeApiCallId(Class_ISession, 0x000A),
+ ISession_getDynamicType = makeApiCallId(Class_ISession, 0x000B),
+ ISession_getTypeRTTIMangledName = makeApiCallId(Class_ISession, 0x000C),
+ ISession_getTypeConformanceWitnessMangledName = makeApiCallId(Class_ISession, 0x000D),
+ ISession_getTypeConformanceWitnessSequentialID = makeApiCallId(Class_ISession, 0x000E),
+ ISession_createTypeConformanceComponentType = makeApiCallId(Class_ISession, 0x000F),
+ ISession_createCompileRequest = makeApiCallId(Class_ISession, 0x0010),
+ ISession_getLoadedModuleCount = makeApiCallId(Class_ISession, 0x0011),
+ ISession_getLoadedModule = makeApiCallId(Class_ISession, 0x0012),
+ ISession_isBinaryModuleUpToDate = makeApiCallId(Class_ISession, 0x0013),
+
+ IModule_findEntryPointByName = makeApiCallId(Class_IModule, 0x0001),
+ IModule_getDefinedEntryPointCount = makeApiCallId(Class_IModule, 0x0002),
+ IModule_getDefinedEntryPoint = makeApiCallId(Class_IModule, 0x0003),
+ IModule_serialize = makeApiCallId(Class_IModule, 0x0004),
+ IModule_writeToFile = makeApiCallId(Class_IModule, 0x0005),
+ IModule_getName = makeApiCallId(Class_IModule, 0x0006),
+ IModule_getFilePath = makeApiCallId(Class_IModule, 0x0007),
+ IModule_getUniqueIdentity = makeApiCallId(Class_IModule, 0x0008),
+ IModule_findAndCheckEntryPoint = makeApiCallId(Class_IModule, 0x0009),
+ IModule_getSession = makeApiCallId(Class_IModule, 0x000A),
+ IModule_getLayout = makeApiCallId(Class_IModule, 0x000B),
+ IModule_getSpecializationParamCount = makeApiCallId(Class_IModule, 0x000C),
+ IModule_getEntryPointCode = makeApiCallId(Class_IModule, 0x000D),
+ IModule_getResultAsFileSystem = makeApiCallId(Class_IModule, 0x000E),
+ IModule_getEntryPointHash = makeApiCallId(Class_IModule, 0x000F),
+ IModule_specialize = makeApiCallId(Class_IModule, 0x0010),
+ IModule_link = makeApiCallId(Class_IModule, 0x0011),
+ IModule_getEntryPointHostCallable = makeApiCallId(Class_IModule, 0x0012),
+ IModule_renameEntryPoint = makeApiCallId(Class_IModule, 0x0013),
+ IModule_linkWithOptions = makeApiCallId(Class_IModule, 0x0014),
+
+ IEntryPoint_getSession = makeApiCallId(Class_IEntryPoint, 0x0001),
+ IEntryPoint_getLayout = makeApiCallId(Class_IEntryPoint, 0x0002),
+ IEntryPoint_getSpecializationParamCount = makeApiCallId(Class_IEntryPoint, 0x0003),
+ IEntryPoint_getEntryPointCode = makeApiCallId(Class_IEntryPoint, 0x0004),
+ IEntryPoint_getResultAsFileSystem = makeApiCallId(Class_IEntryPoint, 0x0005),
+ IEntryPoint_getEntryPointHash = makeApiCallId(Class_IEntryPoint, 0x0006),
+ IEntryPoint_specialize = makeApiCallId(Class_IEntryPoint, 0x0007),
+ IEntryPoint_link = makeApiCallId(Class_IEntryPoint, 0x0008),
+ IEntryPoint_getEntryPointHostCallable = makeApiCallId(Class_IEntryPoint, 0x0009),
+ IEntryPoint_renameEntryPoint = makeApiCallId(Class_IEntryPoint, 0x000A),
+ IEntryPoint_linkWithOptions = makeApiCallId(Class_IEntryPoint, 0x000B),
+
+ ICompositeComponentType_getSession = makeApiCallId(Class_ICompositeComponentType, 0x0001),
+ ICompositeComponentType_getLayout = makeApiCallId(Class_ICompositeComponentType, 0x0002),
+ ICompositeComponentType_getSpecializationParamCount = makeApiCallId(Class_ICompositeComponentType, 0x0003),
+ ICompositeComponentType_getEntryPointCode = makeApiCallId(Class_ICompositeComponentType, 0x0004),
+ ICompositeComponentType_getResultAsFileSystem = makeApiCallId(Class_ICompositeComponentType, 0x0005),
+ ICompositeComponentType_getEntryPointHash = makeApiCallId(Class_ICompositeComponentType, 0x0006),
+ ICompositeComponentType_specialize = makeApiCallId(Class_ICompositeComponentType, 0x0007),
+ ICompositeComponentType_link = makeApiCallId(Class_ICompositeComponentType, 0x0008),
+ ICompositeComponentType_getEntryPointHostCallable = makeApiCallId(Class_ICompositeComponentType, 0x0009),
+ ICompositeComponentType_renameEntryPoint = makeApiCallId(Class_ICompositeComponentType, 0x000A),
+ ICompositeComponentType_linkWithOptions = makeApiCallId(Class_ICompositeComponentType, 0x000B),
+
+ ITypeConformance_getSession = makeApiCallId(Class_ITypeConformance, 0x0001),
+ ITypeConformance_getLayout = makeApiCallId(Class_ITypeConformance, 0x0002),
+ ITypeConformance_getSpecializationParamCount = makeApiCallId(Class_ITypeConformance, 0x0003),
+ ITypeConformance_getEntryPointCode = makeApiCallId(Class_ITypeConformance, 0x0004),
+ ITypeConformance_getResultAsFileSystem = makeApiCallId(Class_ITypeConformance, 0x0005),
+ ITypeConformance_getEntryPointHash = makeApiCallId(Class_ITypeConformance, 0x0006),
+ ITypeConformance_specialize = makeApiCallId(Class_ITypeConformance, 0x0007),
+ ITypeConformance_link = makeApiCallId(Class_ITypeConformance, 0x0008),
+ ITypeConformance_getEntryPointHostCallable = makeApiCallId(Class_ITypeConformance, 0x0009),
+ ITypeConformance_renameEntryPoint = makeApiCallId(Class_ITypeConformance, 0x000A),
+ ITypeConformance_linkWithOptions = makeApiCallId(Class_ITypeConformance, 0x000B)
+ };
+}
+#endif
diff --git a/source/slang-capture-replay/capture-manager.cpp b/source/slang-capture-replay/capture-manager.cpp
new file mode 100644
index 000000000..be5615e00
--- /dev/null
+++ b/source/slang-capture-replay/capture-manager.cpp
@@ -0,0 +1,53 @@
+
+#include <string>
+#include <sstream>
+#include <thread>
+#include "capture-manager.h"
+
+namespace SlangCapture
+{
+ CaptureManager::CaptureManager(uint64_t globalSessionHandle)
+ : m_encoder(&m_memoryStream)
+ {
+ std::stringstream ss;
+ ss << "gs-"<< globalSessionHandle <<"t-"<<std::this_thread::get_id() << ".cap";
+ m_fileStream = std::make_unique<FileOutputStream>(ss.str());
+ }
+
+ void CaptureManager::clearWithHeader(const ApiCallId& callId, uint64_t handleId)
+ {
+ m_memoryStream.flush();
+ FunctionHeader header {};
+ header.callId = callId;
+ header.handleId = handleId;
+
+ // write header to memory stream
+ m_memoryStream.write(&header, sizeof(FunctionHeader));
+ }
+
+ ParameterEncoder* CaptureManager::beginMethodCapture(const ApiCallId& callId, uint64_t handleId)
+ {
+ clearWithHeader(callId, handleId);
+ return &m_encoder;
+ }
+
+ void CaptureManager::endMethodCapture()
+ {
+ FunctionHeader* pHeader = const_cast<FunctionHeader*>(
+ reinterpret_cast<const FunctionHeader*>(m_memoryStream.getData()));
+
+ pHeader->dataSizeInBytes = m_memoryStream.getSizeInBytes() - sizeof(FunctionHeader);
+
+ std::hash<std::thread::id> hasher;
+ pHeader->threadId = hasher(std::this_thread::get_id());
+
+ // write capture data to file
+ m_fileStream->write(m_memoryStream.getData(), m_memoryStream.getSizeInBytes());
+
+ // take effect of the write
+ m_fileStream->flush();
+
+ // clear the memory stream
+ m_memoryStream.flush();
+ }
+}
diff --git a/source/slang-capture-replay/capture-manager.h b/source/slang-capture-replay/capture-manager.h
new file mode 100644
index 000000000..55d42c458
--- /dev/null
+++ b/source/slang-capture-replay/capture-manager.h
@@ -0,0 +1,30 @@
+#ifndef CAPTURE_MANAGER_H
+#define CAPTURE_MANAGER_H
+
+#include "parameter-encoder.h"
+#include "api_callId.h"
+namespace SlangCapture
+{
+ class CaptureManager
+ {
+ public:
+ CaptureManager(uint64_t globalSessionHandle);
+ ParameterEncoder* beginMethodCapture(const ApiCallId& callId, uint64_t handleId);
+ void endMethodCapture();
+ private:
+ void clearWithHeader(const ApiCallId& callId, uint64_t handleId);
+
+ struct FunctionHeader
+ {
+ ApiCallId callId {InvalidCallId};
+ uint64_t handleId {0};
+ uint64_t dataSizeInBytes {0};
+ uint64_t threadId {0};
+ };
+
+ MemoryStream m_memoryStream;
+ std::unique_ptr<FileOutputStream> m_fileStream;
+ ParameterEncoder m_encoder;
+ };
+} // namespace SlangCapture
+#endif // CAPTURE_MANAGER_H
diff --git a/source/slang-capture-replay/output-stream.cpp b/source/slang-capture-replay/output-stream.cpp
new file mode 100644
index 000000000..acde6fbf1
--- /dev/null
+++ b/source/slang-capture-replay/output-stream.cpp
@@ -0,0 +1,52 @@
+#include "output-stream.h"
+#include "capture_utility.h"
+
+namespace SlangCapture
+{
+ FileOutputStream::FileOutputStream(const std::string& filename, bool append)
+ {
+ Slang::String path(filename.c_str());
+ Slang::FileMode fileMode = append ? Slang::FileMode::Append : Slang::FileMode::Create;
+ Slang::FileAccess fileAccess = Slang::FileAccess::Write;
+ Slang::FileShare fileShare = Slang::FileShare::None;
+
+ SlangResult res = m_fileStream.init(path, fileMode, fileAccess, fileShare);
+
+ if (res != SLANG_OK)
+ {
+ SlangCapture::slangCaptureLog(SlangCapture::LogLevel::Error, "Failed to open file %s\n", filename.c_str());
+ std::abort();
+ }
+ }
+
+ FileOutputStream::~FileOutputStream()
+ {
+ m_fileStream.close();
+ }
+
+ void FileOutputStream::write(const void* data, size_t len)
+ {
+ SLANG_CAPTURE_ASSERT(m_fileStream.write(data, len));
+ }
+
+ MemoryStream::MemoryStream()
+ : m_memoryStream(Slang::FileAccess::Write)
+ { }
+
+ void FileOutputStream::flush()
+ {
+ SLANG_CAPTURE_ASSERT(m_fileStream.flush());
+ }
+
+ void MemoryStream::write(const void* data, size_t len)
+ {
+ SLANG_CAPTURE_ASSERT(m_memoryStream.write(data, len));
+ }
+
+ void MemoryStream::flush()
+ {
+ // This call will reset the underlying buffer to size 0,
+ // and reset the write position to 0.
+ m_memoryStream.setContent(nullptr, 0);
+ }
+}
diff --git a/source/slang-capture-replay/output-stream.h b/source/slang-capture-replay/output-stream.h
new file mode 100644
index 000000000..1f2c882b0
--- /dev/null
+++ b/source/slang-capture-replay/output-stream.h
@@ -0,0 +1,46 @@
+#ifndef OUTPUT_STREAM_H
+#define OUTPUT_STREAM_H
+
+#include <string>
+#include "../core/slang-stream.h"
+
+namespace SlangCapture
+{
+ 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 SlangCapture
+#endif // OUTPUT_STREAM_H
diff --git a/source/slang-capture-replay/parameter-encoder.cpp b/source/slang-capture-replay/parameter-encoder.cpp
new file mode 100644
index 000000000..5167cc2ab
--- /dev/null
+++ b/source/slang-capture-replay/parameter-encoder.cpp
@@ -0,0 +1,72 @@
+#include "parameter-encoder.h"
+
+namespace SlangCapture
+{
+ void ParameterEncoder::encodeStruct(slang::SessionDesc const& desc)
+ {
+ encodeUint64(desc.structureSize);
+ encodeInt64(desc.targetCount);
+
+ for (SlangInt i = 0; i < desc.targetCount; i++)
+ {
+ encodeStruct(desc.targets[i]);
+ }
+
+ encodeUint32(desc.flags);
+ encodeUint32(desc.defaultMatrixLayoutMode);
+ encodeInt64(desc.searchPathCount);
+ for (SlangInt i = 0; i < desc.searchPathCount; i++)
+ {
+ encodeString(desc.searchPaths[i]);
+ }
+
+ encodeInt64(desc.preprocessorMacroCount);
+ for (SlangInt i = 0; i < desc.preprocessorMacroCount; i++)
+ {
+ encodeStruct(desc.preprocessorMacros[i]);
+ }
+
+ encodeBool(desc.enableEffectAnnotations);
+ encodeBool(desc.allowGLSLSyntax);
+
+ encodeUint32(desc.compilerOptionEntryCount);
+ for (uint32_t i = 0; i < desc.compilerOptionEntryCount; i++)
+ {
+ encodeStruct(desc.compilerOptionEntries[i]);
+ }
+ }
+
+ void ParameterEncoder::encodeStruct(slang::PreprocessorMacroDesc const& desc)
+ {
+ encodeString(desc.name);
+ encodeString(desc.value);
+ }
+
+ void ParameterEncoder::encodeStruct(slang::CompilerOptionEntry const& entry)
+ {
+ encodeInt32((int32_t)(entry.name));
+ encodeStruct(entry.value);
+ }
+
+ void ParameterEncoder::encodeStruct(slang::CompilerOptionValue const& value)
+ {
+ (void)value;
+ }
+
+ void ParameterEncoder::encodeStruct(slang::TargetDesc const& targetDesc)
+ {
+ (void)targetDesc;
+ }
+
+ void ParameterEncoder::encodePointer(const void* value, bool omitData, size_t size)
+ {
+ (void)value;
+ (void)omitData;
+ (void)size;
+ }
+ // first 4-bytes is the length of the string
+ void ParameterEncoder::encodeString(const char* value)
+ {
+ (void)value;
+ }
+}
diff --git a/source/slang-capture-replay/parameter-encoder.h b/source/slang-capture-replay/parameter-encoder.h
new file mode 100644
index 000000000..c7c2d959a
--- /dev/null
+++ b/source/slang-capture-replay/parameter-encoder.h
@@ -0,0 +1,51 @@
+#ifndef PARAMETER_ENCODER_H
+#define PARAMETER_ENCODER_H
+
+#include <cstdio>
+#include <cinttypes>
+#include <cstdint>
+
+#include "output-stream.h"
+
+namespace SlangCapture
+{
+ class ParameterEncoder
+ {
+ public:
+ ParameterEncoder(OutputStream* stream) : m_stream(stream) {};
+ void encodeInt8(int8_t value) { encodeValue(value); }
+ void encodeUint8(uint8_t value) { encodeValue(value); }
+ void encodeInt16(int16_t value) { encodeValue(value); }
+ void encodeUint16(uint16_t value) { encodeValue(value); }
+ void encodeInt32(int32_t value) { encodeValue(value); }
+ void encodeUint32(uint32_t value) { encodeValue(value); }
+ void encodeInt64(int64_t value) { encodeValue(value); }
+ void encodeUint64(uint64_t value) { encodeValue(value); }
+ void encodeFloat(float value) { encodeValue(value); }
+ void encodeDouble(double value) { encodeValue(value); }
+ void encodeBool(bool value) { encodeValue(value); }
+
+ template<typename T>
+ void encodeEnumValue(T value) { encodeValue(static_cast<uint32_t>(value)); }
+
+ void encodeString(const char* value);
+ void encodePointer(const void* value, bool omitData = false, size_t size = 0);
+ void encodeAddress(const void* value) { encodeValue(reinterpret_cast<uint64_t>(value)); }
+
+ void encodeStruct(slang::SessionDesc const& desc);
+ void encodeStruct(slang::PreprocessorMacroDesc const& desc);
+ void encodeStruct(slang::CompilerOptionEntry const& entry);
+ void encodeStruct(slang::CompilerOptionValue const& value);
+ void encodeStruct(slang::TargetDesc const& targetDesc);
+
+ private:
+ template <typename T>
+ void encodeValue(T value)
+ {
+ m_stream->write(&value, sizeof(T));
+ }
+ OutputStream* m_stream;
+ };
+} // namespace SlangCapture
+
+#endif // PARAMETER_ENCODER_H
diff --git a/source/slang-capture-replay/slang-global-session.cpp b/source/slang-capture-replay/slang-global-session.cpp
index 05a2b93ec..45ea0b58d 100644
--- a/source/slang-capture-replay/slang-global-session.cpp
+++ b/source/slang-capture-replay/slang-global-session.cpp
@@ -1,5 +1,3 @@
-
-#include <vector>
#include "slang-global-session.h"
#include "slang-session.h"
#include "slang-filesystem.h"
@@ -8,10 +6,21 @@
namespace SlangCapture
{
+ // constructor is called in slang_createGlobalSession
GlobalSessionCapture::GlobalSessionCapture(slang::IGlobalSession* session):
m_actualGlobalSession(session)
{
SLANG_CAPTURE_ASSERT(m_actualGlobalSession != nullptr);
+
+ m_thisHandle = reinterpret_cast<SlangCapture::AddressFormat>(this);
+ m_captureManager = std::make_unique<CaptureManager>(m_thisHandle);
+
+ // We will use the address of the global session as the filename for the capture manager
+ // to make it unique for each global session.
+ // capture slang::createGlobalSession
+ ParameterEncoder* encoder = m_captureManager->beginMethodCapture(ApiCallId::ICreateGlobalSession, g_globalFunctionHandle);
+ encoder->encodeAddress(m_actualGlobalSession);
+ m_captureManager->endMethodCapture();
}
GlobalSessionCapture::~GlobalSessionCapture()
diff --git a/source/slang-capture-replay/slang-global-session.h b/source/slang-capture-replay/slang-global-session.h
index 52260ba21..6923ddf11 100644
--- a/source/slang-capture-replay/slang-global-session.h
+++ b/source/slang-capture-replay/slang-global-session.h
@@ -5,6 +5,7 @@
#include "../../slang.h"
#include "../../slang-com-helper.h"
#include "../core/slang-smart-pointer.h"
+#include "capture-manager.h"
namespace SlangCapture
{
@@ -58,6 +59,8 @@ namespace SlangCapture
SLANG_NO_THROW SlangResult SLANG_MCALL getSessionDescDigest(slang::SessionDesc* sessionDesc, ISlangBlob** outBlob) override;
+ CaptureManager* getCaptureManager() { return m_captureManager.get(); }
+
private:
SLANG_FORCE_INLINE slang::IGlobalSession* asExternal(GlobalSessionCapture* session)
{
@@ -65,6 +68,16 @@ namespace SlangCapture
}
Slang::ComPtr<slang::IGlobalSession> m_actualGlobalSession;
+
+ // we will create one capture 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 capture 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<CaptureManager> m_captureManager;
+ uint64_t m_thisHandle = 0;
};
} // namespace Slang