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