First pass of new shader manager
This commit is contained in:
108
src/dawn/display/shader/ShaderManager.hpp
Normal file
108
src/dawn/display/shader/ShaderManager.hpp
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/Shader.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
typedef int64_t shaderlock_t;
|
||||
typedef int16_t shaderid_t;
|
||||
|
||||
class ShaderManager {
|
||||
private:
|
||||
int32_t nextId;
|
||||
shaderlock_t nextLock;
|
||||
std::map<shaderid_t, Shader*> shaders;
|
||||
std::map<shaderlock_t, shaderid_t> shaderLocks;
|
||||
std::map<shaderid_t, std::vector<shaderlock_t>> shaderLocksByShader;
|
||||
|
||||
/**
|
||||
* Returns the shader id for the given shader type, or -1 if it is not
|
||||
* loaded.
|
||||
*
|
||||
* @return The shader id for the shader, or -1 if it is not loaded.
|
||||
*/
|
||||
template<class T>
|
||||
shaderid_t getShaderId() {
|
||||
auto it = shaders.begin();
|
||||
while(it != shaders.end()) {
|
||||
auto asT = dynamic_cast<T*>(it->second);
|
||||
if(asT != nullptr) return asT->shaderId;
|
||||
++it;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new shader manager.
|
||||
*/
|
||||
ShaderManager();
|
||||
|
||||
/**
|
||||
* Locks a shader of the given type. If the shader is not already loaded,
|
||||
* it will be loaded. If the shader is already loaded, it will be
|
||||
* returned.
|
||||
*
|
||||
* @return The shader lock for the shader of the given type.
|
||||
*/
|
||||
template<class T>
|
||||
shaderlock_t lockShader() {
|
||||
auto shaderId = this->getShaderId<T>();
|
||||
if(shaderId == -1) {
|
||||
T* shader = new T();
|
||||
shader->compile();
|
||||
shader->shaderId = this->nextId++;
|
||||
this->shaders[shader->shaderId] = shader;
|
||||
shaderId = shader->shaderId;
|
||||
}
|
||||
|
||||
shaderlock_t lock = this->nextId++;
|
||||
this->shaderLocks[lock] = shaderId;
|
||||
this->shaderLocksByShader[shaderId].push_back(lock);
|
||||
return lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shader for the given lock.
|
||||
*
|
||||
* @param lock The shader lock.
|
||||
* @return The shader for the given lock.
|
||||
*/
|
||||
template<class T>
|
||||
T * getShader(shaderlock_t lock) {
|
||||
auto shaderId = this->shaderLocks[lock];
|
||||
return (T*)this->shaders[shaderId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the shader for the given lock. This will unload any shader
|
||||
* that is no longer in use.
|
||||
*
|
||||
* @param lock Lock to release.
|
||||
*/
|
||||
template<class T>
|
||||
void releaseShader(shaderlock_t lock) {
|
||||
auto shaderId = this->shaderLocks[lock];
|
||||
this->shaderLocks.erase(lock);
|
||||
|
||||
auto& locks = this->shaderLocksByShader[shaderId];
|
||||
auto it = std::find(locks.begin(), locks.end(), lock);
|
||||
if(it != locks.end()) locks.erase(it);
|
||||
|
||||
if(locks.size() == 0) {
|
||||
this->shaderLocksByShader.erase(shaderId);
|
||||
auto shader = (T*)this->shaders[shaderId];
|
||||
delete shader;
|
||||
this->shaders.erase(shaderId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the shader manager.
|
||||
*/
|
||||
~ShaderManager();
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user