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 "BsShaderVariation.h"
4#include "Private/RTTI/BsShaderVariationRTTI.h"
5
6namespace bs
7{
8 void ShaderDefines::set(const String& name, float value)
9 {
10 mDefines[name] = toString(value);
11 }
12
13 void ShaderDefines::set(const String& name, INT32 value)
14 {
15 mDefines[name] = toString(value);
16 }
17
18 void ShaderDefines::set(const String& name, UINT32 value)
19 {
20 mDefines[name] = toString(value);
21 }
22
23 void ShaderDefines::set(const String& name, const String& value)
24 {
25 mDefines[name] = value;
26 }
27
28 const ShaderVariation ShaderVariation::EMPTY;
29
30 ShaderVariation::ShaderVariation(const SmallVector<Param, 4>& params)
31 {
32 for (auto& entry : params)
33 mParams[entry.name] = entry;
34 }
35
36 INT32 ShaderVariation::getInt(const StringID& name)
37 {
38 auto iterFind = mParams.find(name);
39 if (iterFind == mParams.end())
40 return 0;
41 else
42 return iterFind->second.i;
43 }
44
45 UINT32 ShaderVariation::getUInt(const StringID& name)
46 {
47 auto iterFind = mParams.find(name);
48 if (iterFind == mParams.end())
49 return 0;
50 else
51 return iterFind->second.ui;
52 }
53
54 float ShaderVariation::getFloat(const StringID& name)
55 {
56 auto iterFind = mParams.find(name);
57 if (iterFind == mParams.end())
58 return 0.0f;
59 else
60 return iterFind->second.f;
61 }
62
63 bool ShaderVariation::getBool(const StringID& name)
64 {
65 auto iterFind = mParams.find(name);
66 if (iterFind == mParams.end())
67 return false;
68 else
69 return iterFind->second.i > 0 ? true : false;
70 }
71
72 void ShaderVariation::setInt(const StringID& name, INT32 value)
73 {
74 addParam(Param(name, value));
75 }
76
77 void ShaderVariation::setUInt(const StringID& name, UINT32 value)
78 {
79 addParam(Param(name, value));
80 }
81
82 void ShaderVariation::setFloat(const StringID& name, float value)
83 {
84 addParam(Param(name, value));
85 }
86
87 void ShaderVariation::setBool(const StringID& name, bool value)
88 {
89 addParam(Param(name, value));
90 }
91
92 Vector<String> ShaderVariation::getParamNames() const
93 {
94 Vector<String> params;
95 params.reserve(mParams.size());
96
97 for(auto& entry : mParams)
98 params.push_back(entry.first);
99
100 return params;
101 }
102
103 ShaderDefines ShaderVariation::getDefines() const
104 {
105 ShaderDefines defines;
106 for (auto& entry : mParams)
107 {
108 switch (entry.second.type)
109 {
110 case Int:
111 case Bool:
112 defines.set(entry.first.c_str(), entry.second.i);
113 break;
114 case UInt:
115 defines.set(entry.first.c_str(), entry.second.ui);
116 break;
117 case Float:
118 defines.set(entry.first.c_str(), entry.second.f);
119 break;
120 }
121 }
122
123 return defines;
124 }
125
126 bool ShaderVariation::matches(const ShaderVariation& other, bool exact) const
127 {
128 for(auto& entry : other.mParams)
129 {
130 const auto iterFind = mParams.find(entry.first);
131 if(iterFind == mParams.end())
132 return false;
133
134 if(entry.second.i != iterFind->second.i)
135 return false;
136 }
137
138 if(exact)
139 {
140 for (auto& entry : mParams)
141 {
142 const auto iterFind = other.mParams.find(entry.first);
143 if (iterFind == other.mParams.end())
144 return false;
145
146 if (entry.second.i != iterFind->second.i)
147 return false;
148 }
149 }
150
151 return true;
152 }
153
154 bool ShaderVariation::operator==(const ShaderVariation& rhs) const
155 {
156 return matches(rhs, true);
157 }
158
159 void ShaderVariations::add(const ShaderVariation& variation)
160 {
161 variation.mIdx = mNextIdx++;
162
163 mVariations.add(variation);
164 }
165
166 UINT32 ShaderVariations::find(const ShaderVariation& variation) const
167 {
168 UINT32 idx = 0;
169 for(auto& entry : mVariations)
170 {
171 if(entry == variation)
172 return idx;
173
174 idx++;
175 }
176
177 return (UINT32)-1;
178 }
179
180 RTTITypeBase* ShaderVariation::getRTTIStatic()
181 {
182 return ShaderVariationRTTI::instance();
183 }
184
185 RTTITypeBase* ShaderVariation::getRTTI() const
186 {
187 return ShaderVariation::getRTTIStatic();
188 }
189
190 // This is here to solve a linking issue on Clang 7. The destructor apparently either doesn't get implicitly
191 // instantiated. This means external libraries linking with bsf, using the same SmallVector template parameters will
192 // trigger an undefined reference linker error. And why doesn't the library instantiate it itself? Don't know, either
193 // a Clang issue or maybe even some part of the standard.
194 template SmallVector<ShaderVariation::Param, 4>::~SmallVector();
195}