mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-16 22:30:42 +02:00
Adding the map of existing shaders and programs and ways to identify them to avoid recompiling them
This commit is contained in:
parent
0885b00ab8
commit
89f4fe1c04
2 changed files with 132 additions and 32 deletions
|
@ -17,59 +17,112 @@
|
|||
|
||||
using namespace gpu;
|
||||
|
||||
Shader::Shader(Type type, const Source& source):
|
||||
std::atomic<uint32_t> Shader::_nextShaderID( 1 );
|
||||
Shader::DomainShaderMaps Shader::_domainShaderMaps;
|
||||
Shader::ProgramMap Shader::_programMap;
|
||||
|
||||
|
||||
Shader::Shader(Type type, const Source& source) :
|
||||
_source(source),
|
||||
_type(type)
|
||||
_type(type),
|
||||
_ID(_nextShaderID++)
|
||||
{
|
||||
}
|
||||
|
||||
Shader::Shader(Type type, const Pointer& vertex, const Pointer& pixel):
|
||||
_type(type)
|
||||
Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel):
|
||||
_type(type),
|
||||
_ID(_nextShaderID++)
|
||||
{
|
||||
_shaders.resize(2);
|
||||
_shaders[VERTEX] = vertex;
|
||||
_shaders[PIXEL] = pixel;
|
||||
}
|
||||
|
||||
Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel) :
|
||||
_type(type) {
|
||||
_shaders.resize(3);
|
||||
_shaders[VERTEX] = vertex;
|
||||
_shaders[GEOMETRY] = geometry;
|
||||
_shaders[PIXEL] = pixel;
|
||||
if (geometry) {
|
||||
_shaders.resize(3);
|
||||
_shaders[VERTEX] = vertex;
|
||||
_shaders[GEOMETRY] = geometry;
|
||||
_shaders[PIXEL] = pixel;
|
||||
} else {
|
||||
_shaders.resize(2);
|
||||
_shaders[VERTEX] = vertex;
|
||||
_shaders[PIXEL] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createOrReuseDomainShader(Type type, const Source& source) {
|
||||
auto found = _domainShaderMaps[type].find(source);
|
||||
if (found != _domainShaderMaps[type].end()) {
|
||||
auto sharedShader = (*found).second.lock();
|
||||
if (sharedShader) {
|
||||
return sharedShader;
|
||||
}
|
||||
}
|
||||
auto shader = Pointer(new Shader(type, source));
|
||||
_domainShaderMaps[type].emplace(source, std::weak_ptr<Shader>(shader));
|
||||
return shader;
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createVertex(const Source& source) {
|
||||
return Pointer(new Shader(VERTEX, source));
|
||||
return createOrReuseDomainShader(VERTEX, source);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createPixel(const Source& source) {
|
||||
return Pointer(new Shader(PIXEL, source));
|
||||
return createOrReuseDomainShader(PIXEL, source);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createGeometry(const Source& source) {
|
||||
return Pointer(new Shader(GEOMETRY, source));
|
||||
return createOrReuseDomainShader(GEOMETRY, source);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) {
|
||||
if (vertexShader && vertexShader->getType() == VERTEX &&
|
||||
pixelShader && pixelShader->getType() == PIXEL) {
|
||||
return Pointer(new Shader(PROGRAM, vertexShader, pixelShader));
|
||||
ShaderPointer Shader::createOrReuseProgramShader(Type type, const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) {
|
||||
ProgramMapKey key(0);
|
||||
|
||||
if (vertexShader && vertexShader->getType() == VERTEX) {
|
||||
key.x = vertexShader->getID();
|
||||
} else {
|
||||
// Shader is not valid, exit
|
||||
return Pointer();
|
||||
}
|
||||
return Pointer();
|
||||
|
||||
if (pixelShader && pixelShader->getType() == PIXEL) {
|
||||
key.y = pixelShader->getID();
|
||||
} else {
|
||||
// Shader is not valid, exit
|
||||
return Pointer();
|
||||
}
|
||||
|
||||
if (geometryShader) {
|
||||
if (geometryShader->getType() == GEOMETRY) {
|
||||
key.z = geometryShader->getID();
|
||||
} else {
|
||||
// Shader is not valid, exit
|
||||
return Pointer();
|
||||
}
|
||||
}
|
||||
|
||||
// program key is defined, now try to reuse
|
||||
auto found = _programMap.find(key);
|
||||
if (found != _programMap.end()) {
|
||||
auto sharedShader = (*found).second.lock();
|
||||
if (sharedShader) {
|
||||
return sharedShader;
|
||||
}
|
||||
}
|
||||
|
||||
// Program is a new one, let's create it
|
||||
auto program = Pointer(new Shader(type, vertexShader, geometryShader, pixelShader));
|
||||
_programMap.emplace(key, std::weak_ptr<Shader>(program));
|
||||
return program;
|
||||
}
|
||||
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) {
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, nullptr, pixelShader);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) {
|
||||
if (vertexShader && vertexShader->getType() == VERTEX &&
|
||||
geometryShader && geometryShader->getType() == GEOMETRY &&
|
||||
pixelShader && pixelShader->getType() == PIXEL) {
|
||||
return Pointer(new Shader(PROGRAM, vertexShader, geometryShader, pixelShader));
|
||||
}
|
||||
return Pointer();
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, geometryShader, pixelShader);
|
||||
|
||||
}
|
||||
|
||||
void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& uniformBuffers, const SlotSet& resourceBuffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs) {
|
||||
|
@ -98,4 +151,5 @@ void Shader::setCompilationLogs(const CompilationLogs& logs) const {
|
|||
|
||||
void Shader::incrementCompilationAttempt() const {
|
||||
_numCompilationAttempts++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <string>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
|
@ -22,6 +23,8 @@ namespace gpu {
|
|||
|
||||
class Shader {
|
||||
public:
|
||||
// unique identifier of a shader
|
||||
using ID = uint32_t;
|
||||
|
||||
typedef std::shared_ptr< Shader > Pointer;
|
||||
typedef std::vector< Pointer > Shaders;
|
||||
|
@ -39,6 +42,11 @@ public:
|
|||
|
||||
virtual const std::string& getCode() const { return _code; }
|
||||
|
||||
class Less {
|
||||
public:
|
||||
bool operator() (const Source& x, const Source& y) const { if (x._lang == y._lang) { return x._code < y._code; } else { return (x._lang < y._lang); } }
|
||||
};
|
||||
|
||||
protected:
|
||||
std::string _code;
|
||||
Language _lang = GLSL;
|
||||
|
@ -134,6 +142,8 @@ public:
|
|||
|
||||
~Shader();
|
||||
|
||||
ID getID() const { return _ID; }
|
||||
|
||||
Type getType() const { return _type; }
|
||||
bool isProgram() const { return getType() > NUM_DOMAINS; }
|
||||
bool isDomain() const { return getType() < NUM_DOMAINS; }
|
||||
|
@ -194,15 +204,15 @@ public:
|
|||
|
||||
|
||||
const GPUObjectPointer gpuObject {};
|
||||
|
||||
|
||||
protected:
|
||||
Shader(Type type, const Source& source);
|
||||
Shader(Type type, const Pointer& vertex, const Pointer& pixel);
|
||||
Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel);
|
||||
|
||||
Shader(const Shader& shader); // deep copy of the sysmem shader
|
||||
Shader& operator=(const Shader& shader); // deep copy of the sysmem texture
|
||||
|
||||
|
||||
// Source contains the actual source code or nothing if the shader is a program
|
||||
Source _source;
|
||||
|
||||
|
@ -221,6 +231,9 @@ protected:
|
|||
// The type of the shader, the master key
|
||||
Type _type;
|
||||
|
||||
// The unique identifier of a shader in the GPU lib
|
||||
uint32_t _ID{ 0 };
|
||||
|
||||
// Number of attempts to compile the shader
|
||||
mutable uint32_t _numCompilationAttempts{ 0 };
|
||||
// Compilation logs (one for each versions generated)
|
||||
|
@ -228,6 +241,39 @@ protected:
|
|||
|
||||
// Whether or not the shader compilation failed
|
||||
bool _compilationHasFailed { false };
|
||||
|
||||
|
||||
// Global maps of the shaders
|
||||
// Unique shader ID
|
||||
static std::atomic<ID> _nextShaderID;
|
||||
|
||||
using ShaderMap = std::map<Source, std::weak_ptr<Shader>, Source::Less>;
|
||||
using DomainShaderMaps = std::array<ShaderMap, NUM_DOMAINS>;
|
||||
static DomainShaderMaps _domainShaderMaps;
|
||||
|
||||
static ShaderPointer createOrReuseDomainShader(Type type, const Source& source);
|
||||
|
||||
using ProgramMapKey = glm::uvec3; // THe IDs of the shaders in a progrma make its key
|
||||
class ProgramKeyLess {
|
||||
public:
|
||||
bool operator() (const ProgramMapKey& l, const ProgramMapKey& r) const {
|
||||
if (l.x == r.x) {
|
||||
if (l.y == r.y) {
|
||||
return (l.z < l.z);
|
||||
}
|
||||
else {
|
||||
return (l.y < l.y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return (l.x < r.x);
|
||||
}
|
||||
}
|
||||
};
|
||||
using ProgramMap = std::map<ProgramMapKey, std::weak_ptr<Shader>, ProgramKeyLess>;
|
||||
static ProgramMap _programMap;
|
||||
|
||||
static ShaderPointer createOrReuseProgramShader(Type type, const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader);
|
||||
};
|
||||
|
||||
typedef Shader::Pointer ShaderPointer;
|
||||
|
|
Loading…
Reference in a new issue