16void __attribute__((constructor)) VuoIsfModuleCompiler::init()
29 this->moduleKey = moduleKey;
77 string summary =
"Failed to parse shader";
78 string details = shaderIssue.message;
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");
96 vuoTypesUsed.push_back(shaderInputPort.vuoTypeName);
98 map<string, VuoCompilerType *> vuoTypes;
99 for (
string t : vuoTypesUsed)
100 vuoTypes[t] = getVuoType(t);
104 __block Module *module;
110 if (shaderFile->
type() == VuoShaderFile::GLSLImageFilter
111 || shaderFile->
type() == VuoShaderFile::GLSLImageGenerator
112 || shaderFile->
type() == VuoShaderFile::GLSLImageTransition)
114 generateMetadata(module);
115 generateNodeInstanceInitFunction(module, &constantsCache, vuoTypes, issues);
116 generateNodeInstanceEventFunction(module, &constantsCache, vuoTypes, issues);
118 else if (shaderFile->
type() == VuoShaderFile::GLSLObjectRenderer)
122 else if (shaderFile->
type() == VuoShaderFile::GLSLObjectFilter)
135void VuoIsfModuleCompiler::generateMetadata(Module *module)
152 if (!isTypeFound(vuoShaderType, issues))
155 Type *llvmShaderType = getFunctionParameterType(vuoShaderType, issues);
159 map<VuoPort *, size_t> indexOfParameterInit;
162 llvmShaderType, vector<VuoPort *>(),
163 indexOfParameterInit, constantsCache);
165 BasicBlock *block = &(function->getEntryBlock());
170 Value *shaderNameValue = constantsCache->
get(shaderFile->
name());
171 Value *shaderValue = CallInst::Create(makeFunction, shaderNameValue,
"s", block);
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);
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);
195 Value *shaderValueAsReturn =
new BitCastInst(shaderValue, function->getReturnType(),
"", block);
196 ReturnInst::Create(module->getContext(), shaderValueAsReturn, block);
205 vector<VuoPort *> inputPorts;
206 vector<VuoPort *> outputPorts;
207 map<VuoPort *, json_object *> detailsForPorts;
209 auto addInputPort = [&inputPorts, &detailsForPorts, &vuoTypes] (
const string &portName,
const string &typeName,
json_object *details)
211 VuoCompilerType *type = typeName ==
"event" ? NULL : vuoTypes[typeName];
213 inputPorts.push_back(inputPort->
getBase());
214 detailsForPorts[inputPort->
getBase()] = details;
217 auto addOutputPort = [&outputPorts, &detailsForPorts, &vuoTypes] (
const string &portName,
const string &typeName,
json_object *details)
221 outputPorts.push_back(outputPort->
getBase());
222 detailsForPorts[outputPort->
getBase()] = details;
225 VuoPort *widthInputPort =
nullptr;
226 VuoPort *heightInputPort =
nullptr;
227 auto addWidthHeightInputPorts = [&inputPorts, &addInputPort, &widthInputPort, &heightInputPort] (void)
232 json_object *widthDetails = json_object_new_object();
233 json_object_object_add(widthDetails,
"name",
VuoText_getJson(
"Width"));
237 json_object *heightDetails = json_object_new_object();
238 json_object_object_add(heightDetails,
"name",
VuoText_getJson(
"Height"));
243 addInputPort(
"vuoWidth",
"VuoInteger", widthDetails);
244 if (! widthInputPort)
245 widthInputPort = inputPorts.back();
246 addInputPort(
"vuoHeight",
"VuoInteger", heightDetails);
247 if (! heightInputPort)
248 heightInputPort = inputPorts.back();
251 VuoPort *timeInputPort =
nullptr;
259 json_object_object_add(details,
"suggestedStep",
VuoReal_getJson(0.1));
261 addInputPort(
"vuoTime",
"VuoReal", details);
262 timeInputPort = inputPorts.back();
265 VuoPort *colorDepthInputPort =
nullptr;
266 bool hasImageInputPort =
false;
269 if (shaderInputPort.vuoTypeName ==
"VuoSize")
271 addWidthHeightInputPorts();
273 else if (shaderInputPort.vuoTypeName ==
"VuoImageColorDepth")
277 json_object *details = shaderInputPort.vuoPortDetails;
278 json_object_object_add(details,
"name",
VuoText_getJson(
"Color Depth"));
281 addInputPort(
"vuoColorDepth", shaderInputPort.vuoTypeName, details);
283 if (! colorDepthInputPort)
284 colorDepthInputPort = inputPorts.back();
290 if (shaderInputPort.vuoTypeName ==
"VuoBoolean")
293 json_object_object_get_ex(shaderInputPort.vuoPortDetails,
"default", &defaultValue);
295 json_object_object_add(shaderInputPort.vuoPortDetails,
"default", defaultValue);
298 addInputPort(shaderInputPort.key, shaderInputPort.vuoTypeName, shaderInputPort.vuoPortDetails);
300 if (shaderInputPort.vuoTypeName ==
"VuoImage")
301 hasImageInputPort =
true;
305 if (! hasImageInputPort && ! widthInputPort && ! heightInputPort)
307 addWidthHeightInputPorts();
314 addOutputPort(shaderOutputPort.key,
"VuoImage", shaderOutputPort.vuoPortDetails);
318 if (!isTypeFound(vuoShaderType, issues))
321 Type *llvmShaderType = getFunctionParameterType(vuoShaderType, issues);
325 map<VuoPort *, size_t> indexOfParameter;
326 map<VuoPort *, size_t> indexOfEventParameter;
329 llvmShaderType, inputPorts, outputPorts,
330 detailsForPorts, map<VuoPort *, string>(),
331 map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
332 indexOfParameter, indexOfEventParameter, constantsCache);
334 BasicBlock *initialBlock = &(function->getEntryBlock());
338 Value *instanceDataValue =
new LoadInst(instanceDataPointerValue,
"instanceData",
false, initialBlock);
342 BasicBlock *findImageBlock = initialBlock;
343 BasicBlock *widthHeightBlock = BasicBlock::Create(module->getContext(),
"widthHeight", function,
nullptr);
346 if (!isTypeFound(vuoImageType, issues))
349 Type *llvmImageType = getFunctionParameterType(vuoImageType, issues);
353 ConstantPointerNull *nullImageValue = ConstantPointerNull::get(
static_cast<PointerType *
>(llvmImageType));
355 AllocaInst *foundImageVariable =
new AllocaInst(llvmImageType, 0,
"foundImageVar", findImageBlock);
356 new StoreInst(nullImageValue, foundImageVariable, findImageBlock);
358 BasicBlock *currBlock = findImageBlock;
359 for (
VuoPort *inputPort : inputPorts)
364 BasicBlock *imageNotNullBlock = BasicBlock::Create(module->getContext(),
"imageNotNull", function,
nullptr);
365 BasicBlock *imageNullBlock = BasicBlock::Create(module->getContext(),
"imageNull", function,
nullptr);
368 ICmpInst *imageNotNull =
new ICmpInst(*currBlock, ICmpInst::ICMP_NE, imageValue, nullImageValue,
"");
369 BranchInst::Create(imageNotNullBlock, imageNullBlock, imageNotNull, currBlock);
371 new StoreInst(imageValue, foundImageVariable, imageNotNullBlock);
372 BranchInst::Create(widthHeightBlock, imageNotNullBlock);
374 currBlock = imageNullBlock;
378 BranchInst::Create(widthHeightBlock, currBlock);
382 BasicBlock *colorDepthBlock =
nullptr;
383 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final", function,
nullptr);
385 Value *widthValue =
nullptr;
386 Value *heightValue =
nullptr;
387 if (widthInputPort && heightInputPort)
394 colorDepthBlock = widthHeightBlock;
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);
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);
411 BranchInst::Create(colorDepthBlock, imageNotNullBlock);
413 new StoreInst(nullImageValue, outputImagePointer, imageNullBlock);
414 BranchInst::Create(finalBlock, imageNullBlock);
419 Value *colorDepthValue =
nullptr;
420 if (colorDepthInputPort)
432 if (!isTypeFound(vuoColorDepthType, issues))
435 Type *llvmColorDepthType = getFunctionParameterType(vuoColorDepthType, issues);
436 if (! llvmColorDepthType)
439 AllocaInst *colorDepthVariable =
new AllocaInst(llvmColorDepthType, 0,
"colorDepthVar", colorDepthBlock);
441 Value *defaultColorDepthValue = ConstantInt::get(llvmColorDepthType, 0);
442 new StoreInst(defaultColorDepthValue, colorDepthVariable, colorDepthBlock);
444 BasicBlock *imageNotNullBlock = BasicBlock::Create(module->getContext(),
"foundImageNotNull", function,
nullptr);
445 BasicBlock *loadColorDepthBlock = BasicBlock::Create(module->getContext(),
"loadColorDepth", function,
nullptr);
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);
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);
457 colorDepthValue =
new LoadInst(colorDepthVariable,
"colorDepth",
false, loadColorDepthBlock);
459 colorDepthBlock = loadColorDepthBlock;
464 BasicBlock *setUniformsBlock = colorDepthBlock;
466 for (
VuoPort *inputPort : inputPorts)
469 if (inputPort == widthInputPort || inputPort == heightInputPort || inputPort == colorDepthInputPort)
477 Value *instanceDataValue_setUniform =
new BitCastInst(instanceDataValue, setUniformFunction->getFunctionType()->getParamType(0),
"", setUniformsBlock);
479 string portName = (inputPort == timeInputPort ?
"TIME" : inputPort->getClass()->getName());
480 Value *portNameValue = constantsCache->
get(portName);
483 Value *secondPortDataArg =
nullptr;
484 bool hasSecondParam = (setUniformFunction->getFunctionType()->getNumParams() == 4);
489 if (portDataType && portDataType->
getModuleKey() ==
"VuoPoint2d")
491 bool scaleToSamplerRect =
false;
493 if (json_object_object_get_ex(detailsForPorts[inputPort],
"scaleToSamplerRect", &j))
494 scaleToSamplerRect = json_object_get_boolean(j);
496 if (scaleToSamplerRect)
501 vector<Value *> coordinateArgs;
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);
514 vector<Value *> setUniformArgs;
515 setUniformArgs.push_back(instanceDataValue_setUniform);
516 setUniformArgs.push_back(portNameValue);
517 setUniformArgs.push_back(portDataArg);
519 setUniformArgs.push_back(secondPortDataArg);
520 CallInst::Create(setUniformFunction, setUniformArgs,
"", setUniformsBlock);
525 BasicBlock *renderBlock = setUniformsBlock;
529 Value *instanceDataValue_render =
new BitCastInst(instanceDataValue, renderFunction->getFunctionType()->getParamType(0),
"", renderBlock);
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);
538 Type *outputImageType =
static_cast<PointerType *
>( outputImagePointer->getType() )->getElementType();
539 Value *renderedImageValueArg =
new BitCastInst(renderedImageValue, outputImageType,
"", renderBlock);
541 new StoreInst(renderedImageValueArg, outputImagePointer, renderBlock);
543 BranchInst::Create(finalBlock, renderBlock);
545 ReturnInst::Create(module->getContext(), finalBlock);
564 if (params.size() != 1)
567 ostringstream details;
568 details << moduleKey <<
" is lowered to " << params.size() <<
" parameters; expected 1.";