1 //
2 // Copyright 2019 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/usdImaging/plugin/sdrGlslfx/parserPlugin.h"
25
26 #include "pxr/base/vt/array.h"
27 #include "pxr/base/gf/vec2f.h"
28 #include "pxr/base/gf/vec3f.h"
29 #include "pxr/base/gf/matrix4f.h"
30 #include "pxr/base/gf/matrix4d.h"
31 #include "pxr/base/tf/staticTokens.h"
32 #include "pxr/usd/ar/resolver.h"
33 #include "pxr/usd/ndr/nodeDiscoveryResult.h"
34 #include "pxr/usd/sdr/shaderNode.h"
35 #include "pxr/usd/sdr/shaderProperty.h"
36 #include "pxr/imaging/hio/glslfx.h"
37
38 PXR_NAMESPACE_OPEN_SCOPE
39
40 NDR_REGISTER_PARSER_PLUGIN(SdrGlslfxParserPlugin);
41
42 TF_DEFINE_PRIVATE_TOKENS(
43 _tokens,
44
45 // Discovery and source type
46 ((discoveryType, "glslfx"))
47 ((sourceType, "glslfx"))
48 );
49
50 const NdrTokenVec&
GetDiscoveryTypes() const51 SdrGlslfxParserPlugin::GetDiscoveryTypes() const
52 {
53 static const NdrTokenVec _DiscoveryTypes = {_tokens->discoveryType};
54 return _DiscoveryTypes;
55 }
56
57 const TfToken&
GetSourceType() const58 SdrGlslfxParserPlugin::GetSourceType() const
59 {
60 return _tokens->sourceType;
61 }
62
63 static VtValue
ConvertToSdrCompatibleValueAndType(VtValue any,size_t * arraySize,TfToken * sdrType)64 ConvertToSdrCompatibleValueAndType(
65 VtValue any,
66 size_t * arraySize,
67 TfToken * sdrType)
68 {
69 // Unrecognized type by default
70 *sdrType = SdrPropertyTypes->Unknown;
71
72 // Not an array by default.
73 *arraySize = 0;
74
75 // XXX : Add support for the following sdr types:
76 // String, Struct, Terminal and Vstruct.
77 // XXX : We could add some glslfx metadata to recognize if this GfVec3f
78 // is an Sdr type Vector, Color, Point or a Normal..
79 if (any.IsHolding< std::vector<VtValue> >()) {
80
81 std::vector<VtValue> const & anyVec = any.Get< std::vector<VtValue> >();
82
83 // support for matrix
84 if (anyVec.size() == 16) {
85 if (anyVec[0].IsHolding<double>()) {
86 GfMatrix4d retMat;
87 double * m = retMat.GetArray();
88 for(int i=0; i < 16; i++) {
89 m[i] = anyVec[i].UncheckedGet<double>();
90 }
91 *sdrType = SdrPropertyTypes->Matrix;
92 return VtValue(retMat);
93 }
94 else if (anyVec[0].IsHolding<float>()) {
95 GfMatrix4f retMat;
96 float * m = retMat.GetArray();
97 for(int i=0; i < 16; i++) {
98 m[i] = anyVec[i].UncheckedGet<float>();
99 }
100 *sdrType = SdrPropertyTypes->Matrix;
101 return VtValue(retMat);
102 } else {
103 return VtValue();
104 }
105
106 // support for vectors length 1
107 } else if (anyVec.size() == 1) {
108 if (anyVec[0].IsHolding<double>()){
109 // Sdr has no doubles, converting them to floats
110 *sdrType = SdrPropertyTypes->Float;
111 return VtValue( (float)anyVec[0].UncheckedGet<double>());
112
113 } else if (anyVec[0].IsHolding<float>()){
114 *sdrType = SdrPropertyTypes->Float;
115 return VtValue( anyVec[0].UncheckedGet<float>());
116 }
117
118 // support for vectors length 2
119 } else if (anyVec.size() == 2) {
120 VtFloatArray retVec(2);
121 for (int i = 0; i < 2; i++) {
122 if (anyVec[i].IsHolding<double>()) {
123 retVec[i] = anyVec[i].UncheckedGet<double>();
124 } else if (anyVec[i].IsHolding<float>()) {
125 retVec[i] = anyVec[i].UncheckedGet<float>();
126 } else {
127 return VtValue();
128 }
129 }
130
131 *sdrType = SdrPropertyTypes->Float;
132 *arraySize = 2;
133 return VtValue(retVec);
134
135 } else if (anyVec.size() == 3) {
136 // support for vectors length 3
137 GfVec3f retVec;
138 for (int i = 0; i < 3; i++) {
139 if (anyVec[i].IsHolding<double>()) {
140 retVec[i] = anyVec[i].UncheckedGet<double>();
141 } else if (anyVec[i].IsHolding<float>()) {
142 retVec[i] = anyVec[i].UncheckedGet<float>();
143 } else {
144 return VtValue();
145 }
146 }
147
148 *sdrType = SdrPropertyTypes->Color;
149 return VtValue(retVec);
150
151 // support for vectors length 4
152 } else if (anyVec.size() == 4) {
153 VtFloatArray retVec(4);
154 for (int i = 0; i < 4; i++) {
155 if (anyVec[i].IsHolding<double>()) {
156 retVec[i] = anyVec[i].UncheckedGet<double>();
157 } else if (anyVec[i].IsHolding<float>()) {
158 retVec[i] = anyVec[i].UncheckedGet<float>();
159 } else {
160 return VtValue();
161 }
162 }
163
164 *sdrType = SdrPropertyTypes->Float;
165 *arraySize = 4;
166 return VtValue(retVec);
167 }
168
169 } else if (any.IsHolding<double>()){
170 // Sdr has no doubles, converting them to floats
171 *sdrType = SdrPropertyTypes->Float;
172 return VtValue( (float)any.UncheckedGet<double>());
173
174 } else if (any.IsHolding<float>()){
175 *sdrType = SdrPropertyTypes->Float;
176 return VtValue( any.UncheckedGet<float>());
177
178 } else if (any.IsHolding<int>()){
179 *sdrType = SdrPropertyTypes->Int;
180 return VtValue( any.UncheckedGet<int>());
181
182 } else if (any.IsHolding<bool>()){
183 // Sdr has no bool, converting them to int
184 *sdrType = SdrPropertyTypes->Int;
185 return VtValue( (int)any.UncheckedGet<bool>());
186 }
187
188 return any;
189 }
190
191 NdrNodeUniquePtr
Parse(const NdrNodeDiscoveryResult & discoveryResult)192 SdrGlslfxParserPlugin::Parse(const NdrNodeDiscoveryResult& discoveryResult)
193 {
194 std::unique_ptr<HioGlslfx> glslfx;
195
196 if (!discoveryResult.uri.empty()) {
197 #if AR_VERSION == 1
198 // Get the resolved URI to a location that can be read
199 // by the glslfx parser.
200 bool localFetchSuccessful = ArGetResolver().FetchToLocalResolvedPath(
201 discoveryResult.uri,
202 discoveryResult.resolvedUri
203 );
204
205 if (!localFetchSuccessful) {
206 TF_WARN("Could not localize the glslfx at URI [%s] into"
207 " a local path. An invalid Sdr node definition"
208 " will be created.",
209 discoveryResult.uri.c_str());
210 return NdrParserPlugin::GetInvalidNode(discoveryResult);
211 }
212 #endif
213
214 glslfx = std::make_unique<HioGlslfx>(discoveryResult.resolvedUri);
215
216 } else if (!discoveryResult.sourceCode.empty()) {
217 std::istringstream sourceCodeStream(discoveryResult.sourceCode);
218 glslfx = std::make_unique<HioGlslfx>(sourceCodeStream);
219
220 } else {
221 TF_WARN("Invalid NdrNodeDiscoveryResult with identifier %s: both uri "
222 "and sourceCode are empty.", discoveryResult.identifier.GetText());
223
224 return NdrParserPlugin::GetInvalidNode(discoveryResult);
225 }
226
227 std::string errorString;
228 if (!glslfx->IsValid(&errorString)){
229 TF_WARN("Failed to parse glslfx at URI [%s] error [%s]",
230 discoveryResult.uri.c_str(),
231 errorString.c_str());
232 }
233
234 NdrPropertyUniquePtrVec nodeProperties;
235
236 HioGlslfxConfig::Parameters params = glslfx->GetParameters();
237 for (HioGlslfxConfig::Parameter const & p : params) {
238
239 size_t arraySize = 0;
240 TfToken sdrType;
241 VtValue defaultValue = ConvertToSdrCompatibleValueAndType(
242 p.defaultValue,
243 &arraySize,
244 &sdrType);
245
246 NdrTokenMap hints;
247 NdrOptionVec options;
248 NdrTokenMap localMetadata;
249 nodeProperties.push_back(
250 std::make_unique<SdrShaderProperty>(
251 TfToken(p.name),
252 sdrType,
253 defaultValue,
254 false,
255 arraySize,
256 localMetadata,
257 hints,
258 options
259 ));
260 }
261
262 HioGlslfxConfig::Textures textures = glslfx->GetTextures();
263 for (HioGlslfxConfig::Texture const & t : textures) {
264
265 size_t arraySize = 0;
266 TfToken sdrType;
267 VtValue defaultValue = ConvertToSdrCompatibleValueAndType(
268 t.defaultValue,
269 &arraySize,
270 &sdrType);
271
272 // Check for a default value, or fallback to all black.
273 if (defaultValue.IsEmpty()) {
274 sdrType = SdrPropertyTypes->Color;
275 defaultValue = VtValue(GfVec3f(0.0,0.0,0.0));
276 }
277
278 NdrTokenMap hints;
279 NdrOptionVec options;
280 NdrTokenMap localMetadata;
281 nodeProperties.push_back(
282 std::make_unique<SdrShaderProperty>(
283 TfToken(t.name),
284 sdrType,
285 defaultValue,
286 false,
287 arraySize,
288 localMetadata,
289 hints,
290 options
291 ));
292 }
293
294 NdrTokenMap metadata = discoveryResult.metadata;
295 std::vector<std::string> primvarNames;
296 if (metadata.count(SdrNodeMetadata->Primvars)) {
297 primvarNames.push_back(metadata.at(SdrNodeMetadata->Primvars));
298 }
299
300 HioGlslfxConfig::Attributes attributes = glslfx->GetAttributes();
301 for (HioGlslfxConfig::Attribute const & a : attributes) {
302 primvarNames.push_back(a.name);
303 }
304
305 metadata[SdrNodeMetadata->Primvars] = TfStringJoin(primvarNames, "|");
306
307 // XXX: Add support for reading metadata from glslfx and converting
308 // to node metadata
309
310 return std::make_unique<SdrShaderNode>(
311 discoveryResult.identifier,
312 discoveryResult.version,
313 discoveryResult.name,
314 discoveryResult.family,
315 _tokens->sourceType,
316 _tokens->sourceType,
317 discoveryResult.resolvedUri,
318 discoveryResult.resolvedUri,
319 std::move(nodeProperties),
320 metadata,
321 discoveryResult.sourceCode);
322 }
323
324 PXR_NAMESPACE_CLOSE_SCOPE
325