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 "Material/BsTechnique.h"
4#include "Error/BsException.h"
5#include "RenderAPI/BsRenderAPI.h"
6#include "Renderer/BsRendererManager.h"
7#include "Material/BsPass.h"
8#include "Renderer/BsRenderer.h"
9#include "Managers/BsGpuProgramManager.h"
10#include "Private/RTTI/BsTechniqueRTTI.h"
11
12namespace bs
13{
14 TechniqueBase::TechniqueBase(const String& language, const Vector<StringID>& tags, const ShaderVariation& variation)
15 :mLanguage(language), mTags(tags), mVariation(variation)
16 {
17
18 }
19
20 bool TechniqueBase::isSupported() const
21 {
22 if (ct::GpuProgramManager::instance().isLanguageSupported(mLanguage) || mLanguage == "Any")
23 return true;
24
25 return false;
26 }
27
28 bool TechniqueBase::hasTag(const StringID& tag)
29 {
30 for(auto& entry : mTags)
31 {
32 if (entry == tag)
33 return true;
34 }
35
36 return false;
37 }
38
39 template<bool Core>
40 TTechnique<Core>::TTechnique(const String& language, const Vector<StringID>& tags,
41 const ShaderVariation& variation, const Vector<SPtr<PassType>>& passes)
42 : TechniqueBase(language, tags, variation), mPasses(passes)
43 { }
44
45 template<bool Core>
46 TTechnique<Core>::TTechnique()
47 : TechniqueBase("", {}, ShaderVariation())
48 { }
49
50 template<bool Core>
51 SPtr<typename TTechnique<Core>::PassType> TTechnique<Core>::getPass(UINT32 idx) const
52 {
53 if (idx < 0 || idx >= (UINT32)mPasses.size())
54 BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
55
56 return mPasses[idx];
57 }
58 template<bool Core>
59 void TTechnique<Core>::compile()
60 {
61 for(auto& pass : mPasses)
62 pass->compile();
63 }
64
65 template class TTechnique < false > ;
66 template class TTechnique < true >;
67
68 Technique::Technique(const String& language, const Vector<StringID>& tags,
69 const ShaderVariation& variation, const Vector<SPtr<Pass>>& passes)
70 :TTechnique(language, tags, variation, passes)
71 { }
72
73 Technique::Technique()
74 : TTechnique()
75 { }
76
77 SPtr<ct::Technique> Technique::getCore() const
78 {
79 return std::static_pointer_cast<ct::Technique>(mCoreSpecific);
80 }
81
82 SPtr<ct::CoreObject> Technique::createCore() const
83 {
84 Vector<SPtr<ct::Pass>> passes;
85 for (auto& pass : mPasses)
86 passes.push_back(pass->getCore());
87
88 ct::Technique* technique = new(bs_alloc<ct::Technique>()) ct::Technique(
89 mLanguage,
90 mTags,
91 mVariation,
92 passes);
93
94 SPtr<ct::Technique> techniquePtr = bs_shared_ptr<ct::Technique>(technique);
95 techniquePtr->_setThisPtr(techniquePtr);
96
97 return techniquePtr;
98 }
99
100 void Technique::getCoreDependencies(Vector<CoreObject*>& dependencies)
101 {
102 for (auto& pass : mPasses)
103 dependencies.push_back(pass.get());
104 }
105
106 SPtr<Technique> Technique::create(const String& language, const Vector<SPtr<Pass>>& passes)
107 {
108 Technique* technique = new (bs_alloc<Technique>()) Technique(language, {}, ShaderVariation(), passes);
109 SPtr<Technique> techniquePtr = bs_core_ptr<Technique>(technique);
110 techniquePtr->_setThisPtr(techniquePtr);
111 techniquePtr->initialize();
112
113 return techniquePtr;
114 }
115
116 SPtr<Technique> Technique::create(const String& language, const Vector<StringID>& tags,
117 const ShaderVariation& variation, const Vector<SPtr<Pass>>& passes)
118 {
119 Technique* technique = new (bs_alloc<Technique>()) Technique(language, tags, variation, passes);
120 SPtr<Technique> techniquePtr = bs_core_ptr<Technique>(technique);
121 techniquePtr->_setThisPtr(techniquePtr);
122 techniquePtr->initialize();
123
124 return techniquePtr;
125 }
126
127 SPtr<Technique> Technique::createEmpty()
128 {
129 Technique* technique = new (bs_alloc<Technique>()) Technique();
130 SPtr<Technique> techniquePtr = bs_core_ptr<Technique>(technique);
131 techniquePtr->_setThisPtr(techniquePtr);
132
133 return techniquePtr;
134 }
135
136 RTTITypeBase* Technique::getRTTIStatic()
137 {
138 return TechniqueRTTI::instance();
139 }
140
141 RTTITypeBase* Technique::getRTTI() const
142 {
143 return Technique::getRTTIStatic();
144 }
145
146 namespace ct
147 {
148 Technique::Technique(const String& language, const Vector<StringID>& tags, const ShaderVariation& variation,
149 const Vector<SPtr<Pass>>& passes)
150 :TTechnique(language, tags, variation, passes)
151 { }
152
153 SPtr<Technique> Technique::create(const String& language, const Vector<SPtr<Pass>>& passes)
154 {
155 Technique* technique = new (bs_alloc<Technique>()) Technique(language, {}, ShaderVariation(), passes);
156 SPtr<Technique> techniquePtr = bs_shared_ptr<Technique>(technique);
157 techniquePtr->_setThisPtr(techniquePtr);
158 techniquePtr->initialize();
159
160 return techniquePtr;
161 }
162
163 SPtr<Technique> Technique::create(const String& language, const Vector<StringID>& tags,
164 const ShaderVariation& variation, const Vector<SPtr<Pass>>& passes)
165 {
166 Technique* technique = new (bs_alloc<Technique>()) Technique(language, tags, variation, passes);
167 SPtr<Technique> techniquePtr = bs_shared_ptr<Technique>(technique);
168 techniquePtr->_setThisPtr(techniquePtr);
169 techniquePtr->initialize();
170
171 return techniquePtr;
172 }
173 }
174}