0ad/source/graphics/ShaderManager.h
Ralph Sennhauser ead62bba78
Update trac links with gitea links
This replaces all links pointing to trac with their corresponding links
to gitea. Also replace http with https while at it.

Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
2024-12-10 11:29:48 +01:00

148 lines
4.7 KiB
C++

/* Copyright (C) 2024 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 "renderer/backend/IDevice.h"
#include "renderer/backend/PipelineState.h"
#include <functional>
#include <memory>
#include <set>
#include <unordered_map>
/**
* Shader manager: loads and caches shader programs.
*
* For a high-level overview of shaders and materials, see
* https://gitea.wildfiregames.com/0ad/0ad/wiki/MaterialSystem
*/
class CShaderManager
{
public:
CShaderManager(Renderer::Backend::IDevice* device);
~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 empty defines.
*/
CShaderTechniquePtr LoadEffect(CStrIntern name);
/**
* Load a shader effect with the pipeline state description overwriting.
* TODO: we should set all needed states in XML.
*/
using PipelineStateDescCallback = CShaderTechnique::PipelineStateDescCallback;
CShaderTechniquePtr LoadEffect(
CStrIntern name, const CShaderDefines& defines, const PipelineStateDescCallback& callback);
/**
* 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;
}
};
Renderer::Backend::IDevice* m_Device = nullptr;
// A CShaderProgram contains expensive backend 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