Skip to content

Commit 8000e0e

Browse files
authored
Cache and reuse glsl module. (#6152)
* Cache and reuse glsl module. * Fix. * Implement record/replay for the new api. * Fix record replay. * Fix test.
1 parent 04353fb commit 8000e0e

25 files changed

+577
-100
lines changed

docs/user-guide/08-compiling.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -589,12 +589,16 @@ A global session is created using the function `slang::createGlobalSession()`:
589589
using namespace slang;
590590

591591
Slang::ComPtr<IGlobalSession> globalSession;
592-
createGlobalSession(globalSession.writeRef());
592+
SlangGlobalSessionDesc desc = {};
593+
createGlobalSession(&desc, globalSession.writeRef());
593594
```
594595
595596
When a global session is created, the Slang system will load its internal representation of the _core module_ that the compiler provides to user code.
596597
The core module can take a significant amount of time to load, so applications are advised to use a single global session if possible, rather than creating and then disposing of one for each compile.
597598
599+
If you want to enable GLSL compatibility mode, you need to set `SlangGlobalSessionDesc::enableGLSL` to `true` when calling `createGlobalSession()`. This will load the necessary GLSL intrinsic module
600+
for compiling GLSL code. Without this setting, compiling GLSL code will result in an error.
601+
598602
> #### Note ####
599603
> Currently, the global session type is *not* thread-safe.
600604
> Applications that wish to compile on multiple threads will need to ensure that each concurrent thread compiles with a distinct global session.
@@ -874,6 +878,7 @@ The only functions which are currently thread safe are
874878
```C++
875879
SlangSession* spCreateSession(const char* deprecated);
876880
SlangResult slang_createGlobalSession(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession);
881+
SlangResult slang_createGlobalSession2(const SlangGlobalSessionDesc* desc, slang::IGlobalSession** outGlobalSession);
877882
SlangResult slang_createGlobalSessionWithoutCoreModule(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession);
878883
ISlangBlob* slang_getEmbeddedCoreModule();
879884
SlangResult slang::createGlobalSession(slang::IGlobalSession** outGlobalSession);

include/slang.h

+80-1
Original file line numberDiff line numberDiff line change
@@ -3520,6 +3520,12 @@ struct SessionDesc;
35203520
struct SpecializationArg;
35213521
struct TargetDesc;
35223522

3523+
enum class BuiltinModuleName
3524+
{
3525+
Core,
3526+
GLSL
3527+
};
3528+
35233529
/** A global session for interaction with the Slang library.
35243530
35253531
An application may create and re-use a single global session across
@@ -3750,6 +3756,36 @@ struct IGlobalSession : public ISlangUnknown
37503756
*/
37513757
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
37523758
getSessionDescDigest(SessionDesc* sessionDesc, ISlangBlob** outBlob) = 0;
3759+
3760+
/** Compile from (embedded source) the builtin module on the session.
3761+
Will return a failure if there is already a builtin module available.
3762+
NOTE! API is experimental and not ready for production code.
3763+
@param module The builtin module name.
3764+
@param flags to control compilation
3765+
*/
3766+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
3767+
compileBuiltinModule(BuiltinModuleName module, CompileCoreModuleFlags flags) = 0;
3768+
3769+
/** Load a builtin module. Currently loads modules from the file system.
3770+
@param module The builtin module name
3771+
@param moduleData Start address of the serialized core module
3772+
@param sizeInBytes The size in bytes of the serialized builtin module
3773+
3774+
NOTE! API is experimental and not ready for production code
3775+
*/
3776+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
3777+
loadBuiltinModule(BuiltinModuleName module, const void* moduleData, size_t sizeInBytes) = 0;
3778+
3779+
/** Save the builtin module to the file system
3780+
@param module The builtin module name
3781+
@param archiveType The type of archive used to hold the builtin module
3782+
@param outBlob The serialized blob containing the builtin module
3783+
3784+
NOTE! API is experimental and not ready for production code */
3785+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveBuiltinModule(
3786+
BuiltinModuleName module,
3787+
SlangArchiveType archiveType,
3788+
ISlangBlob** outBlob) = 0;
37533789
};
37543790

37553791
#define SLANG_UUID_IGlobalSession IGlobalSession::getTypeGuid()
@@ -4429,6 +4465,32 @@ struct SpecializationArg
44294465
// using.
44304466
#define SLANG_API_VERSION 0
44314467

