yum-mirror/slang

Making it easier to work with shaders

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

Jay KwakDisable Link-Time-Optimization by default (#7345)7f04adbfb

master
14.3 KiB361 linesraw
1#ifndef SLANG_FILE_SYSTEM_H_INCLUDED
2#define SLANG_FILE_SYSTEM_H_INCLUDED
3
4#include "../core/slang-blob.h"
5#include "../core/slang-dictionary.h"
6#include "../core/slang-string-util.h"
7#include "slang-com-helper.h"
8#include "slang-com-ptr.h"
9#include "slang.h"
10
11namespace Slang
12{
13
14enum class FileSystemStyle
15{
16    Load,    ///< Equivalent to ISlangFileSystem
17    Ext,     ///< Equivalent to ISlangFileSystemExt
18    Mutable, ///< Equivalent to ISlangModifyableFileSystem
19};
20
21// Can be used for all styles of file system
22class OSFileSystem : public ISlangMutableFileSystem
23{
24public:
25    // ISlangUnknown
26    // override ref counting, as DefaultFileSystem is singleton
27    SLANG_IUNKNOWN_QUERY_INTERFACE
28    SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; }
29    SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; }
30
31    // ISlangCastable
32    virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
33
34    // ISlangFileSystem
35    virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(char const* path, ISlangBlob** outBlob)
36        SLANG_OVERRIDE;
37
38    // ISlangFileSystemExt
39    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
40    getFileUniqueIdentity(const char* path, ISlangBlob** uniqueIdentityOut) SLANG_OVERRIDE;
41    virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
42        SlangPathType fromPathType,
43        const char* fromPath,
44        const char* path,
45        ISlangBlob** pathOut) SLANG_OVERRIDE;
46    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
47    getPathType(const char* path, SlangPathType* pathTypeOut) SLANG_OVERRIDE;
48    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
49    getPath(PathKind pathKind, const char* path, ISlangBlob** outPath) SLANG_OVERRIDE;
50    virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE {}
51    virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(
52        const char* path,
53        FileSystemContentsCallBack callback,
54        void* userData) SLANG_OVERRIDE;
55    virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE
56    {
57        return OSPathKind::Direct;
58    }
59
60    // ISlangModifyableFileSystem
61    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
62    saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
63    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
64    saveFileBlob(const char* path, ISlangBlob* dataBlob) SLANG_OVERRIDE;
65    virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove(const char* path) SLANG_OVERRIDE;
66    virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(const char* path) SLANG_OVERRIDE;
67
68    /// Get a default instance
69    static ISlangFileSystem* getLoadSingleton() { return &g_load; }
70    static ISlangFileSystemExt* getExtSingleton() { return &g_ext; }
71    static ISlangMutableFileSystem* getMutableSingleton() { return &g_mutable; }
72
73private:
74    /// Make so not constructible
75    OSFileSystem(FileSystemStyle style)
76        : m_style(style)
77    {
78    }
79
80    virtual ~OSFileSystem() {}
81
82    ISlangUnknown* getInterface(const Guid& guid);
83    void* getObject(const Guid& guid);
84
85    FileSystemStyle m_style;
86
87    static OSFileSystem g_load;
88    static OSFileSystem g_ext;
89    static OSFileSystem g_mutable;
90};
91
92/* Wraps an underlying ISlangFileSystem or ISlangFileSystemExt and provides caching,
93as well as emulation of methods if only has ISlangFileSystem interface. Will query capabilities
94of the interface on the constructor.
95
96NOTE! That this behavior is the same as previously in that....
971) calcRelativePath, just returns the path as processed by the Path:: methods
982) getUniqueIdentity behavior depends on the UniqueIdentityMode.
99*/
100class CacheFileSystem : public ComBaseObject, public ISlangFileSystemExt
101{
102public:
103    SLANG_CLASS_GUID(0x2f4d1d03, 0xa0d1, 0x434b, {0x87, 0x7a, 0x65, 0x5, 0xa4, 0xa0, 0x9a, 0x3b})
104
105    enum class PathStyle
106    {
107        Default,       ///< Pass to say use the default
108        Simplifiable,  ///< It can be simplified by Path::Simplify
109        FileSystemExt, ///< Use file system
110    };
111
112    enum UniqueIdentityMode
113    {
114        Default,             ///< If passed, will default to the others depending on what kind of
115                             ///< ISlangFileSystem is passed in
116        Path,                ///< Just use the path as is (old style slang behavior)
117        SimplifyPath,        ///< Use the input path 'simplified' (ie removing . and .. aspects)
118        Hash,                ///< Use hashing
119        SimplifyPathAndHash, ///< Tries simplifying path first, and if that doesn't work it hashes
120        FileSystemExt,       ///< Use the file system extended interface.
121    };
122
123    /* Cannot change order/add members without changing s_compressedResultToResult */
124    enum class CompressedResult : uint8_t
125    {
126        Uninitialized, ///< Holds no value
127        Ok,            ///< Ok
128        NotFound,      ///< File not found
129        CannotOpen,    ///< Cannot open
130        Fail,          ///< Generic failure
131        CountOf,
132    };
133
134    struct PathInfo
135    {
136        PathInfo(const String& uniqueIdentity)
137            : m_uniqueIdentity(uniqueIdentity)
138        {
139            m_loadFileResult = CompressedResult::Uninitialized;
140            m_getPathTypeResult = CompressedResult::Uninitialized;
141            m_getCanonicalPathResult = CompressedResult::Uninitialized;
142
143            m_pathType = SLANG_PATH_TYPE_FILE;
144        }
145
146        /// Get the unique identity path as a string
147        const String& getUniqueIdentity() const { return m_uniqueIdentity; }
148
149        String m_uniqueIdentity;
150        CompressedResult m_loadFileResult;
151        CompressedResult m_getPathTypeResult;
152        CompressedResult m_getCanonicalPathResult;
153
154        SlangPathType m_pathType;
155        ComPtr<ISlangBlob> m_fileBlob;
156        String m_canonicalPath;
157    };
158
159    Dictionary<String, PathInfo*>& getPathMap() { return m_pathMap; }
160    Dictionary<String, PathInfo*>& getUniqueMap() { return m_uniqueIdentityMap; }
161
162    // ISlangUnknown
163    SLANG_COM_BASE_IUNKNOWN_ALL
164
165    // ISlangCastable
166    virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
167
168    // ISlangFileSystem
169    virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(char const* path, ISlangBlob** outBlob)
170        SLANG_OVERRIDE;
171
172    // ISlangFileSystemExt
173    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
174    getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity) SLANG_OVERRIDE;
175    virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
176        SlangPathType fromPathType,
177        const char* fromPath,
178        const char* path,
179        ISlangBlob** pathOut) SLANG_OVERRIDE;
180    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
181    getPathType(const char* path, SlangPathType* outPathType) SLANG_OVERRIDE;
182    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
183    getPath(PathKind kind, const char* path, ISlangBlob** outPath) SLANG_OVERRIDE;
184
185    virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE;
186    virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(
187        const char* path,
188        FileSystemContentsCallBack callback,
189        void* userData) SLANG_OVERRIDE;
190    virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE
191    {
192        return m_osPathKind;
193    }
194
195    /// Get the unique identity mode
196    UniqueIdentityMode getUniqueIdentityMode() const { return m_uniqueIdentityMode; }
197    /// Get the path style
198    PathStyle getPathStyle() const { return m_pathStyle; }
199
200    /// Set the inner file system
201    void setInnerFileSystem(
202        ISlangFileSystem* fileSystem,
203        UniqueIdentityMode uniqueIdentityMode = UniqueIdentityMode::Default,
204        PathStyle pathStyle = PathStyle::Default);
205
206    /// Ctor
207    explicit CacheFileSystem(
208        ISlangFileSystem* fileSystem,
209        UniqueIdentityMode uniqueIdentityMode = UniqueIdentityMode::Default,
210        PathStyle pathStyle = PathStyle::Default);
211    /// Dtor
212    virtual ~CacheFileSystem();
213
214    static CompressedResult toCompressedResult(Result res);
215    static Result toResult(CompressedResult compRes)
216    {
217        return s_compressedResultToResult[int(compRes)];
218    }
219    static const Result s_compressedResultToResult[int(CompressedResult::CountOf)];
220
221protected:
222    void* getInterface(const Guid& guid);
223    void* getObject(const Guid& guid);
224
225    SlangResult _getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath);
226    SlangResult _getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath);
227
228    /// Given a path, works out a uniqueIdentity, based on the uniqueIdentityMode.
229    /// outFileContents will be set if file had to be read to produce the uniqueIdentity (ie with
230    /// Hash) If the file doesn't have to be read, then outFileContents will be nullptr, even if it
231    /// is backed by a file.
232    SlangResult _calcUniqueIdentity(
233        const String& path,
234        String& outUniqueIdentity,
235        ComPtr<ISlangBlob>& outFileContents);
236
237    /// For a given path gets a PathInfo. Can return nullptr, if it is not possible to create the
238    /// PathInfo for some reason
239    PathInfo* _resolvePathCacheInfo(const String& path);
240    /// Turns the path into a uniqueIdentity, and then tries to look up in the uniqueIdentityMap.
241    PathInfo* _resolveUniqueIdentityCacheInfo(const String& path);
242    /// Will simplify the path (if possible) to lookup on the pathCache else will create on
243    /// uniqueIdentityMap
244    PathInfo* _resolveSimplifiedPathCacheInfo(const String& path);
245
246    SlangResult _getPathType(PathInfo* pathInfo, const char* inPath, SlangPathType* pathTypeOut);
247
248    /* TODO: This may be improved by mapping to a ISlangBlob. This makes output fast and easy, and
249    if constructed as a StringBlob, we can just static_cast to get as a string to use internally,
250    instead of constantly converting. It is probably the case we cannot do dynamic_cast on
251    ISlangBlob if we don't know where constructed -> if outside of slang codebase doing such a cast
252    can cause an exception. So we *never* want to do dynamic cast from blobs which could be created
253    by external code. */
254
255    Dictionary<String, PathInfo*> m_pathMap; ///< Maps a path to a PathInfo (and unique identity)
256    Dictionary<String, PathInfo*> m_uniqueIdentityMap; ///< Maps a unique identity for a file to its
257                                                       ///< contents. This OWNs the PathInfo.
258
259    UniqueIdentityMode m_uniqueIdentityMode; ///< Determines how the 'uniqueIdentity' is produced.
260                                             ///< Cannot be Default in usage.
261    PathStyle m_pathStyle;                   ///< Style of paths
262
263    ComPtr<ISlangFileSystem> m_fileSystem; ///< Must always be set
264    ComPtr<ISlangFileSystemExt>
265        m_fileSystemExt; ///< Optionally set -> if nullptr will fall back on the m_fileSystem and
266                         ///< emulate all the other methods of ISlangFileSystemExt
267
268    OSPathKind m_osPathKind = OSPathKind::None; ///< OS path kind
269};
270
271class RelativeFileSystem : public ComBaseObject, public ISlangMutableFileSystem
272{
273public:
274    SLANG_COM_BASE_IUNKNOWN_ALL
275
276    // ISlangFileSystem
277    virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(char const* path, ISlangBlob** outBlob)
278        SLANG_OVERRIDE;
279
280    // ISlangCastable
281    virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
282
283    // ISlangFileSystemExt
284    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
285    getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity) SLANG_OVERRIDE;
286    virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
287        SlangPathType fromPathType,
288        const char* fromPath,
289        const char* path,
290        ISlangBlob** pathOut) SLANG_OVERRIDE;
291    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
292    getPathType(const char* path, SlangPathType* outPathType) SLANG_OVERRIDE;
293    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
294    getPath(PathKind pathKind, const char* path, ISlangBlob** outPath) SLANG_OVERRIDE;
295    virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE;
296    virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(
297        const char* path,
298        FileSystemContentsCallBack callback,
299        void* userData) SLANG_OVERRIDE;
300    virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() SLANG_OVERRIDE
301    {
302        return m_osPathKind;
303    }
304
305    // ISlangModifyableFileSystem
306    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
307    saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
308    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
309    saveFileBlob(const char* path, ISlangBlob* dataBlob) SLANG_OVERRIDE;
310    virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove(const char* path) SLANG_OVERRIDE;
311    virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(const char* path) SLANG_OVERRIDE;
312
313    /// stripPath will remove any path for an access, making an access always just
314    /// access the *filename* from the input path, in the contained filesystem at the relative path
315    RelativeFileSystem(
316        ISlangFileSystem* fileSystem,
317        const String& relativePath,
318        bool stripPath = false);
319
320protected:
321    ISlangFileSystemExt* _getExt()
322    {
323        return Index(m_style) >= Index(FileSystemStyle::Ext)
324                   ? reinterpret_cast<ISlangFileSystemExt*>(m_fileSystem.get())
325                   : nullptr;
326    }
327    ISlangMutableFileSystem* _getMutable()
328    {
329        return Index(m_style) >= Index(FileSystemStyle::Mutable)
330                   ? reinterpret_cast<ISlangMutableFileSystem*>(m_fileSystem.get())
331                   : nullptr;
332    }
333
334    SlangResult _calcCombinedPathInner(
335        SlangPathType fromPathType,
336        const char* fromPath,
337        const char* path,
338        ISlangBlob** pathOut);
339
340    /// Get the fixed path to the item for the backing file system.
341    SlangResult _getFixedPath(const char* path, String& outPath);
342
343    SlangResult _getCanonicalPath(const char* path, String& outPath);
344
345    ISlangUnknown* getInterface(const Guid& guid);
346    void* getObject(const Guid& guid);
347
348    bool m_stripPath; ///< If set any path prior to an item will be stripped (making the directory
349                      ///< in effect flat)
350
351    FileSystemStyle m_style;
352    ComPtr<ISlangFileSystem> m_fileSystem; ///< NOTE! Has to match what's in style, such style can
353                                           ///< be reached via reinterpret_cast
354
355    String m_relativePath;
356    OSPathKind m_osPathKind = OSPathKind::None; ///< OS path kind
357};
358
359} // namespace Slang
360
361#endif // SLANG_FILE_SYSTEM_H_INCLUDED