Nameless Engine
|
#include <ShaderManager.h>
Classes | |
struct | ShaderData |
Public Member Functions | |
ShaderManager (Renderer *pRenderer) | |
ShaderManager (const ShaderManager &)=delete | |
ShaderManager & | operator= (const ShaderManager &)=delete |
std::optional< Error > | compileShaders (std::vector< ShaderDescription > vShadersToCompile, const std::function< void(size_t iCompiledShaderCount, size_t iTotalShadersToCompile)> &onProgress, const std::function< void(ShaderDescription shaderDescription, std::variant< std::string, Error > error)> &onError, const std::function< void()> &onCompleted) |
bool | isShaderNameCanBeUsed (const std::string &sShaderName) |
bool | markShaderToBeRemoved (const std::string &sShaderName) |
void | performSelfValidation () |
Protected Member Functions | |
void | compileShaderTask (size_t iQueryId, const std::shared_ptr< std::atomic< size_t > > &pCompiledShaderCount, size_t iTotalShaderCount, ShaderDescription shaderDescription, const std::function< void(size_t iCompiledShaderCount, size_t iTotalShadersToCompile)> &onProgress, const std::function< void(ShaderDescription shaderDescription, std::variant< std::string, Error > error)> &onError, const std::function< void()> &onCompleted) |
std::shared_ptr< ShaderPack > | findShader (const std::string &sShaderName) |
void | releaseShaderBytecodeIfNotUsed (const std::string &sShaderName) |
void | removeShaderIfMarkedToBeRemoved (const std::string &sShaderName) |
std::optional< Error > | refreshShaderCache () |
Private Attributes | |
std::unique_ptr< ShaderCacheManager > | pShaderCacheManager |
std::pair< std::recursive_mutex, ShaderData > | mtxShaderData |
std::atomic< size_t > | iTotalCompileShadersQueries = 0 |
Renderer *const | pRenderer = nullptr |
Static Private Attributes | |
static const std::array< char, 65 > | vValidCharactersForShaderName |
static const size_t | iMaximumShaderNameLength = 40 |
Friends | |
class | ShaderUser |
class | Renderer |
Handles shader compilation and controls shader registry.
ne::ShaderManager::ShaderManager | ( | Renderer * | pRenderer | ) |
Constructor.
pRenderer | Parent renderer that uses this shader manager. |
std::optional< Error > ne::ShaderManager::compileShaders | ( | std::vector< ShaderDescription > | vShadersToCompile, |
const std::function< void(size_t iCompiledShaderCount, size_t iTotalShadersToCompile)> & | onProgress, | ||
const std::function< void(ShaderDescription shaderDescription, std::variant< std::string, Error > error)> & | onError, | ||
const std::function< void()> & | onCompleted | ||
) |
Add shaders to be asynchronously compiled.
Compiled shaders are stored on disk, when a shader is needed it will be automatically loaded from disk into memory and when no longer being used it will be released from memory (stored on disk again).
vShadersToCompile | Array of shaders to compile. Use isShaderNameCanBeUsed to check if a shader name is free (unique). |
onProgress | Callback function that will be called when each shader is compiled. This will also be called when all shaders are compiled (together with 'onCompleted'). The first argument is number of compiled shaders and the second one is total number of shaders to compile. |
onError | Callback function that will be called if an error occurred. This might be one of the two things: shader compilation error/warning (shader contains error) or internal error (engine failed to compile shader). If there was a shader compilation error/warning, this shader will be marked as processed and onProgress will be called (but this shader will not be added to shader manager and will not be available, you will need to fix the error and add this shader again). |
onCompleted | Callback function that will be called once all shaders are compiled. |
|
protected |
Compiles each shader. Executed as a thread pooled task to do this work asynchronously.
iQueryId | Unique number used to differentiate different calls compileShaders. |
pCompiledShaderCount | Current total number of shaders compiled (in query). |
iTotalShaderCount | Total number of shaders to compile in this query (might be bigger than the size of the vShadersToCompile argument because the query is divided in smaller tasks). |
shaderDescription | Shader to compile. |
onProgress | Callback function that will be called when each shader is compiled. This will also be called when all shaders are compiled (together with 'onCompleted'). The first argument is number of compiled shaders and the second one is total number of shaders to compile. |
onError | Callback function that will be called if an error occurred. This might be one of the two things: shader compilation error/warning (shader contains error) or internal error (engine failed somewhere). If there was a shader compilation error/warning, this shader will be marked as processed and onProgress will be called (but this shader will not be added to shader manager and will not be available, use will need to fix the error and add this shader again). |
onCompleted | Callback function that will be called once all shaders are compiled. |
|
protected |
Returns compiled shader (compiled using compileShaders).
sShaderName | Name of this shader. |
nullptr
if the shader with the specified name was not found, valid pointer otherwise. bool ne::ShaderManager::isShaderNameCanBeUsed | ( | const std::string & | sShaderName | ) |
Checks if the shader name is free (no shader with this name found) to be used in compileShaders.
sShaderName | Name to check. |
true
if can be used (no shader with this name found), false
otherwise. bool ne::ShaderManager::markShaderToBeRemoved | ( | const std::string & | sShaderName | ) |
Removes the shader if nobody is referencing it, otherwise marks shader to be removed later.
Typically you would not use this function as we expect you to make one call to compileShaders in the beginning of the game to compile ALL of your shaders (for all levels) and never remove them as compiled shaders are not stored in memory, they are stored on disk and when actually needed/used loaded from disk to memory. If some shader was used but no longer needed it will be released from memory until someone will need it again.
If somebody is still referencing this shader, the shader will be added to "to remove" array and will be removed later when nobody is referencing this shader (specifically when only one std::shared_ptr<Shader> instance pointing to this shader will exist (it will exist in ShaderManager as ShaderManager stores pointer to each shader)).
sShaderName | Shader name to be marked for removal. |
void ne::ShaderManager::performSelfValidation | ( | ) |
Analyzes the current state to see if any shader-related errors have place (like unused shaders in memory or etc.). Fixes errors and reports them in log.
|
protected |
Looks if any of the global shader cache parameters changed (such as build mode, shader model, etc.), clears shader cache directory and creates a fresh new shader cache directory with up to date info.
|
protected |
Looks if the specified shader is not used by anyone and releases shader bytecode from memory if it was previously loaded.
sShaderName | Name of the shader to release bytecode. |
|
protected |
Looks if this shader was marked "to be removed" and that it's not being used by anyone else, if this is correct removes the shader.
sShaderName | Name of the shader to remove. |
|
inlinestaticprivate |
Maximum length of a shader name.
|
private |
Total number of "compile shaders" queries. Used to differentiate calls to compileShaderTask.
|
private |
Internal shader data guarded by mutex.
|
private |
Do not delete. Parent renderer that uses this shader manager.
|
private |
Handles everything related to shader cache.
|
inlinestaticprivate |
Array of characters that can be used for shader name. We limit amount of valid characters because we store compiled shaders on disk and different filesystems have different limitations for file names.