18void __attribute__((constructor)) VuoIsfModuleCompiler::init()
28VuoIsfModuleCompiler::VuoIsfModuleCompiler(
const string &moduleKey,
const string &sourcePath,
38VuoModuleCompiler * VuoIsfModuleCompiler::newModuleCompiler(
const string &moduleKey,
const string &sourcePath,
41 string dir, file, ext;
54 this->sourceCode = sourceCode;
64 string dir, file, ext;
84 shared_ptr<VuoShaderIssues> shaderIssues = std::make_shared<VuoShaderIssues>();
100 vector<string> vuoTypesUsed = {
"VuoShader",
"VuoImage",
"VuoImageColorDepth",
"VuoReal",
"VuoInteger",
"VuoBoolean" };
102 vuoTypesUsed.push_back(shaderInputPort.vuoTypeName);
104 for (
const string &typeName : vuoTypesUsed)
109 __block Module *
module;
112 module = new Module(moduleKey, *VuoCompiler::globalLLVMContext);
115 if (shaderFile->
type() == VuoShaderFile::GLSLImageFilter
116 || shaderFile->
type() == VuoShaderFile::GLSLImageGenerator
117 || shaderFile->
type() == VuoShaderFile::GLSLImageTransition)
119 generateMetadata(module);
120 generateNodeInstanceInitFunction(module, &constantsCache,
vuoTypes, issues);
121 generateNodeInstanceEventFunction(module, &constantsCache,
vuoTypes, issues);
123 else if (shaderFile->
type() == VuoShaderFile::GLSLObjectRenderer)
127 else if (shaderFile->
type() == VuoShaderFile::GLSLObjectFilter)
134 results.module =
module;
142void VuoIsfModuleCompiler::generateMetadata(Module *module)
159 if (!isTypeFound(vuoShaderType, issues))
162 Type *llvmShaderType = getFunctionParameterType(vuoShaderType, issues);
166 map<VuoPort *, size_t> indexOfParameterInit;
169 llvmShaderType, vector<VuoPort *>(),
170 indexOfParameterInit, constantsCache);
172 BasicBlock *block = &(function->getEntryBlock());
177 Value *shaderNameValue = constantsCache->
get(shaderFile->
name());
178 Value *shaderValue = CallInst::Create(makeFunction, shaderNameValue,
"s", block);
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);
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);
202 Value *shaderValueAsReturn =
new BitCastInst(shaderValue, function->getReturnType(),
"", block);
203 ReturnInst::Create(module->getContext(), shaderValueAsReturn, block);
212 vector<VuoPort *> inputPorts;
213 vector<VuoPort *> outputPorts;
214 map<VuoPort *, json_object *> detailsForPorts;
216 auto addInputPort = [&inputPorts, &detailsForPorts, &
vuoTypes] (
const string &portName,
const string &typeName, json_object *details)
220 inputPorts.push_back(inputPort->
getBase());
221 detailsForPorts[inputPort->
getBase()] = details;
224 auto addOutputPort = [&outputPorts, &detailsForPorts, &
vuoTypes] (
const string &portName,
const string &typeName, json_object *details)
228 outputPorts.push_back(outputPort->
getBase());
229 detailsForPorts[outputPort->
getBase()] = details;
232 VuoPort *widthInputPort =
nullptr;
233 VuoPort *heightInputPort =
nullptr;
234 auto addWidthHeightInputPorts = [&inputPorts, &addInputPort, &widthInputPort, &heightInputPort] (void)
239 json_object *widthDetails = json_object_new_object();
240 json_object_object_add(widthDetails,
"name",
VuoText_getJson(
"Width"));
244 json_object *heightDetails = json_object_new_object();
245 json_object_object_add(heightDetails,
"name",
VuoText_getJson(
"Height"));
250 addInputPort(
"vuoWidth",
"VuoInteger", widthDetails);
251 if (! widthInputPort)
252 widthInputPort = inputPorts.back();
253 addInputPort(
"vuoHeight",
"VuoInteger", heightDetails);
254 if (! heightInputPort)
255 heightInputPort = inputPorts.back();
258 VuoPort *timeInputPort =
nullptr;
263 json_object *details = json_object_new_object();
266 json_object_object_add(details,
"suggestedStep",
VuoReal_getJson(0.1));
268 addInputPort(
"vuoTime",
"VuoReal", details);
269 timeInputPort = inputPorts.back();
272 VuoPort *colorDepthInputPort =
nullptr;
273 bool hasImageInputPort =
false;
276 if (shaderInputPort.vuoTypeName ==
"VuoSize")
278 addWidthHeightInputPorts();
280 else if (shaderInputPort.vuoTypeName ==
"VuoImageColorDepth")
284 json_object *details = shaderInputPort.vuoPortDetails;
285 json_object_object_add(details,
"name",
VuoText_getJson(
"Color Depth"));
288 addInputPort(
"vuoColorDepth", shaderInputPort.vuoTypeName, details);
290 if (! colorDepthInputPort)
291 colorDepthInputPort = inputPorts.back();
297 if (shaderInputPort.vuoTypeName ==
"VuoBoolean")
299 json_object *defaultValue = NULL;
300 json_object_object_get_ex(shaderInputPort.vuoPortDetails,
"default", &defaultValue);
302 json_object_object_add(shaderInputPort.vuoPortDetails,
"default", defaultValue);
305 addInputPort(shaderInputPort.key, shaderInputPort.vuoTypeName, shaderInputPort.vuoPortDetails);
307 if (shaderInputPort.vuoTypeName ==
"VuoImage")
308 hasImageInputPort =
true;
312 if (! hasImageInputPort && ! widthInputPort && ! heightInputPort)
314 addWidthHeightInputPorts();
321 addOutputPort(shaderOutputPort.key,
"VuoImage", shaderOutputPort.vuoPortDetails);
325 if (!isTypeFound(vuoShaderType, issues))
328 Type *llvmShaderType = getFunctionParameterType(vuoShaderType, issues);
332 map<VuoPort *, size_t> indexOfParameter;
333 map<VuoPort *, size_t> indexOfEventParameter;
336 llvmShaderType, inputPorts, outputPorts,
337 detailsForPorts, map<VuoPort *, string>(),
338 map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
339 indexOfParameter, indexOfEventParameter, constantsCache);
341 BasicBlock *initialBlock = &(function->getEntryBlock());
345 Value *instanceDataValue =
new LoadInst(instanceDataPointerValue,
"instanceData",
false, initialBlock);
349 BasicBlock *findImageBlock = initialBlock;
350 BasicBlock *widthHeightBlock = BasicBlock::Create(module->getContext(),
"widthHeight", function,
nullptr);
353 if (!isTypeFound(vuoImageType, issues))
356 Type *llvmImageType = getFunctionParameterType(vuoImageType, issues);
360 ConstantPointerNull *nullImageValue = ConstantPointerNull::get(
static_cast<PointerType *
>(llvmImageType));
362 AllocaInst *foundImageVariable =
new AllocaInst(llvmImageType, 0,
"foundImageVar", findImageBlock);
363 new StoreInst(nullImageValue, foundImageVariable, findImageBlock);
365 BasicBlock *currBlock = findImageBlock;
366 for (
VuoPort *inputPort : inputPorts)
371 BasicBlock *imageNotNullBlock = BasicBlock::Create(module->getContext(),
"imageNotNull", function,
nullptr);
372 BasicBlock *imageNullBlock = BasicBlock::Create(module->getContext(),
"imageNull", function,
nullptr);
375 ICmpInst *imageNotNull =
new ICmpInst(*currBlock, ICmpInst::ICMP_NE, imageValue, nullImageValue,
"");
376 BranchInst::Create(imageNotNullBlock, imageNullBlock, imageNotNull, currBlock);
378 new StoreInst(imageValue, foundImageVariable, imageNotNullBlock);
379 BranchInst::Create(widthHeightBlock, imageNotNullBlock);
381 currBlock = imageNullBlock;
385 BranchInst::Create(widthHeightBlock, currBlock);
389 BasicBlock *colorDepthBlock =
nullptr;
390 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final", function,
nullptr);
392 Value *widthValue =
nullptr;
393 Value *heightValue =
nullptr;
394 if (widthInputPort && heightInputPort)
401 colorDepthBlock = widthHeightBlock;
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);
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);
418 BranchInst::Create(colorDepthBlock, imageNotNullBlock);
420 new StoreInst(nullImageValue, outputImagePointer, imageNullBlock);
421 BranchInst::Create(finalBlock, imageNullBlock);
426 Value *colorDepthValue =
nullptr;
427 if (colorDepthInputPort)
439 if (!isTypeFound(vuoColorDepthType, issues))
442 Type *llvmColorDepthType = getFunctionParameterType(vuoColorDepthType, issues);
443 if (! llvmColorDepthType)
446 AllocaInst *colorDepthVariable =
new AllocaInst(llvmColorDepthType, 0,
"colorDepthVar", colorDepthBlock);
448 Value *defaultColorDepthValue = ConstantInt::get(llvmColorDepthType, 0);
449 new StoreInst(defaultColorDepthValue, colorDepthVariable, colorDepthBlock);
451 BasicBlock *imageNotNullBlock = BasicBlock::Create(module->getContext(),
"foundImageNotNull", function,
nullptr);
452 BasicBlock *loadColorDepthBlock = BasicBlock::Create(module->getContext(),
"loadColorDepth", function,
nullptr);
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);
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);
464 colorDepthValue =
new LoadInst(colorDepthVariable,
"colorDepth",
false, loadColorDepthBlock);
466 colorDepthBlock = loadColorDepthBlock;
471 BasicBlock *setUniformsBlock = colorDepthBlock;
473 for (
VuoPort *inputPort : inputPorts)
476 if (inputPort == widthInputPort || inputPort == heightInputPort || inputPort == colorDepthInputPort)
484 Value *instanceDataValue_setUniform =
new BitCastInst(instanceDataValue, setUniformFunction->getFunctionType()->getParamType(0),
"", setUniformsBlock);
486 string portName = (inputPort == timeInputPort ?
"TIME" : inputPort->getClass()->getName());
487 Value *portNameValue = constantsCache->
get(portName);
490 Value *secondPortDataArg =
nullptr;
491 bool hasSecondParam = (setUniformFunction->getFunctionType()->getNumParams() == 4);
496 if (portDataType && portDataType->
getModuleKey() ==
"VuoPoint2d")
498 bool scaleToSamplerRect =
false;
500 if (json_object_object_get_ex(detailsForPorts[inputPort],
"scaleToSamplerRect", &j))
501 scaleToSamplerRect = json_object_get_boolean(j);
503 if (scaleToSamplerRect)
508 vector<Value *> coordinateArgs;
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);
521 vector<Value *> setUniformArgs;
522 setUniformArgs.push_back(instanceDataValue_setUniform);
523 setUniformArgs.push_back(portNameValue);
524 setUniformArgs.push_back(portDataArg);
526 setUniformArgs.push_back(secondPortDataArg);
527 CallInst::Create(setUniformFunction, setUniformArgs,
"", setUniformsBlock);
532 BasicBlock *renderBlock = setUniformsBlock;
536 Value *instanceDataValue_render =
new BitCastInst(instanceDataValue, renderFunction->getFunctionType()->getParamType(0),
"", renderBlock);
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);
545 Type *outputImageType =
static_cast<PointerType *
>( outputImagePointer->getType() )->getElementType();
546 Value *renderedImageValueArg =
new BitCastInst(renderedImageValue, outputImageType,
"", renderBlock);
548 new StoreInst(renderedImageValueArg, outputImagePointer, renderBlock);
550 BranchInst::Create(finalBlock, renderBlock);
552 ReturnInst::Create(module->getContext(), finalBlock);
571 if (params.size() != 1)
574 ostringstream details;
575 details <<
moduleKey <<
" is lowered to " << params.size() <<
" parameters; expected 1.";