yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Yong HeCache and reuse glsl module. (#6152)8000e0ede

master
21.0 KiB609 linesraw
1#include "slang-global-session.h"
2
3#include "../../slang/slang-compiler.h"
4#include "../util/record-utility.h"
5#include "slang-filesystem.h"
6#include "slang-session.h"
7
8namespace SlangRecord
9{
10// constructor is called in slang_createGlobalSession
11GlobalSessionRecorder::GlobalSessionRecorder(
12    const SlangGlobalSessionDesc* desc,
13    slang::IGlobalSession* session)
14    : m_actualGlobalSession(session)
15{
16    SLANG_RECORD_ASSERT(m_actualGlobalSession != nullptr);
17
18    m_globalSessionHandle =
19        reinterpret_cast<SlangRecord::AddressFormat>(m_actualGlobalSession.get());
20    m_recordManager = new RecordManager(m_globalSessionHandle);
21
22    // We will use the address of the global session as the filename for the record manager
23    // to make it unique for each global session.
24    // record slang::createGlobalSession
25
26    ParameterRecorder* recorder{};
27    {
28        recorder = m_recordManager->beginMethodRecord(
29            ApiCallId::CreateGlobalSession,
30            g_globalFunctionHandle);
31        recorder->recordStruct(*desc);
32        recorder = m_recordManager->endMethodRecord();
33    }
34
35    recorder->recordAddress(m_actualGlobalSession);
36    m_recordManager->apendOutput();
37}
38
39SLANG_NO_THROW SlangResult SLANG_MCALL
40GlobalSessionRecorder::queryInterface(SlangUUID const& uuid, void** outObject)
41{
42    if (uuid == Session::getTypeGuid())
43    {
44        // no add-ref here, the query will cause the inner session to handle the add-ref.
45        this->m_actualGlobalSession->queryInterface(uuid, outObject);
46        return SLANG_OK;
47    }
48
49    if (uuid == ISlangUnknown::getTypeGuid() && uuid == IGlobalSession::getTypeGuid())
50    {
51        addReference();
52        *outObject = static_cast<slang::IGlobalSession*>(this);
53        return SLANG_OK;
54    }
55
56    return SLANG_E_NO_INTERFACE;
57}
58
59SLANG_NO_THROW SlangResult SLANG_MCALL
60GlobalSessionRecorder::createSession(slang::SessionDesc const& desc, slang::ISession** outSession)
61{
62    setLogLevel();
63    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
64
65    slang::ISession* actualSession = nullptr;
66
67    ParameterRecorder* recorder{};
68    {
69        recorder = m_recordManager->beginMethodRecord(
70            ApiCallId::IGlobalSession_createSession,
71            m_globalSessionHandle);
72        recorder->recordStruct(desc);
73        recorder = m_recordManager->endMethodRecord();
74    }
75
76    SlangResult res = m_actualGlobalSession->createSession(desc, &actualSession);
77
78    { // record output
79        recorder->recordAddress(actualSession);
80        m_recordManager->apendOutput();
81    }
82
83    if (actualSession != nullptr)
84    {
85        // reset the file system to our record file system. After createSession() call,
86        // the Linkage will set to user provided file system or slang default file system.
87        // We need to reset it to our record file system
88        Slang::Linkage* linkage = static_cast<Linkage*>(actualSession);
89        FileSystemRecorder* fileSystemRecord =
90            new FileSystemRecorder(linkage->getFileSystemExt(), m_recordManager.get());
91
92        Slang::ComPtr<FileSystemRecorder> resultFileSystemRecorder(fileSystemRecord);
93        linkage->setFileSystem(resultFileSystemRecorder.detach());
94
95        SessionRecorder* sessionRecord = new SessionRecorder(actualSession, m_recordManager.get());
96        Slang::ComPtr<SessionRecorder> result(sessionRecord);
97        *outSession = result.detach();
98    }
99
100    return res;
101}
102
103SLANG_NO_THROW SlangProfileID SLANG_MCALL GlobalSessionRecorder::findProfile(char const* name)
104{
105    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
106
107    ParameterRecorder* recorder{};
108    {
109        recorder = m_recordManager->beginMethodRecord(
110            ApiCallId::IGlobalSession_findProfile,
111            m_globalSessionHandle);
112        recorder->recordString(name);
113        recorder = m_recordManager->endMethodRecord();
114    }
115
116    SlangProfileID profileId = m_actualGlobalSession->findProfile(name);
117    return profileId;
118}
119
120SLANG_NO_THROW void SLANG_MCALL
121GlobalSessionRecorder::setDownstreamCompilerPath(SlangPassThrough passThrough, char const* path)
122{
123    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
124
125    ParameterRecorder* recorder{};
126    {
127        recorder = m_recordManager->beginMethodRecord(
128            ApiCallId::IGlobalSession_setDownstreamCompilerPath,
129            m_globalSessionHandle);
130        recorder->recordEnumValue(passThrough);
131        recorder->recordString(path);
132        m_recordManager->endMethodRecord();
133    }
134
135    m_actualGlobalSession->setDownstreamCompilerPath(passThrough, path);
136}
137
138SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::setDownstreamCompilerPrelude(
139    SlangPassThrough inPassThrough,
140    char const* prelude)
141{
142    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
143
144    ParameterRecorder* recorder{};
145    {
146        recorder = m_recordManager->beginMethodRecord(
147            ApiCallId::IGlobalSession_setDownstreamCompilerPrelude,
148            m_globalSessionHandle);
149        recorder->recordEnumValue(inPassThrough);
150        recorder->recordString(prelude);
151        m_recordManager->endMethodRecord();
152    }
153
154    m_actualGlobalSession->setDownstreamCompilerPrelude(inPassThrough, prelude);
155}
156
157SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::getDownstreamCompilerPrelude(
158    SlangPassThrough inPassThrough,
159    ISlangBlob** outPrelude)
160{
161    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
162
163    ParameterRecorder* recorder{};
164    {
165        recorder = m_recordManager->beginMethodRecord(
166            ApiCallId::IGlobalSession_getDownstreamCompilerPrelude,
167            m_globalSessionHandle);
168        recorder->recordEnumValue(inPassThrough);
169        recorder = m_recordManager->endMethodRecord();
170    }
171
172    m_actualGlobalSession->getDownstreamCompilerPrelude(inPassThrough, outPrelude);
173
174    {
175        recorder->recordAddress(*outPrelude);
176        m_recordManager->apendOutput();
177    }
178}
179
180SLANG_NO_THROW const char* SLANG_MCALL GlobalSessionRecorder::getBuildTagString()
181{
182    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
183
184    // No need to record this function. It's just a query function and it won't impact the internal
185    // state.
186    const char* resStr = m_actualGlobalSession->getBuildTagString();
187    return resStr;
188}
189
190SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::setDefaultDownstreamCompiler(
191    SlangSourceLanguage sourceLanguage,
192    SlangPassThrough defaultCompiler)
193{
194    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
195
196    ParameterRecorder* recorder{};
197    {
198        recorder = m_recordManager->beginMethodRecord(
199            ApiCallId::IGlobalSession_setDefaultDownstreamCompiler,
200            m_globalSessionHandle);
201        recorder->recordEnumValue(sourceLanguage);
202        recorder->recordEnumValue(defaultCompiler);
203        recorder = m_recordManager->endMethodRecord();
204    }
205
206    SlangResult res =
207        m_actualGlobalSession->setDefaultDownstreamCompiler(sourceLanguage, defaultCompiler);
208    return res;
209}
210
211SLANG_NO_THROW SlangPassThrough SLANG_MCALL
212GlobalSessionRecorder::getDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage)
213{
214    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
215
216    ParameterRecorder* recorder{};
217    {
218        recorder = m_recordManager->beginMethodRecord(
219            ApiCallId::IGlobalSession_getDefaultDownstreamCompiler,
220            m_globalSessionHandle);
221        recorder->recordEnumValue(sourceLanguage);
222        recorder = m_recordManager->endMethodRecord();
223    }
224
225    SlangPassThrough passThrough =
226        m_actualGlobalSession->getDefaultDownstreamCompiler(sourceLanguage);
227    return passThrough;
228}
229
230SLANG_NO_THROW void SLANG_MCALL
231GlobalSessionRecorder::setLanguagePrelude(SlangSourceLanguage inSourceLanguage, char const* prelude)
232{
233    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
234
235    ParameterRecorder* recorder{};
236    {
237        recorder = m_recordManager->beginMethodRecord(
238            ApiCallId::IGlobalSession_setLanguagePrelude,
239            m_globalSessionHandle);
240        recorder->recordEnumValue(inSourceLanguage);
241        recorder->recordString(prelude);
242        recorder = m_recordManager->endMethodRecord();
243    }
244
245    m_actualGlobalSession->setLanguagePrelude(inSourceLanguage, prelude);
246}
247
248SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::getLanguagePrelude(
249    SlangSourceLanguage inSourceLanguage,
250    ISlangBlob** outPrelude)
251{
252    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
253
254    ParameterRecorder* recorder{};
255    {
256        recorder = m_recordManager->beginMethodRecord(
257            ApiCallId::IGlobalSession_getLanguagePrelude,
258            m_globalSessionHandle);
259        recorder->recordEnumValue(inSourceLanguage);
260        recorder = m_recordManager->endMethodRecord();
261    }
262
263    m_actualGlobalSession->getLanguagePrelude(inSourceLanguage, outPrelude);
264
265    {
266        recorder->recordAddress(*outPrelude);
267        m_recordManager->apendOutput();
268    }
269}
270
271SLANG_NO_THROW SlangResult SLANG_MCALL
272GlobalSessionRecorder::createCompileRequest(slang::ICompileRequest** outCompileRequest)
273{
274    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
275
276    ParameterRecorder* recorder{};
277    {
278        recorder = m_recordManager->beginMethodRecord(
279            ApiCallId::IGlobalSession_createCompileRequest,
280            m_globalSessionHandle);
281        recorder = m_recordManager->endMethodRecord();
282    }
283
284    SLANG_ALLOW_DEPRECATED_BEGIN
285    SlangResult res = m_actualGlobalSession->createCompileRequest(outCompileRequest);
286    SLANG_ALLOW_DEPRECATED_END
287
288    {
289        recorder->recordAddress(*outCompileRequest);
290        m_recordManager->apendOutput();
291    }
292
293    return res;
294}
295
296SLANG_NO_THROW void SLANG_MCALL
297GlobalSessionRecorder::addBuiltins(char const* sourcePath, char const* sourceString)
298{
299    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
300    ParameterRecorder* recorder{};
301    {
302        recorder = m_recordManager->beginMethodRecord(
303            ApiCallId::IGlobalSession_addBuiltins,
304            m_globalSessionHandle);
305        recorder->recordString(sourcePath);
306        recorder->recordString(sourceString);
307        recorder = m_recordManager->endMethodRecord();
308    }
309
310    m_actualGlobalSession->addBuiltins(sourcePath, sourceString);
311}
312
313SLANG_NO_THROW void SLANG_MCALL
314GlobalSessionRecorder::setSharedLibraryLoader(ISlangSharedLibraryLoader* loader)
315{
316    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
317    // TODO: Not sure if we need to record this function. Because this functions is something like
318    // the file system override, it's provided by user code. So capturing it makes no sense. The
319    // only way is to wrapper this interface by our own implementation, and record it there.
320    m_actualGlobalSession->setSharedLibraryLoader(loader);
321}
322
323SLANG_NO_THROW ISlangSharedLibraryLoader* SLANG_MCALL
324GlobalSessionRecorder::getSharedLibraryLoader()
325{
326    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
327
328    ParameterRecorder* recorder{};
329    {
330        recorder = m_recordManager->beginMethodRecord(
331            ApiCallId::IGlobalSession_getSharedLibraryLoader,
332            m_globalSessionHandle);
333        recorder = m_recordManager->endMethodRecord();
334    }
335
336    ISlangSharedLibraryLoader* loader = m_actualGlobalSession->getSharedLibraryLoader();
337
338    {
339        recorder->recordAddress(loader);
340        m_recordManager->apendOutput();
341    }
342    return loader;
343}
344
345SLANG_NO_THROW SlangResult SLANG_MCALL
346GlobalSessionRecorder::checkCompileTargetSupport(SlangCompileTarget target)
347{
348    // No need to record this function. It's just a query function and it won't impact the internal
349    // state.
350    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
351    SlangResult res = m_actualGlobalSession->checkCompileTargetSupport(target);
352    return res;
353}
354
355SLANG_NO_THROW SlangResult SLANG_MCALL
356GlobalSessionRecorder::checkPassThroughSupport(SlangPassThrough passThrough)
357{
358    // No need to record this function. It's just a query function and it won't impact the internal
359    // state.
360    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
361    SlangResult res = m_actualGlobalSession->checkPassThroughSupport(passThrough);
362    return res;
363}
364
365SLANG_NO_THROW SlangResult SLANG_MCALL
366GlobalSessionRecorder::compileCoreModule(slang::CompileCoreModuleFlags flags)
367{
368    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
369
370    ParameterRecorder* recorder{};
371    {
372        recorder = m_recordManager->beginMethodRecord(
373            ApiCallId::IGlobalSession_compileCoreModule,
374            m_globalSessionHandle);
375        recorder->recordEnumValue(flags);
376        m_recordManager->endMethodRecord();
377    }
378
379    SlangResult res = m_actualGlobalSession->compileCoreModule(flags);
380    return res;
381}
382
383SLANG_NO_THROW SlangResult SLANG_MCALL
384GlobalSessionRecorder::loadCoreModule(const void* coreModule, size_t coreModuleSizeInBytes)
385{
386    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
387
388    ParameterRecorder* recorder{};
389    {
390        recorder = m_recordManager->beginMethodRecord(
391            ApiCallId::IGlobalSession_loadCoreModule,
392            m_globalSessionHandle);
393        recorder->recordPointer(coreModule, false, coreModuleSizeInBytes);
394        m_recordManager->endMethodRecord();
395    }
396
397    SlangResult res = m_actualGlobalSession->loadCoreModule(coreModule, coreModuleSizeInBytes);
398    return res;
399}
400
401SLANG_NO_THROW SlangResult SLANG_MCALL
402GlobalSessionRecorder::saveCoreModule(SlangArchiveType archiveType, ISlangBlob** outBlob)
403{
404    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
405
406    ParameterRecorder* recorder{};
407    {
408        recorder = m_recordManager->beginMethodRecord(
409            ApiCallId::IGlobalSession_saveCoreModule,
410            m_globalSessionHandle);
411        recorder->recordEnumValue(archiveType);
412        recorder = m_recordManager->endMethodRecord();
413    }
414
415    SlangResult res = m_actualGlobalSession->saveCoreModule(archiveType, outBlob);
416
417    {
418        recorder->recordAddress(*outBlob);
419        m_recordManager->apendOutput();
420    }
421    return res;
422}
423
424SLANG_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
444SLANG_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}
464SLANG_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
488SLANG_NO_THROW SlangCapabilityID SLANG_MCALL GlobalSessionRecorder::findCapability(char const* name)
489{
490    // No need to record this function. It's just a query function and it won't impact the internal
491    // state.
492    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
493    SlangCapabilityID capId = m_actualGlobalSession->findCapability(name);
494    return capId;
495}
496
497SLANG_NO_THROW void SLANG_MCALL GlobalSessionRecorder::setDownstreamCompilerForTransition(
498    SlangCompileTarget source,
499    SlangCompileTarget target,
500    SlangPassThrough compiler)
501{
502    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
503
504    ParameterRecorder* recorder{};
505    {
506        recorder = m_recordManager->beginMethodRecord(
507            ApiCallId::IGlobalSession_setDownstreamCompilerForTransition,
508            m_globalSessionHandle);
509        recorder->recordEnumValue(source);
510        recorder->recordEnumValue(target);
511        recorder->recordEnumValue(compiler);
512        m_recordManager->endMethodRecord();
513    }
514
515    m_actualGlobalSession->setDownstreamCompilerForTransition(source, target, compiler);
516}
517
518SLANG_NO_THROW SlangPassThrough SLANG_MCALL
519GlobalSessionRecorder::getDownstreamCompilerForTransition(
520    SlangCompileTarget source,
521    SlangCompileTarget target)
522{
523    // No need to record this function. It's just a query function and it won't impact the internal
524    // state.
525    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
526    SlangPassThrough passThrough =
527        m_actualGlobalSession->getDownstreamCompilerForTransition(source, target);
528    return passThrough;
529}
530
531SLANG_NO_THROW void SLANG_MCALL
532GlobalSessionRecorder::getCompilerElapsedTime(double* outTotalTime, double* outDownstreamTime)
533{
534    // No need to record this function. It's just a query function and it won't impact the internal
535    // state.
536    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
537    m_actualGlobalSession->getCompilerElapsedTime(outTotalTime, outDownstreamTime);
538}
539
540SLANG_NO_THROW SlangResult SLANG_MCALL
541GlobalSessionRecorder::setSPIRVCoreGrammar(char const* jsonPath)
542{
543    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
544
545    ParameterRecorder* recorder{};
546    {
547        recorder = m_recordManager->beginMethodRecord(
548            ApiCallId::IGlobalSession_setSPIRVCoreGrammar,
549            m_globalSessionHandle);
550        recorder->recordString(jsonPath);
551        m_recordManager->endMethodRecord();
552    }
553
554    SlangResult res = m_actualGlobalSession->setSPIRVCoreGrammar(jsonPath);
555    return res;
556}
557
558SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::parseCommandLineArguments(
559    int argc,
560    const char* const* argv,
561    slang::SessionDesc* outSessionDesc,
562    ISlangUnknown** outAllocation)
563{
564    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
565
566    ParameterRecorder* recorder{};
567    {
568        recorder = m_recordManager->beginMethodRecord(
569            ApiCallId::IGlobalSession_parseCommandLineArguments,
570            m_globalSessionHandle);
571        recorder->recordInt32(argc);
572        recorder->recordStringArray(argv, argc);
573        recorder = m_recordManager->endMethodRecord();
574    }
575
576    SlangResult res =
577        m_actualGlobalSession->parseCommandLineArguments(argc, argv, outSessionDesc, outAllocation);
578
579    {
580        recorder->recordAddress(outSessionDesc);
581        recorder->recordAddress(*outAllocation);
582        m_recordManager->apendOutput();
583    }
584    return res;
585}
586
587SLANG_NO_THROW SlangResult SLANG_MCALL
588GlobalSessionRecorder::getSessionDescDigest(slang::SessionDesc* sessionDesc, ISlangBlob** outBlob)
589{
590    slangRecordLog(LogLevel::Verbose, "%p: %s\n", m_actualGlobalSession.get(), __PRETTY_FUNCTION__);
591
592    ParameterRecorder* recorder{};
593    {
594        recorder = m_recordManager->beginMethodRecord(
595            ApiCallId::IGlobalSession_getSessionDescDigest,
596            m_globalSessionHandle);
597        recorder->recordStruct(*sessionDesc);
598        recorder = m_recordManager->endMethodRecord();
599    }
600
601    SlangResult res = m_actualGlobalSession->getSessionDescDigest(sessionDesc, outBlob);
602
603    {
604        recorder->recordAddress(*outBlob);
605        m_recordManager->apendOutput();
606    }
607    return res;
608}
609} // namespace SlangRecord