4468+
enum SlangLanguageVersion
4469+
{
4470+
SLANG_LANGUAGE_VERSION_2025 = 2025
4471+
};
4472+
4473+
4474+
/* Description of a Slang global session.
4475+
*/
4476+
struct SlangGlobalSessionDesc
4477+
{
4478+
/// Size of this struct.
4479+
uint32_t structureSize = sizeof(SlangGlobalSessionDesc);
4480+
4481+
/// Slang API version.
4482+
uint32_t apiVersion = SLANG_API_VERSION;
4483+
4484+
/// Slang language version.
4485+
uint32_t languageVersion = SLANG_LANGUAGE_VERSION_2025;
4486+
4487+
/// Whether to enable GLSL support.
4488+
bool enableGLSL = false;
4489+
4490+
/// Reserved for future use.
4491+
uint32_t reserved[16] = {};
4492+
};
4493+
44324494
/* Create a global session, with the built-in core module.
44334495
44344496
@param apiVersion Pass in SLANG_API_VERSION
@@ -4437,6 +4499,16 @@ struct SpecializationArg
44374499
SLANG_EXTERN_C SLANG_API SlangResult
44384500
slang_createGlobalSession(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession);
44394501

4502+
4503+
/* Create a global session, with the built-in core module.
4504+
4505+
@param desc Description of the global session.
4506+
@param outGlobalSession (out)The created global session.
4507+
*/
4508+
SLANG_EXTERN_C SLANG_API SlangResult slang_createGlobalSession2(
4509+
const SlangGlobalSessionDesc* desc,
4510+
slang::IGlobalSession** outGlobalSession);
4511+
44404512
/* Create a global session, but do not set up the core module. The core module can
44414513
then be loaded via loadCoreModule or compileCoreModule
44424514
@@ -4472,7 +4544,14 @@ namespace slang
44724544
{
44734545
inline SlangResult createGlobalSession(slang::IGlobalSession** outGlobalSession)
44744546
{
4475-
return slang_createGlobalSession(SLANG_API_VERSION, outGlobalSession);
4547+
SlangGlobalSessionDesc defaultDesc = {};
4548+
return slang_createGlobalSession2(&defaultDesc, outGlobalSession);
4549+
}
4550+
inline SlangResult createGlobalSession(
4551+
const SlangGlobalSessionDesc* desc,
4552+
slang::IGlobalSession** outGlobalSession)
4553+
{
4554+
return slang_createGlobalSession2(desc, outGlobalSession);
44764555
}
44774556
inline void shutdown()
44784557
{

source/slang-record-replay/record/parameter-recorder.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
namespace SlangRecord
44
{
5+
void ParameterRecorder::recordStruct(SlangGlobalSessionDesc const& desc)
6+
{
7+
recordUint32(desc.structureSize);
8+
recordUint32(desc.apiVersion);
9+
recordUint32(desc.languageVersion);
10+
recordUint32(desc.enableGLSL);
11+
}
12+
513
void ParameterRecorder::recordStruct(slang::SessionDesc const& desc)
614
{
715
recordUint64(desc.structureSize);

source/slang-record-replay/record/parameter-recorder.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ParameterRecorder
4040
{
4141
recordValue(reinterpret_cast<SlangRecord::AddressFormat>(value));
4242
}
43-
43+
void recordStruct(SlangGlobalSessionDesc const& desc);
4444
void recordStruct(slang::SessionDesc const& desc);
4545
void recordStruct(slang::PreprocessorMacroDesc const& desc);
4646
void recordStruct(slang::CompilerOptionEntry const& entry);

source/slang-record-replay/record/slang-global-session.cpp

+71-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
namespace SlangRecord
99
{
1010
// constructor is called in slang_createGlobalSession
11-
GlobalSessionRecorder::GlobalSessionRecorder(slang::IGlobalSession* session)
11+
GlobalSessionRecorder::GlobalSessionRecorder(
12+
const SlangGlobalSessionDesc* desc,
13+
slang::IGlobalSession* session)
1214
: m_actualGlobalSession(session)
1315
{
1416
SLANG_RECORD_ASSERT(m_actualGlobalSession != nullptr);
@@ -23,7 +25,10 @@ GlobalSessionRecorder::GlobalSessionRecorder(slang::IGlobalSession* session)
2325

2426
ParameterRecorder* recorder{};
2527
{
26-
m_recordManager->beginMethodRecord(ApiCallId::CreateGlobalSession, g_globalFunctionHandle);
28+
recorder = m_recordManager->beginMethodRecord(
29+
ApiCallId::CreateGlobalSession,
30+
g_globalFunctionHandle);
31+
recorder->recordStruct(*desc);
2732
recorder = m_recordManager->endMethodRecord();
2833
}
2934

@@ -416,6 +421,70 @@ GlobalSessionRecorder::saveCoreModule(SlangArchiveType archiveType, ISlangBlob**
416421
return res;
417422
}
418423

424+
SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::compileBuiltinModule(
425+
slang::BuiltinModuleName module,
426+
slang::CompileCoreModuleFlags flags)
427+
{
428+
slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
429+
430+
ParameterRecorder* recorder{};
431+
{
432+
recorder = m_recordManager->beginMethodRecord(
433+
ApiCallId::IGlobalSession_compileBuiltinModule,
434+
m_globalSessionHandle);
435+
recorder->recordEnumValue(module);
436+
recorder->recordEnumValue(flags);
437+
m_recordManager->endMethodRecord();
438+
}
439+
440+
SlangResult res = m_actualGlobalSession->compileBuiltinModule(module, flags);
441+
return res;
442+
}
443+
444+
SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::loadBuiltinModule(
445+
slang::BuiltinModuleName module,
446+
const void* moduleData,
447+
size_t sizeInBytes)
448+
{
449+
slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
450+
451+
ParameterRecorder* recorder{};
452+
{
453+
recorder = m_recordManager->beginMethodRecord(
454+
ApiCallId::IGlobalSession_loadBuiltinModule,
455+
m_globalSessionHandle);
456+
recorder->recordEnumValue(module);
457+
recorder->recordPointer(moduleData, false, sizeInBytes);
458+
m_recordManager->endMethodRecord();
459+
}
460+
461+
SlangResult res = m_actualGlobalSession->loadBuiltinModule(module, moduleData, sizeInBytes);
462+
return res;
463+
}
464+
SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::saveBuiltinModule(
465+
slang::BuiltinModuleName module,
466+
SlangArchiveType archiveType,
467+
ISlangBlob** outBlob)
468+
{
469+
slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
470+
471+
ParameterRecorder* recorder{};
472+
{
473+
recorder = m_recordManager->beginMethodRecord(
474+
ApiCallId::IGlobalSession_saveBuiltinModule,
475+
m_globalSessionHandle);
476+
recorder->recordEnumValue(module);
477+
recorder->recordEnumValue(archiveType);
478+
recorder = m_recordManager->endMethodRecord();
479+
}
480+
SlangResult res = m_actualGlobalSession->saveBuiltinModule(module, archiveType, outBlob);
481+
{
482+
recorder->recordAddress(*outBlob);
483+
m_recordManager->apendOutput();
484+
}
485+
return res;
486+
}
487+
419488
SLANG_NO_THROW SlangCapabilityID SLANG_MCALL GlobalSessionRecorder::findCapability(char const* name)
420489
{
421490
// No need to record this function. It's just a query function and it won't impact the internal

source/slang-record-replay/record/slang-global-session.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ using namespace Slang;
1414
class GlobalSessionRecorder : public RefObject, public slang::IGlobalSession
1515
{
1616
public:
17-
explicit GlobalSessionRecorder(slang::IGlobalSession* session);
17+
explicit GlobalSessionRecorder(
18+
const SlangGlobalSessionDesc* desc,
19+
slang::IGlobalSession* session);
1820

1921
SLANG_REF_OBJECT_IUNKNOWN_ADD_REF
2022
SLANG_REF_OBJECT_IUNKNOWN_RELEASE
@@ -64,6 +66,18 @@ class GlobalSessionRecorder : public RefObject, public slang::IGlobalSession
6466
SLANG_NO_THROW SlangResult SLANG_MCALL
6567
saveCoreModule(SlangArchiveType archiveType, ISlangBlob** outBlob) override;
6668

69+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL compileBuiltinModule(
70+
slang::BuiltinModuleName module,
71+
slang::CompileCoreModuleFlags flags) override;
72+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBuiltinModule(
73+
slang::BuiltinModuleName module,
74+
const void* moduleData,
75+
size_t sizeInBytes) override;
76+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveBuiltinModule(
77+
slang::BuiltinModuleName module,
78+
SlangArchiveType archiveType,
79+
ISlangBlob** outBlob) override;
80+
6781
SLANG_NO_THROW SlangCapabilityID SLANG_MCALL findCapability(char const* name) override;
6882

6983
SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerForTransition(

source/slang-record-replay/replay/decoder-consumer.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ namespace SlangRecord
1111
class IDecoderConsumer
1212
{
1313
public:
14-
virtual void CreateGlobalSession(ObjectID outGlobalSessionId) = 0;
14+
virtual void CreateGlobalSession(
15+
SlangGlobalSessionDesc const& desc,
16+
ObjectID outGlobalSessionId) = 0;
1517
virtual void IGlobalSession_createSession(
1618
ObjectID objectId,
1719
slang::SessionDesc const& desc,

source/slang-record-replay/replay/decoder-helper.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ size_t BlobDecoder::decode(const uint8_t* buffer, int64_t bufferSize)
5454
return readByte;
5555
}
5656

57+
template class StructDecoder<SlangGlobalSessionDesc>;
5758
template class StructDecoder<slang::SessionDesc>;
5859
template class StructDecoder<slang::PreprocessorMacroDesc>;
5960
template class StructDecoder<slang::CompilerOptionEntry>;

source/slang-record-replay/replay/json-consumer.cpp

+22-1
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,24 @@ void JsonConsumer::_writeCompilerOptionEntryHelper(
618618
}
619619
}
620620

621+
void JsonConsumer::_writeGlobalSessionDescHelper(
622+
Slang::StringBuilder& builder,
623+
int indent,
624+
SlangGlobalSessionDesc const& desc,
625+
Slang::String keyName,
626+
bool isLastField)
627+
{
628+
SLANG_UNUSED(isLastField);
629+
630+
ScopeWritterForKey scopeWritterForGlobalSessionDesc(&builder, &indent, keyName);
631+
{
632+
_writePair(builder, indent, "structureSize", (uint32_t)desc.structureSize);
633+
_writePair(builder, indent, "apiVersion", (uint32_t)desc.apiVersion);
634+
_writePair(builder, indent, "languageVersion", (uint32_t)desc.languageVersion);
635+
_writePair(builder, indent, "enablGLSL", (uint32_t)desc.enableGLSL);
636+
}
637+
}
638+
621639
void JsonConsumer::_writeSessionDescHelper(
622640
Slang::StringBuilder& builder,
623641
int indent,
@@ -779,14 +797,17 @@ void JsonConsumer::_writeSessionDescHelper(
779797
}
780798
}
781799

782-
void JsonConsumer::CreateGlobalSession(ObjectID outGlobalSessionId)
800+
void JsonConsumer::CreateGlobalSession(
801+
SlangGlobalSessionDesc const& desc,
802+
ObjectID outGlobalSessionId)
783803
{
784804
SANITY_CHECK();
785805
Slang::StringBuilder builder;
786806
int indent = 0;
787807

788808
{
789809
ScopeWritterForKey scopeWritter(&builder, &indent, "IGlobalSession::createGlobalSession");
810+
_writeGlobalSessionDescHelper(builder, indent, desc, "inDesc");
790811
_writePairNoComma(
791812
builder,
792813
indent,

source/slang-record-replay/replay/json-consumer.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ class JsonConsumer : public IDecoderConsumer, public Slang::RefObject
9292
public:
9393
JsonConsumer(const Slang::String& filePath);
9494
virtual ~JsonConsumer() = default;
95-
virtual void CreateGlobalSession(ObjectID outGlobalSessionId);
95+
virtual void CreateGlobalSession(
96+
SlangGlobalSessionDesc const& desc,
97+
ObjectID outGlobalSessionId);
9698
virtual void IGlobalSession_createSession(
9799
ObjectID objectId,
98100
slang::SessionDesc const& desc,
@@ -540,6 +542,12 @@ class JsonConsumer : public IDecoderConsumer, public Slang::RefObject
540542
slang::CompilerOptionEntry* compilerOptionEntries,
541543
uint32_t compilerOptionEntryCount,
542544
bool isLast = false);
545+
static void _writeGlobalSessionDescHelper(
546+
Slang::StringBuilder& builder,
547+
int indent,
548+
SlangGlobalSessionDesc const& globalSessionDesc,
549+
Slang::String keyName,
550+
bool isLast = false);
543551
static void _writeSessionDescHelper(
544552
Slang::StringBuilder& builder,
545553
int indent,

0 commit comments

Comments
 (0)