Vuo 2.4.4
Loading...
Searching...
No Matches
VuoIsfModuleCompiler.cc
Go to the documentation of this file.
1
11#include <sstream>
12
13void *VuoApp_mainThread = nullptr;
14
18void __attribute__((constructor)) VuoIsfModuleCompiler::init()
19{
20 VuoModuleCompiler::registerModuleCompiler("isf", &VuoIsfModuleCompiler::newModuleCompiler);
22 VuoApp_mainThread = (void *)pthread_self();
23}
24
28VuoIsfModuleCompiler::VuoIsfModuleCompiler(const string &moduleKey, const string &sourcePath,
29 const VuoModuleCompilerSettings &settings) :
30 VuoModuleCompiler(moduleKey, sourcePath, settings),
31 shaderFile(nullptr)
32{
33}
34
38VuoModuleCompiler * VuoIsfModuleCompiler::newModuleCompiler(const string &moduleKey, const string &sourcePath,
39 const VuoModuleCompilerSettings &settings)
40{
41 string dir, file, ext;
45
46 return nullptr;
47}
48
52void VuoIsfModuleCompiler::overrideSourceCode(const string &sourceCode, const string &sourcePath)
53{
54 this->sourceCode = sourceCode;
55}
56
61{
63
64 string dir, file, ext;
66 VuoFileUtilities::File sourceFile(dir, file + "." + ext);
67
68 try
69 {
70 shaderFile = new VuoShaderFile(sourceFile, sourceCode);
71 }
72 catch (VuoException &e)
73 {
74 VuoCompilerIssue issue(VuoCompilerIssue::Error, "compiling ISF node class", sourcePath, "", e.what());
75 issues->append(issue);
76 return results;
77 }
78
79 // Check for GLSL syntax errors.
80
81 VuoShader shader = VuoShader_makeFromFile(shaderFile);
82 VuoLocal(shader);
83
84 shared_ptr<VuoShaderIssues> shaderIssues = std::make_shared<VuoShaderIssues>();
85 __block bool ok;
86 VuoGlContext_perform(^(CGLContextObj cgl_ctx){
87 ok = VuoShader_upload(shader, VuoMesh_IndividualTriangles, cgl_ctx, shaderIssues.get());
88 });
89
90 if (! ok)
91 {
92 VuoCompilerIssue issue(VuoCompilerIssue::Error, "compiling ISF node class", sourcePath, "", "Failed to parse shader");
93 issue.setShaderIssues(shaderIssues);
94 issues->append(issue);
95 return results;
96 }
97
98 // Look up types before getting on llvmQueue.
99
100 vector<string> vuoTypesUsed = { "VuoShader", "VuoImage", "VuoImageColorDepth", "VuoReal", "VuoInteger", "VuoBoolean" };
101 for (VuoShaderFile::Port shaderInputPort : shaderFile->inputPorts())
102 vuoTypesUsed.push_back(shaderInputPort.vuoTypeName);
103
104 for (const string &typeName : vuoTypesUsed)
105 lookUpVuoType(typeName);
106
107 // Generate bitcode.
108
109 __block Module *module;
110 dispatch_sync(llvmQueue, ^{
111
112 module = new Module(moduleKey, *VuoCompiler::globalLLVMContext);
113 VuoCompilerConstantsCache constantsCache(module);
114
115 if (shaderFile->type() == VuoShaderFile::GLSLImageFilter
116 || shaderFile->type() == VuoShaderFile::GLSLImageGenerator
117 || shaderFile->type() == VuoShaderFile::GLSLImageTransition)
118 {
119 generateMetadata(module);
120 generateNodeInstanceInitFunction(module, &constantsCache, vuoTypes, issues);
121 generateNodeInstanceEventFunction(module, &constantsCache, vuoTypes, issues);
122 }
123 else if (shaderFile->type() == VuoShaderFile::GLSLObjectRenderer)
124 {
126 }
127 else if (shaderFile->type() == VuoShaderFile::GLSLObjectFilter)
128 {
130 }
131
132 });
133
134 results.module = module;
136 return results;
137}
138
142void VuoIsfModuleCompiler::generateMetadata(Module *module)
143{
144 json_object *metadata = shaderFile->vuoModuleMetadata();
145 VuoCompilerCodeGenUtilities::generateModuleMetadata(module, json_object_to_json_string_ext(metadata, JSON_C_TO_STRING_PLAIN), "");
146}
147
151void VuoIsfModuleCompiler::generateNodeInstanceInitFunction(Module *module, VuoCompilerConstantsCache *constantsCache,
152 map<string, VuoCompilerType *> vuoTypes, VuoCompilerIssues *issues)
153{
154 Constant *vertexSourceValue = VuoCompilerCodeGenUtilities::generatePointerToConstantString(module, shaderFile->expandedVertexSource(), "vertexSource");
155 Constant *geometrySourceValue = VuoCompilerCodeGenUtilities::generatePointerToConstantString(module, shaderFile->expandedGeometrySource(), "geometrySource");
156 Constant *fragmentSourceValue = VuoCompilerCodeGenUtilities::generatePointerToConstantString(module, shaderFile->expandedFragmentSource(), "fragmentSource");
157
158 VuoCompilerType *vuoShaderType = vuoTypes["VuoShader"];
159 if (!isTypeFound(vuoShaderType, issues))
160 return;
161
162 Type *llvmShaderType = getFunctionParameterType(vuoShaderType, issues);
163 if (!llvmShaderType)
164 return;
165
166 map<VuoPort *, size_t> indexOfParameterInit;
167
169 llvmShaderType, vector<VuoPort *>(),
170 indexOfParameterInit, constantsCache);
171
172 BasicBlock *block = &(function->getEntryBlock());
173
174 // VuoShader s = VuoShader_make(sf->name());
175
176 Function *makeFunction = VuoCompilerCodeGenUtilities::getVuoShaderMakeFunction(module);
177 Value *shaderNameValue = constantsCache->get(shaderFile->name());
178 Value *shaderValue = CallInst::Create(makeFunction, shaderNameValue, "s", block);
179
180 // VuoShader_addSource(s, VuoMesh_IndividualTriangles, vertexSource, geometrySource, fragmentSource);
181
182 Function *addSourceFunction = VuoCompilerCodeGenUtilities::getVuoShaderAddSourceFunction(module);
183 vector<Value *> addSourceArgs;
184 addSourceArgs.push_back(shaderValue);
185 addSourceArgs.push_back(ConstantInt::get(addSourceFunction->getFunctionType()->getParamType(1), 0));
186 addSourceArgs.push_back(vertexSourceValue);
187 addSourceArgs.push_back(geometrySourceValue);
188 addSourceArgs.push_back(fragmentSourceValue);
189 CallInst::Create(addSourceFunction, addSourceArgs, "", block);
190
191 // ISF shaders can potentially produce transparent output,
192 // even if the input images and colors are opaque.
193 // s->isTransparent = true;
194 Function *setTransparentFunction = VuoCompilerCodeGenUtilities::getVuoShaderSetTransparentFunction(module);
195 vector<Value *> setTransparentArgs;
196 setTransparentArgs.push_back(shaderValue);
197 setTransparentArgs.push_back(ConstantInt::get(setTransparentFunction->getFunctionType()->getParamType(1), 1));
198 CallInst::Create(setTransparentFunction, setTransparentArgs, "", block);
199
200 // return s;
201
202 Value *shaderValueAsReturn = new BitCastInst(shaderValue, function->getReturnType(), "", block);
203 ReturnInst::Create(module->getContext(), shaderValueAsReturn, block);
204}
205
209void VuoIsfModuleCompiler::generateNodeInstanceEventFunction(Module *module, VuoCompilerConstantsCache *constantsCache,
210 map<string, VuoCompilerType *> vuoTypes, VuoCompilerIssues *issues)
211{
212 vector<VuoPort *> inputPorts;
213 vector<VuoPort *> outputPorts;
214 map<VuoPort *, json_object *> detailsForPorts;
215
216 auto addInputPort = [&inputPorts, &detailsForPorts, &vuoTypes] (const string &portName, const string &typeName, json_object *details)
217 {
218 VuoCompilerType *type = typeName == "event" ? NULL : vuoTypes[typeName];
219 VuoCompilerInputEventPort *inputPort = VuoCompilerInputEventPort::newPort(portName, type ? type->getBase() : NULL);
220 inputPorts.push_back(inputPort->getBase());
221 detailsForPorts[inputPort->getBase()] = details;
222 };
223
224 auto addOutputPort = [&outputPorts, &detailsForPorts, &vuoTypes] (const string &portName, const string &typeName, json_object *details)
225 {
226 VuoCompilerType *type = vuoTypes[typeName];
228 outputPorts.push_back(outputPort->getBase());
229 detailsForPorts[outputPort->getBase()] = details;
230 };
231
232 VuoPort *widthInputPort = nullptr;
233 VuoPort *heightInputPort = nullptr;
234 auto addWidthHeightInputPorts = [&inputPorts, &addInputPort, &widthInputPort, &heightInputPort] (void)
235 {
236 // VuoInputData(VuoInteger, {"name":"Width", "default":640, "suggestedMin":1, "suggestedStep":32}) vuoWidth,
237 // VuoInputData(VuoInteger, {"name":"Height", "default":480, "suggestedMin":1, "suggestedStep":32}) vuoHeight
238
239 json_object *widthDetails = json_object_new_object();
240 json_object_object_add(widthDetails, "name", VuoText_getJson("Width"));
241 json_object_object_add(widthDetails, "default", VuoInteger_getJson(640));
242 json_object_object_add(widthDetails, "suggestedMin", VuoInteger_getJson(1));
243 json_object_object_add(widthDetails, "suggestedStep", VuoInteger_getJson(32));
244 json_object *heightDetails = json_object_new_object();
245 json_object_object_add(heightDetails, "name", VuoText_getJson("Height"));
246 json_object_object_add(heightDetails, "default", VuoInteger_getJson(480));
247 json_object_object_add(heightDetails, "suggestedMin", VuoInteger_getJson(1));
248 json_object_object_add(heightDetails, "suggestedStep", VuoInteger_getJson(32));
249
250 addInputPort("vuoWidth", "VuoInteger", widthDetails);
251 if (! widthInputPort)
252 widthInputPort = inputPorts.back();
253 addInputPort("vuoHeight", "VuoInteger", heightDetails);
254 if (! heightInputPort)
255 heightInputPort = inputPorts.back();
256 };
257
258 VuoPort *timeInputPort = nullptr;
259 if (shaderFile->showsTime())
260 {
261 // VuoInputData(VuoReal, {"name":"Time", "default":0.0, "suggestedStep":0.1}) vuoTime
262
263 json_object *details = json_object_new_object();
264 json_object_object_add(details, "name", VuoText_getJson("Time"));
265 json_object_object_add(details, "default", VuoReal_getJson(0.0));
266 json_object_object_add(details, "suggestedStep", VuoReal_getJson(0.1));
267
268 addInputPort("vuoTime", "VuoReal", details);
269 timeInputPort = inputPorts.back();
270 }
271
272 VuoPort *colorDepthInputPort = nullptr;
273 bool hasImageInputPort = false;
274 for (VuoShaderFile::Port shaderInputPort : shaderFile->inputPorts())
275 {
276 if (shaderInputPort.vuoTypeName == "VuoSize")
277 {
278 addWidthHeightInputPorts();
279 }
280 else if (shaderInputPort.vuoTypeName == "VuoImageColorDepth")
281 {
282 // VuoInputData(VuoImageColorDepth, {"name":"Color Depth", "default":"8bpc"}) vuoColorDepth
283
284 json_object *details = shaderInputPort.vuoPortDetails;
285 json_object_object_add(details, "name", VuoText_getJson("Color Depth"));
286 json_object_object_add(details, "default", VuoImageColorDepth_getJson(VuoImageColorDepth_8));
287
288 addInputPort("vuoColorDepth", shaderInputPort.vuoTypeName, details);
289
290 if (! colorDepthInputPort)
291 colorDepthInputPort = inputPorts.back();
292 }
293 else
294 {
295 // VuoInputData(type) name
296
297 if (shaderInputPort.vuoTypeName == "VuoBoolean")
298 {
299 json_object *defaultValue = NULL;
300 json_object_object_get_ex(shaderInputPort.vuoPortDetails, "default", &defaultValue);
301 defaultValue = VuoBoolean_getJson(VuoBoolean_makeFromJson(defaultValue));
302 json_object_object_add(shaderInputPort.vuoPortDetails, "default", defaultValue);
303 }
304
305 addInputPort(shaderInputPort.key, shaderInputPort.vuoTypeName, shaderInputPort.vuoPortDetails);
306
307 if (shaderInputPort.vuoTypeName == "VuoImage")
308 hasImageInputPort = true;
309 }
310 }
311
312 if (! hasImageInputPort && ! widthInputPort && ! heightInputPort)
313 {
314 addWidthHeightInputPorts();
315 }
316
317 {
318 // VuoOutputData(type) name
319
320 VuoShaderFile::Port shaderOutputPort = shaderFile->outputPort();
321 addOutputPort(shaderOutputPort.key, "VuoImage", shaderOutputPort.vuoPortDetails);
322 }
323
324 VuoCompilerType *vuoShaderType = vuoTypes["VuoShader"];
325 if (!isTypeFound(vuoShaderType, issues))
326 return;
327
328 Type *llvmShaderType = getFunctionParameterType(vuoShaderType, issues);
329 if (!llvmShaderType)
330 return;
331
332 map<VuoPort *, size_t> indexOfParameter;
333 map<VuoPort *, size_t> indexOfEventParameter;
334
335 Function *function = VuoCompilerCodeGenUtilities::getNodeEventFunction(module, moduleKey, false, true,
336 llvmShaderType, inputPorts, outputPorts,
337 detailsForPorts, map<VuoPort *, string>(),
338 map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
339 indexOfParameter, indexOfEventParameter, constantsCache);
340
341 BasicBlock *initialBlock = &(function->getEntryBlock());
342
343 Value *outputImagePointer = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, indexOfParameter[outputPorts.at(0)]);
344 Value *instanceDataPointerValue = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, 0);
345 Value *instanceDataValue = new LoadInst(instanceDataPointerValue, "instanceData", false, initialBlock);
346
347 // Find the first non-NULL input image.
348
349 BasicBlock *findImageBlock = initialBlock;
350 BasicBlock *widthHeightBlock = BasicBlock::Create(module->getContext(), "widthHeight", function, nullptr);
351
352 VuoCompilerType *vuoImageType = vuoTypes["VuoImage"];
353 if (!isTypeFound(vuoImageType, issues))
354 return;
355
356 Type *llvmImageType = getFunctionParameterType(vuoImageType, issues);
357 if (!llvmImageType)
358 return;
359
360 ConstantPointerNull *nullImageValue = ConstantPointerNull::get(static_cast<PointerType *>(llvmImageType));
361
362 AllocaInst *foundImageVariable = new AllocaInst(llvmImageType, 0, "foundImageVar", findImageBlock);
363 new StoreInst(nullImageValue, foundImageVariable, findImageBlock);
364
365 BasicBlock *currBlock = findImageBlock;
366 for (VuoPort *inputPort : inputPorts)
367 {
368 VuoType *type = static_cast<VuoCompilerPort *>(inputPort->getCompiler())->getDataVuoType();
369 if (type && type->getModuleKey() == "VuoImage")
370 {
371 BasicBlock *imageNotNullBlock = BasicBlock::Create(module->getContext(), "imageNotNull", function, nullptr);
372 BasicBlock *imageNullBlock = BasicBlock::Create(module->getContext(), "imageNull", function, nullptr);
373
374 Value *imageValue = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, indexOfParameter[inputPort]);
375 ICmpInst *imageNotNull = new ICmpInst(*currBlock, ICmpInst::ICMP_NE, imageValue, nullImageValue, "");
376 BranchInst::Create(imageNotNullBlock, imageNullBlock, imageNotNull, currBlock);
377
378 new StoreInst(imageValue, foundImageVariable, imageNotNullBlock);
379 BranchInst::Create(widthHeightBlock, imageNotNullBlock);
380
381 currBlock = imageNullBlock;
382 }
383 }
384
385 BranchInst::Create(widthHeightBlock, currBlock);
386
387 // Set width and height…
388
389 BasicBlock *colorDepthBlock = nullptr;
390 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(), "final", function, nullptr);
391
392 Value *widthValue = nullptr;
393 Value *heightValue = nullptr;
394 if (widthInputPort && heightInputPort)
395 {
396 // … from input port values if they exist.
397
398 widthValue = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, indexOfParameter[widthInputPort]);
399 heightValue = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, indexOfParameter[heightInputPort]);
400
401 colorDepthBlock = widthHeightBlock;
402 }
403 else
404 {
405 // … to the first non-NULL image's pixelsWide/High.
406 // If no non-NULL image, set the output image to NULL and return.
407
408 BasicBlock *imageNotNullBlock = BasicBlock::Create(module->getContext(), "foundImageNotNull", function, nullptr);
409 BasicBlock *imageNullBlock = BasicBlock::Create(module->getContext(), "foundImageNull", function, nullptr);
410 colorDepthBlock = BasicBlock::Create(module->getContext(), "colorDepth", function, nullptr);
411
412 Value *imageValue = new LoadInst(foundImageVariable, "foundImage", false, widthHeightBlock);
413 ICmpInst *imageNotNull = new ICmpInst(*widthHeightBlock, ICmpInst::ICMP_NE, imageValue, nullImageValue, "");
414 BranchInst::Create(imageNotNullBlock, imageNullBlock, imageNotNull, widthHeightBlock);
415
416 widthValue = VuoCompilerCodeGenUtilities::generateGetStructPointerElement(module, imageNotNullBlock, imageValue, 3);
417 heightValue = VuoCompilerCodeGenUtilities::generateGetStructPointerElement(module, imageNotNullBlock, imageValue, 4);
418 BranchInst::Create(colorDepthBlock, imageNotNullBlock);
419
420 new StoreInst(nullImageValue, outputImagePointer, imageNullBlock);
421 BranchInst::Create(finalBlock, imageNullBlock);
422 }
423
424 // Set colorDepth…
425
426 Value *colorDepthValue = nullptr;
427 if (colorDepthInputPort)
428 {
429 // … from the input port value if it exists.
430
431 colorDepthValue = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, indexOfParameter[colorDepthInputPort]);
432 }
433 else
434 {
435 // … to the first non-NULL image's VuoImage_getColorDepth().
436 // If no non-NULL image, default to VuoImageColorDepth_8.
437
438 VuoCompilerType *vuoColorDepthType = vuoTypes["VuoImageColorDepth"];
439 if (!isTypeFound(vuoColorDepthType, issues))
440 return;
441
442 Type *llvmColorDepthType = getFunctionParameterType(vuoColorDepthType, issues);
443 if (! llvmColorDepthType)
444 return;
445
446 AllocaInst *colorDepthVariable = new AllocaInst(llvmColorDepthType, 0, "colorDepthVar", colorDepthBlock);
447
448 Value *defaultColorDepthValue = ConstantInt::get(llvmColorDepthType, 0);
449 new StoreInst(defaultColorDepthValue, colorDepthVariable, colorDepthBlock);
450
451 BasicBlock *imageNotNullBlock = BasicBlock::Create(module->getContext(), "foundImageNotNull", function, nullptr);
452 BasicBlock *loadColorDepthBlock = BasicBlock::Create(module->getContext(), "loadColorDepth", function, nullptr);
453
454 Value *imageValue = new LoadInst(foundImageVariable, "foundImage", false, colorDepthBlock);
455 ICmpInst *imageNotNull = new ICmpInst(*colorDepthBlock, ICmpInst::ICMP_NE, imageValue, nullImageValue, "");
456 BranchInst::Create(imageNotNullBlock, loadColorDepthBlock, imageNotNull, colorDepthBlock);
457
458 Function *colorDepthFunction = VuoCompilerCodeGenUtilities::getVuoImageGetColorDepthFunction(module);
459 Value *imageValueArg = new BitCastInst(imageValue, colorDepthFunction->getFunctionType()->getParamType(0), "", imageNotNullBlock);
460 Value *imageColorDepthValue = CallInst::Create(colorDepthFunction, imageValueArg, "colorDepth", imageNotNullBlock);
461 new StoreInst(imageColorDepthValue, colorDepthVariable, imageNotNullBlock);
462 BranchInst::Create(loadColorDepthBlock, imageNotNullBlock);
463
464 colorDepthValue = new LoadInst(colorDepthVariable, "colorDepth", false, loadColorDepthBlock);
465
466 colorDepthBlock = loadColorDepthBlock;
467 }
468
469 // Set uniforms.
470
471 BasicBlock *setUniformsBlock = colorDepthBlock;
472
473 for (VuoPort *inputPort : inputPorts)
474 {
475 // Don't provide uniforms for inputs applied when rendering the image (vuoWidth, vuoHeight, vuoColorDepth).
476 if (inputPort == widthInputPort || inputPort == heightInputPort || inputPort == colorDepthInputPort)
477 continue;
478
479 // VuoShader_setUniform_<type>(*instance, key, value);
480
481 VuoType *portDataType = static_cast<VuoCompilerPort *>(inputPort->getCompiler())->getDataVuoType();
482 Function *setUniformFunction = VuoCompilerCodeGenUtilities::getVuoShaderSetUniformFunction(module, portDataType ? portDataType->getCompiler() : vuoTypes["VuoBoolean"]);
483
484 Value *instanceDataValue_setUniform = new BitCastInst(instanceDataValue, setUniformFunction->getFunctionType()->getParamType(0), "", setUniformsBlock);
485
486 string portName = (inputPort == timeInputPort ? "TIME" : inputPort->getClass()->getName());
487 Value *portNameValue = constantsCache->get(portName);
488
489 Value *portDataArg = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, indexOfParameter[inputPort]);
490 Value *secondPortDataArg = nullptr;
491 bool hasSecondParam = (setUniformFunction->getFunctionType()->getNumParams() == 4);
492 if (hasSecondParam)
493 secondPortDataArg = VuoCompilerCodeGenUtilities::getArgumentAtIndex(function, indexOfParameter[inputPort] + 1);
494
495 // Some ISF shaders expect their `point2D` inputs in shader2DRect (pixel) coordinates.
496 if (portDataType && portDataType->getModuleKey() == "VuoPoint2d")
497 {
498 bool scaleToSamplerRect = false;
499 json_object *j;
500 if (json_object_object_get_ex(detailsForPorts[inputPort], "scaleToSamplerRect", &j))
501 scaleToSamplerRect = json_object_get_boolean(j);
502
503 if (scaleToSamplerRect)
504 {
505 // value = VuoShader_samplerRectCoordinatesFromNormalizedCoordinates(value, width, height);
507
508 vector<Value *> coordinateArgs;
509 // On arm64, VuoPoint2d is lowered to `<2 x float>` when it's an argument to the nodeInstanceEvent function,
510 // yet it's lowered to `double` when it's an argument to the VuoShader_samplerRectCoordinatesFromNormalizedCoordinates function.
511 // Explicitly casting avoids LLVM's `Calling a function with a bad signature` assertion.
512 coordinateArgs.push_back(new BitCastInst(portDataArg, coordinateFunction->getFunctionType()->getParamType(0), "point2dCasted", setUniformsBlock));
513 coordinateArgs.push_back(widthValue);
514 coordinateArgs.push_back(heightValue);
515 portDataArg = CallInst::Create(coordinateFunction, coordinateArgs, "", setUniformsBlock);
516 }
517 }
518
519 portDataArg = VuoCompilerCodeGenUtilities::generateTypeCast(module, setUniformsBlock, portDataArg, setUniformFunction->getFunctionType()->getParamType(2));
520
521 vector<Value *> setUniformArgs;
522 setUniformArgs.push_back(instanceDataValue_setUniform);
523 setUniformArgs.push_back(portNameValue);
524 setUniformArgs.push_back(portDataArg);
525 if (hasSecondParam)
526 setUniformArgs.push_back(secondPortDataArg);
527 CallInst::Create(setUniformFunction, setUniformArgs, "", setUniformsBlock);
528 }
529
530 // *outputImage = VuoImageRenderer_render(*instance, width, height, colorDepth);
531
532 BasicBlock *renderBlock = setUniformsBlock;
533
535
536 Value *instanceDataValue_render = new BitCastInst(instanceDataValue, renderFunction->getFunctionType()->getParamType(0), "", renderBlock);
537
538 vector<Value *> renderArgs;
539 renderArgs.push_back(instanceDataValue_render);
540 renderArgs.push_back(widthValue);
541 renderArgs.push_back(heightValue);
542 renderArgs.push_back(colorDepthValue);
543 Value *renderedImageValue = CallInst::Create(renderFunction, renderArgs, "", renderBlock);
544
545 Type *outputImageType = static_cast<PointerType *>( outputImagePointer->getType() )->getElementType();
546 Value *renderedImageValueArg = new BitCastInst(renderedImageValue, outputImageType, "", renderBlock);
547
548 new StoreInst(renderedImageValueArg, outputImagePointer, renderBlock);
549
550 BranchInst::Create(finalBlock, renderBlock);
551
552 ReturnInst::Create(module->getContext(), finalBlock);
553}
554
555bool VuoIsfModuleCompiler::isTypeFound(VuoCompilerType *type, VuoCompilerIssues *issues)
556{
557 if (!type)
558 {
559 string moduleKey = type->getBase()->getModuleKey();
560 VuoCompilerIssue issue(VuoCompilerIssue::Error, "compiling ISF node class", "", "Couldn't find type " + moduleKey + ".", "");
561 issues->append(issue);
562 return false;
563 }
564
565 return true;
566}
567
568Type * VuoIsfModuleCompiler::getFunctionParameterType(VuoCompilerType *type, VuoCompilerIssues *issues)
569{
570 vector<Type *> params = type->getFunctionParameterTypes();
571 if (params.size() != 1)
572 {
573 string moduleKey = type->getBase()->getModuleKey();
574 ostringstream details;
575 details << moduleKey << " is lowered to " << params.size() << " parameters; expected 1.";
576 VuoCompilerIssue issue(VuoCompilerIssue::Error, "compiling ISF node class", "", moduleKey + " has an unsupported format.", details.str());
577 issues->append(issue);
578 return nullptr;
579 }
580
581 return params[0];
582}