Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_SHADERMANAGER
19 : #define INCLUDED_SHADERMANAGER
20 :
21 : #include "graphics/ShaderDefines.h"
22 : #include "graphics/ShaderProgram.h"
23 : #include "graphics/ShaderTechnique.h"
24 : #include "renderer/backend/PipelineState.h"
25 :
26 : #include <functional>
27 : #include <memory>
28 : #include <set>
29 : #include <unordered_map>
30 :
31 : /**
32 : * Shader manager: loads and caches shader programs.
33 : *
34 : * For a high-level overview of shaders and materials, see
35 : * http://trac.wildfiregames.com/wiki/MaterialSystem
36 : */
37 : class CShaderManager
38 : {
39 : public:
40 : CShaderManager();
41 : ~CShaderManager();
42 :
43 : /**
44 : * Load a shader effect.
45 : * Effects can be implemented via many techniques; this returns the best usable technique.
46 : * @param name name of effect XML specification (file is loaded from shaders/effects/${name}.xml)
47 : * @param defines key/value set of preprocessor definitions
48 : * @return loaded technique, or empty technique on error
49 : */
50 : CShaderTechniquePtr LoadEffect(CStrIntern name, const CShaderDefines& defines);
51 :
52 : /**
53 : * Load a shader effect, with empty defines.
54 : */
55 : CShaderTechniquePtr LoadEffect(CStrIntern name);
56 :
57 : /**
58 : * Load a shader effect with the pipeline state description overwriting.
59 : * TODO: we should set all needed states in XML.
60 : */
61 : using PipelineStateDescCallback = CShaderTechnique::PipelineStateDescCallback;
62 : CShaderTechniquePtr LoadEffect(
63 : CStrIntern name, const CShaderDefines& defines, const PipelineStateDescCallback& callback);
64 :
65 : /**
66 : * Returns the number of shader effects that are currently loaded.
67 : */
68 : size_t GetNumEffectsLoaded() const;
69 :
70 : private:
71 0 : struct CacheKey
72 : {
73 : std::string name;
74 : CShaderDefines defines;
75 :
76 0 : bool operator<(const CacheKey& k) const
77 : {
78 0 : if (name < k.name) return true;
79 0 : if (k.name < name) return false;
80 0 : return defines < k.defines;
81 : }
82 : };
83 :
84 : // A CShaderProgram contains expensive backend state, so we ought to cache it.
85 : // The compiled state depends solely on the filename and list of defines,
86 : // so we store that in CacheKey.
87 : // TODO: is this cache useful when we already have an effect cache?
88 : std::map<CacheKey, CShaderProgramPtr> m_ProgramCache;
89 :
90 : /**
91 : * Key for effect cache lookups.
92 : * This stores two separate CShaderDefines because the renderer typically
93 : * has one set from the rendering context and one set from the material;
94 : * by handling both separately here, we avoid the cost of having to merge
95 : * the two sets into a single one before doing the cache lookup.
96 : */
97 : struct EffectCacheKey
98 : {
99 : CStrIntern name;
100 : CShaderDefines defines;
101 :
102 : bool operator==(const EffectCacheKey& b) const;
103 : };
104 :
105 : struct EffectCacheKeyHash
106 : {
107 : size_t operator()(const EffectCacheKey& key) const;
108 : };
109 :
110 : using EffectCacheMap = std::unordered_map<EffectCacheKey, CShaderTechniquePtr, EffectCacheKeyHash>;
111 : EffectCacheMap m_EffectCache;
112 :
113 : // Store the set of shaders that need to be reloaded when the given file is modified
114 : template<typename T>
115 : using HotloadFilesMap = std::unordered_map<
116 : VfsPath,
117 : std::set<std::weak_ptr<T>, std::owner_less<std::weak_ptr<T>>>>;
118 : HotloadFilesMap<CShaderTechnique> m_HotloadTechniques;
119 : HotloadFilesMap<CShaderProgram> m_HotloadPrograms;
120 :
121 : /**
122 : * Load a shader program.
123 : * @param name name of shader XML specification (file is loaded from shaders/${name}.xml)
124 : * @param defines key/value set of preprocessor definitions
125 : * @return loaded program, or null pointer on error
126 : */
127 : CShaderProgramPtr LoadProgram(const CStr& name, const CShaderDefines& defines);
128 :
129 : bool LoadTechnique(CShaderTechniquePtr& tech);
130 :
131 : static Status ReloadChangedFileCB(void* param, const VfsPath& path);
132 : Status ReloadChangedFile(const VfsPath& path);
133 :
134 : /**
135 : * Associates the file with the technique to be reloaded if the file has changed.
136 : */
137 : void AddTechniqueFileDependency(const CShaderTechniquePtr& technique, const VfsPath& path);
138 :
139 : /**
140 : * Associates the file with the program to be reloaded if the file has changed.
141 : */
142 : void AddProgramFileDependency(const CShaderProgramPtr& program, const VfsPath& path);
143 : };
144 :
145 : #endif // INCLUDED_SHADERMANAGER
|