1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "GLSL/BsGLSLProgramPipelineManager.h"
4#include "GLSL/BsGLSLGpuProgram.h"
5#include "Profiling/BsRenderStats.h"
6
7namespace bs { namespace ct
8{
9 ::std::size_t GLSLProgramPipelineManager::ProgramPipelineKeyHashFunction::operator()
10 (const GLSLProgramPipelineManager::ProgramPipelineKey &key) const
11 {
12 std::size_t seed = 0;
13 bs_hash_combine(seed, key.vertexProgKey);
14 bs_hash_combine(seed, key.fragmentProgKey);
15 bs_hash_combine(seed, key.geometryProgKey);
16 bs_hash_combine(seed, key.hullProgKey);
17 bs_hash_combine(seed, key.domainProgKey);
18
19 return seed;
20 }
21
22 bool GLSLProgramPipelineManager::ProgramPipelineKeyEqual::operator()
23 (const GLSLProgramPipelineManager::ProgramPipelineKey &a, const GLSLProgramPipelineManager::ProgramPipelineKey &b) const
24 {
25 return a.vertexProgKey == b.vertexProgKey && a.fragmentProgKey == b.fragmentProgKey && a.geometryProgKey == b.geometryProgKey &&
26 a.hullProgKey == b.hullProgKey && a.domainProgKey == b.domainProgKey;
27 }
28
29 GLSLProgramPipelineManager::~GLSLProgramPipelineManager()
30 {
31 for (auto& pipeline : mPipelines)
32 {
33 glDeleteProgramPipelines(1, &pipeline.second.glHandle);
34 BS_CHECK_GL_ERROR();
35
36 BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_PipelineObject);
37 }
38 }
39
40 const GLSLProgramPipeline* GLSLProgramPipelineManager::getPipeline(GLSLGpuProgram* vertexProgram, GLSLGpuProgram* fragmentProgram,
41 GLSLGpuProgram* geometryProgram, GLSLGpuProgram* hullProgram, GLSLGpuProgram* domainProgram)
42 {
43 ProgramPipelineKey key;
44 key.vertexProgKey = vertexProgram != nullptr ? vertexProgram->getProgramID() : 0;
45 key.fragmentProgKey = fragmentProgram != nullptr ? fragmentProgram->getProgramID() : 0;
46 key.geometryProgKey = geometryProgram != nullptr ? geometryProgram->getProgramID() : 0;
47 key.hullProgKey = hullProgram != nullptr ? hullProgram->getProgramID() : 0;
48 key.domainProgKey = domainProgram != nullptr ? domainProgram->getProgramID() : 0;
49
50 auto iterFind = mPipelines.find(key);
51
52 if(iterFind == mPipelines.end())
53 {
54 GLSLProgramPipeline newPipeline;
55
56 glGenProgramPipelines(1, &newPipeline.glHandle);
57 BS_CHECK_GL_ERROR();
58
59 if(vertexProgram != nullptr)
60 {
61 glUseProgramStages(newPipeline.glHandle, GL_VERTEX_SHADER_BIT, vertexProgram->getGLHandle());
62 BS_CHECK_GL_ERROR();
63 }
64
65 if(fragmentProgram != nullptr)
66 {
67 glUseProgramStages(newPipeline.glHandle, GL_FRAGMENT_SHADER_BIT, fragmentProgram->getGLHandle());
68 BS_CHECK_GL_ERROR();
69 }
70
71 if(geometryProgram != nullptr)
72 {
73 glUseProgramStages(newPipeline.glHandle, GL_GEOMETRY_SHADER_BIT, geometryProgram->getGLHandle());
74 BS_CHECK_GL_ERROR();
75 }
76
77 if(hullProgram != nullptr)
78 {
79 glUseProgramStages(newPipeline.glHandle, GL_TESS_CONTROL_SHADER_BIT, hullProgram->getGLHandle());
80 BS_CHECK_GL_ERROR();
81 }
82
83 if(domainProgram != nullptr)
84 {
85 glUseProgramStages(newPipeline.glHandle, GL_TESS_EVALUATION_SHADER_BIT, domainProgram->getGLHandle());
86 BS_CHECK_GL_ERROR();
87 }
88
89 mPipelines[key] = newPipeline;
90
91 BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineObject);
92 return &mPipelines[key];
93 }
94 else
95 return &iterFind->second;
96 }
97}}