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