yum-mirror/slang

Making it easier to work with shaders

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

Ellie HermaszewskaStable names and backwards compat for serialized IR modules (#7644)00746bf09

master
20.2 KiB637 linesraw
1#include "slang-session.h"
2
3#include "../util/record-utility.h"
4#include "slang-component-type.h"
5#include "slang-composite-component-type.h"
6#include "slang-entrypoint.h"
7#include "slang-type-conformance.h"
8
9namespace SlangRecord
10{
11
12SessionRecorder::SessionRecorder(slang::ISession* session, RecordManager* recordManager)
13    : m_actualSession(session), m_recordManager(recordManager)
14{
15    SLANG_RECORD_ASSERT(m_actualSession);
16    SLANG_RECORD_ASSERT(m_recordManager);
17    m_sessionHandle = reinterpret_cast<uint64_t>(m_actualSession.get());
18    slangRecordLog(LogLevel::Verbose, "%s: %p\n", "SessionRecorder create:", session);
19}
20
21ISlangUnknown* SessionRecorder::getInterface(const Guid& guid)
22{
23    if (guid == ISlangUnknown::getTypeGuid() || guid == ISession::getTypeGuid())
24        return asExternal(this);
25
26    return nullptr;
27}
28
29SLANG_NO_THROW slang::IGlobalSession* SessionRecorder::getGlobalSession()
30{
31    // No need to record this function.
32    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
33    slang::IGlobalSession* pGlobalSession = m_actualSession->getGlobalSession();
34    return pGlobalSession;
35}
36
37SLANG_NO_THROW slang::IModule* SessionRecorder::loadModule(
38    const char* moduleName,
39    slang::IBlob** outDiagnostics)
40{
41    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
42
43    ParameterRecorder* recorder{};
44    {
45        recorder =
46            m_recordManager->beginMethodRecord(ApiCallId::ISession_loadModule, m_sessionHandle);
47        recorder->recordString(moduleName);
48        recorder = m_recordManager->endMethodRecord();
49    }
50
51    slang::IModule* pModule = m_actualSession->loadModule(moduleName, outDiagnostics);
52
53    {
54        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
55        recorder->recordAddress(pModule);
56        m_recordManager->apendOutput();
57    }
58
59    IModuleRecorder* pModuleRecorder = getModuleRecorder(pModule);
60    return static_cast<slang::IModule*>(pModuleRecorder);
61}
62
63SLANG_NO_THROW slang::IModule* SessionRecorder::loadModuleFromIRBlob(
64    const char* moduleName,
65    const char* path,
66    slang::IBlob* source,
67    slang::IBlob** outDiagnostics)
68{
69    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
70
71    ParameterRecorder* recorder{};
72    {
73        recorder = m_recordManager->beginMethodRecord(
74            ApiCallId::ISession_loadModuleFromIRBlob,
75            m_sessionHandle);
76        recorder->recordString(moduleName);
77        recorder->recordString(path);
78        recorder->recordPointer(source);
79        recorder = m_recordManager->endMethodRecord();
80    }
81
82    slang::IModule* pModule =
83        m_actualSession->loadModuleFromIRBlob(moduleName, path, source, outDiagnostics);
84
85    {
86        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
87        recorder->recordAddress(pModule);
88        m_recordManager->apendOutput();
89    }
90
91    IModuleRecorder* pModuleRecorder = getModuleRecorder(pModule);
92    return static_cast<slang::IModule*>(pModuleRecorder);
93}
94
95SLANG_NO_THROW SlangResult SLANG_MCALL SessionRecorder::loadModuleInfoFromIRBlob(
96    slang::IBlob* source,
97    SlangInt& outModuleVersion,
98    const char*& outModuleCompilerVersion,
99    const char*& outModuleName)
100{
101    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
102
103    ParameterRecorder* recorder{};
104    {
105        recorder = m_recordManager->beginMethodRecord(
106            ApiCallId::ISession_loadModuleFromIRBlob,
107            m_sessionHandle);
108        recorder->recordPointer(source);
109        recorder = m_recordManager->endMethodRecord();
110    }
111
112    const auto result = m_actualSession->loadModuleInfoFromIRBlob(
113        source,
114        outModuleVersion,
115        outModuleCompilerVersion,
116        outModuleName);
117
118    {
119        recorder->recordInt64(outModuleVersion);
120        recorder->recordString(outModuleCompilerVersion);
121        recorder->recordString(outModuleName);
122        m_recordManager->apendOutput();
123    }
124
125    return result;
126}
127
128SLANG_NO_THROW slang::IModule* SessionRecorder::loadModuleFromSource(
129    const char* moduleName,
130    const char* path,
131    slang::IBlob* source,
132    slang::IBlob** outDiagnostics)
133{
134    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
135
136    ParameterRecorder* recorder{};
137    {
138        recorder = m_recordManager->beginMethodRecord(
139            ApiCallId::ISession_loadModuleFromSource,
140            m_sessionHandle);
141        recorder->recordString(moduleName);
142        recorder->recordString(path);
143        recorder->recordPointer(source);
144        recorder = m_recordManager->endMethodRecord();
145    }
146
147    slang::IModule* pModule =
148        m_actualSession->loadModuleFromSource(moduleName, path, source, outDiagnostics);
149
150    {
151        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
152        recorder->recordAddress(pModule);
153        m_recordManager->apendOutput();
154    }
155
156    IModuleRecorder* pModuleRecorder = getModuleRecorder(pModule);
157    return static_cast<slang::IModule*>(pModuleRecorder);
158}
159
160SLANG_NO_THROW slang::IModule* SessionRecorder::loadModuleFromSourceString(
161    const char* moduleName,
162    const char* path,
163    const char* string,
164    slang::IBlob** outDiagnostics)
165{
166    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
167
168    ParameterRecorder* recorder{};
169    {
170        recorder = m_recordManager->beginMethodRecord(
171            ApiCallId::ISession_loadModuleFromSourceString,
172            m_sessionHandle);
173        recorder->recordString(moduleName);
174        recorder->recordString(path);
175        recorder->recordString(string);
176        recorder = m_recordManager->endMethodRecord();
177    }
178
179    slang::IModule* pModule =
180        m_actualSession->loadModuleFromSourceString(moduleName, path, string, outDiagnostics);
181
182    {
183        // TODO: Not sure if we need to record the diagnostics blob.
184        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
185        recorder->recordAddress(pModule);
186        m_recordManager->apendOutput();
187    }
188
189    IModuleRecorder* pModuleRecorder = getModuleRecorder(pModule);
190    return static_cast<slang::IModule*>(pModuleRecorder);
191}
192
193SLANG_NO_THROW SlangResult SessionRecorder::createCompositeComponentType(
194    slang::IComponentType* const* componentTypes,
195    SlangInt componentTypeCount,
196    slang::IComponentType** outCompositeComponentType,
197    ISlangBlob** outDiagnostics)
198{
199    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
200
201    Slang::List<slang::IComponentType*> componentTypeList;
202
203    // get the actual component types from our record wrappers
204    if (SLANG_OK != getActualComponentTypes(componentTypes, componentTypeCount, componentTypeList))
205    {
206        SLANG_RECORD_ASSERT(!"Failed to get actual component types");
207    }
208
209    ParameterRecorder* recorder{};
210    {
211        recorder = m_recordManager->beginMethodRecord(
212            ApiCallId::ISession_createCompositeComponentType,
213            m_sessionHandle);
214        recorder->recordAddressArray(componentTypeList.getBuffer(), componentTypeCount);
215        recorder = m_recordManager->endMethodRecord();
216    }
217
218    SlangResult result = m_actualSession->createCompositeComponentType(
219        componentTypeList.getBuffer(),
220        componentTypeCount,
221        outCompositeComponentType,
222        outDiagnostics);
223
224    {
225        recorder->recordAddress(*outCompositeComponentType);
226        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
227        m_recordManager->apendOutput();
228    }
229
230    if (SLANG_OK == result)
231    {
232        CompositeComponentTypeRecorder* compositeComponentTypeRecord =
233            new CompositeComponentTypeRecorder(this, *outCompositeComponentType, m_recordManager);
234        Slang::ComPtr<CompositeComponentTypeRecorder> resultRecord(compositeComponentTypeRecord);
235        *outCompositeComponentType = resultRecord.detach();
236    }
237
238    return result;
239}
240
241SLANG_NO_THROW slang::TypeReflection* SessionRecorder::specializeType(
242    slang::TypeReflection* type,
243    slang::SpecializationArg const* specializationArgs,
244    SlangInt specializationArgCount,
245    ISlangBlob** outDiagnostics)
246{
247    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
248
249    ParameterRecorder* recorder{};
250    {
251        recorder =
252            m_recordManager->beginMethodRecord(ApiCallId::ISession_specializeType, m_sessionHandle);
253        recorder->recordAddress(type);
254        recorder->recordStructArray(specializationArgs, specializationArgCount);
255        recorder = m_recordManager->endMethodRecord();
256    }
257
258    slang::TypeReflection* pTypeReflection = m_actualSession->specializeType(
259        type,
260        specializationArgs,
261        specializationArgCount,
262        outDiagnostics);
263
264    {
265        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
266        recorder->recordAddress(pTypeReflection);
267        m_recordManager->apendOutput();
268    }
269
270    return pTypeReflection;
271}
272
273SLANG_NO_THROW slang::TypeLayoutReflection* SessionRecorder::getTypeLayout(
274    slang::TypeReflection* type,
275    SlangInt targetIndex,
276    slang::LayoutRules rules,
277    ISlangBlob** outDiagnostics)
278{
279    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
280
281    ParameterRecorder* recorder{};
282    {
283        recorder =
284            m_recordManager->beginMethodRecord(ApiCallId::ISession_getTypeLayout, m_sessionHandle);
285        recorder->recordAddress(type);
286        recorder->recordInt64(targetIndex);
287        recorder->recordEnumValue(rules);
288        recorder = m_recordManager->endMethodRecord();
289    }
290
291    slang::TypeLayoutReflection* pTypeLayoutReflection =
292        m_actualSession->getTypeLayout(type, targetIndex, rules, outDiagnostics);
293
294    {
295        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
296        recorder->recordAddress(pTypeLayoutReflection);
297        m_recordManager->apendOutput();
298    }
299
300    return pTypeLayoutReflection;
301}
302
303SLANG_NO_THROW slang::TypeReflection* SessionRecorder::getContainerType(
304    slang::TypeReflection* elementType,
305    slang::ContainerType containerType,
306    ISlangBlob** outDiagnostics)
307{
308    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
309
310    ParameterRecorder* recorder{};
311    {
312        recorder = m_recordManager->beginMethodRecord(
313            ApiCallId::ISession_getContainerType,
314            m_sessionHandle);
315        recorder->recordAddress(elementType);
316        recorder->recordEnumValue(containerType);
317        recorder = m_recordManager->endMethodRecord();
318    }
319
320    slang::TypeReflection* pTypeReflection =
321        m_actualSession->getContainerType(elementType, containerType, outDiagnostics);
322
323    {
324        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
325        recorder->recordAddress(pTypeReflection);
326        m_recordManager->apendOutput();
327    }
328
329    return pTypeReflection;
330}
331
332SLANG_NO_THROW slang::TypeReflection* SessionRecorder::getDynamicType()
333{
334    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
335
336    ParameterRecorder* recorder{};
337    {
338        recorder =
339            m_recordManager->beginMethodRecord(ApiCallId::ISession_getDynamicType, m_sessionHandle);
340        recorder = m_recordManager->endMethodRecord();
341    }
342
343    slang::TypeReflection* pTypeReflection = m_actualSession->getDynamicType();
344
345    {
346        recorder->recordAddress(pTypeReflection);
347        m_recordManager->apendOutput();
348    }
349
350    return pTypeReflection;
351}
352
353SLANG_NO_THROW SlangResult
354SessionRecorder::getTypeRTTIMangledName(slang::TypeReflection* type, ISlangBlob** outNameBlob)
355{
356    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
357
358    ParameterRecorder* recorder{};
359    {
360        recorder = m_recordManager->beginMethodRecord(
361            ApiCallId::ISession_getTypeRTTIMangledName,
362            m_sessionHandle);
363        recorder->recordAddress(type);
364        recorder = m_recordManager->endMethodRecord();
365    }
366
367    SlangResult result = m_actualSession->getTypeRTTIMangledName(type, outNameBlob);
368
369    {
370        recorder->recordAddress(outNameBlob);
371        m_recordManager->apendOutput();
372    }
373
374    return result;
375}
376
377SLANG_NO_THROW SlangResult SessionRecorder::getTypeConformanceWitnessMangledName(
378    slang::TypeReflection* type,
379    slang::TypeReflection* interfaceType,
380    ISlangBlob** outNameBlob)
381{
382    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
383
384    ParameterRecorder* recorder{};
385    {
386        recorder = m_recordManager->beginMethodRecord(
387            ApiCallId::ISession_getTypeConformanceWitnessMangledName,
388            m_sessionHandle);
389        recorder->recordAddress(type);
390        recorder->recordAddress(interfaceType);
391        recorder = m_recordManager->endMethodRecord();
392    }
393
394    SlangResult result =
395        m_actualSession->getTypeConformanceWitnessMangledName(type, interfaceType, outNameBlob);
396
397    {
398        recorder->recordAddress(outNameBlob);
399        m_recordManager->apendOutput();
400    }
401
402    return result;
403}
404
405SLANG_NO_THROW SlangResult SessionRecorder::getDynamicObjectRTTIBytes(
406    slang::TypeReflection* type,
407    slang::TypeReflection* interfaceType,
408    uint32_t* outRTTIDataBuffer,
409    uint32_t bufferSizeInBytes)
410{
411    // No need to record this function, it's just a query.
412
413    SlangResult result = m_actualSession->getDynamicObjectRTTIBytes(
414        type,
415        interfaceType,
416        outRTTIDataBuffer,
417        bufferSizeInBytes);
418    return result;
419}
420
421SLANG_NO_THROW SlangResult SessionRecorder::getTypeConformanceWitnessSequentialID(
422    slang::TypeReflection* type,
423    slang::TypeReflection* interfaceType,
424    uint32_t* outId)
425{
426    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
427
428    ParameterRecorder* recorder{};
429    {
430        recorder = m_recordManager->beginMethodRecord(
431            ApiCallId::ISession_getTypeConformanceWitnessSequentialID,
432            m_sessionHandle);
433        recorder->recordAddress(type);
434        recorder->recordAddress(interfaceType);
435        recorder = m_recordManager->endMethodRecord();
436    }
437
438    SlangResult result =
439        m_actualSession->getTypeConformanceWitnessSequentialID(type, interfaceType, outId);
440
441    // No need to record outId, it's not slang allocation
442    return result;
443}
444
445SLANG_NO_THROW SlangResult SessionRecorder::createTypeConformanceComponentType(
446    slang::TypeReflection* type,
447    slang::TypeReflection* interfaceType,
448    slang::ITypeConformance** outConformance,
449    SlangInt conformanceIdOverride,
450    ISlangBlob** outDiagnostics)
451{
452    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
453
454    ParameterRecorder* recorder{};
455    {
456        recorder = m_recordManager->beginMethodRecord(
457            ApiCallId::ISession_createTypeConformanceComponentType,
458            m_sessionHandle);
459        recorder->recordAddress(type);
460        recorder->recordAddress(interfaceType);
461        recorder->recordInt64(conformanceIdOverride);
462        recorder = m_recordManager->endMethodRecord();
463    }
464
465    SlangResult result = m_actualSession->createTypeConformanceComponentType(
466        type,
467        interfaceType,
468        outConformance,
469        conformanceIdOverride,
470        outDiagnostics);
471
472    {
473        recorder->recordAddress(*outConformance);
474        recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr);
475        m_recordManager->apendOutput();
476    }
477
478    if (SLANG_OK != result)
479    {
480        ITypeConformanceRecorder* conformanceRecord =
481            new TypeConformanceRecorder(this, *outConformance, m_recordManager);
482        Slang::ComPtr<ITypeConformanceRecorder> resultRecord(conformanceRecord);
483        *outConformance = resultRecord.detach();
484    }
485
486    return result;
487}
488
489SLANG_NO_THROW SlangResult
490SessionRecorder::createCompileRequest(SlangCompileRequest** outCompileRequest)
491{
492    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
493
494    ParameterRecorder* recorder{};
495    {
496        recorder = m_recordManager->beginMethodRecord(
497            ApiCallId::ISession_createCompileRequest,
498            m_sessionHandle);
499        recorder = m_recordManager->endMethodRecord();
500    }
501
502    SlangResult result = m_actualSession->createCompileRequest(outCompileRequest);
503
504    {
505        recorder->recordAddress(*outCompileRequest);
506        m_recordManager->apendOutput();
507    }
508
509    return result;
510}
511
512SLANG_NO_THROW SlangInt SessionRecorder::getLoadedModuleCount()
513{
514    // No need to record this function, it's just a query.
515    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
516    SlangInt count = m_actualSession->getLoadedModuleCount();
517    return count;
518}
519
520SLANG_NO_THROW slang::IModule* SessionRecorder::getLoadedModule(SlangInt index)
521{
522    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
523
524    ParameterRecorder* recorder{};
525    {
526        recorder = m_recordManager->beginMethodRecord(
527            ApiCallId::ISession_getLoadedModule,
528            m_sessionHandle);
529        recorder->recordInt64(index);
530        recorder = m_recordManager->endMethodRecord();
531    }
532
533    slang::IModule* pModule = m_actualSession->getLoadedModule(index);
534
535    {
536        recorder->recordAddress(pModule);
537        m_recordManager->apendOutput();
538    }
539
540    if (pModule)
541    {
542        IModuleRecorder* moduleRecord = nullptr;
543        bool ret = m_mapModuleToRecord.tryGetValue(pModule, moduleRecord);
544        if (!ret)
545        {
546            SLANG_RECORD_ASSERT(!"Module not found in mapModuleToRecord");
547        }
548        ComPtr<slang::IModule> result(static_cast<slang::IModule*>(moduleRecord));
549        return result.detach();
550    }
551
552    return pModule;
553}
554
555SLANG_NO_THROW bool SessionRecorder::isBinaryModuleUpToDate(
556    const char* modulePath,
557    slang::IBlob* binaryModuleBlob)
558{
559    // No need to record this function, it's a query function and doesn't impact slang internal
560    // state.
561    slangRecordLog(LogLevel::Verbose, "%s\n", __PRETTY_FUNCTION__);
562    bool result = m_actualSession->isBinaryModuleUpToDate(modulePath, binaryModuleBlob);
563    return result;
564}
565
566IModuleRecorder* SessionRecorder::getModuleRecorder(slang::IModule* module)
567{
568    IModuleRecorder* moduleRecord = nullptr;
569    bool ret = m_mapModuleToRecord.tryGetValue(module, moduleRecord);
570    if (!ret)
571    {
572        moduleRecord = new ModuleRecorder(this, module, m_recordManager);
573        Slang::ComPtr<IModuleRecorder> result(moduleRecord);
574        m_moduleRecordersAlloation.add(result);
575        m_mapModuleToRecord.add(module, result.detach());
576    }
577    else
578    {
579        ComPtr<IModuleRecorder> result(moduleRecord);
580        return result.detach();
581    }
582
583    return moduleRecord;
584}
585
586SlangResult SessionRecorder::getActualComponentTypes(
587    slang::IComponentType* const* componentTypes,
588    SlangInt componentTypeCount,
589    List<slang::IComponentType*>& outActualComponentTypes)
590{
591    for (SlangInt i = 0; i < componentTypeCount; i++)
592    {
593        slang::IComponentType* const& componentType = componentTypes[i];
594        void* outObj = nullptr;
595
596        if (componentType->queryInterface(IModuleRecorder::getTypeGuid(), &outObj) == SLANG_OK)
597        {
598            ModuleRecorder* moduleRecord = static_cast<ModuleRecorder*>(outObj);
599            outActualComponentTypes.add(moduleRecord->getActualModule());
600        }
601        else if (
602            componentType->queryInterface(IEntryPointRecorder::getTypeGuid(), &outObj) == SLANG_OK)
603        {
604            EntryPointRecorder* entrypointRecord = static_cast<EntryPointRecorder*>(outObj);
605            outActualComponentTypes.add(entrypointRecord->getActualEntryPoint());
606        }
607        else if (
608            componentType->queryInterface(CompositeComponentTypeRecorder::getTypeGuid(), &outObj) ==
609            SLANG_OK)
610        {
611            CompositeComponentTypeRecorder* compositeComponentTypeRecord =
612                static_cast<CompositeComponentTypeRecorder*>(outObj);
613            outActualComponentTypes.add(
614                compositeComponentTypeRecord->getActualCompositeComponentType());
615        }
616        else if (
617            componentType->queryInterface(ITypeConformanceRecorder::getTypeGuid(), &outObj) ==
618            SLANG_OK)
619        {
620            TypeConformanceRecorder* typeConformanceRecorder =
621                static_cast<TypeConformanceRecorder*>(outObj);
622            outActualComponentTypes.add(typeConformanceRecorder->getActualTypeConformance());
623        }
624        // will fall back to the actual component type, it means that we didn't record this type.
625        else
626        {
627            outActualComponentTypes.add(componentType);
628        }
629    }
630
631    if (componentTypeCount == outActualComponentTypes.getCount())
632    {
633        return SLANG_OK;
634    }
635    return SLANG_FAIL;
636}
637} // namespace SlangRecord