Hi Malcom,
after having trouble with multiple inputs I started again with a fresh CudaTop example.
In my header i just added a second surfaceobject:
cudaSurfaceObject_t myInputSurface;
cudaSurfaceObject_t myInputSurface2;
And then i added a bunch of debug messages to my execute:
void CudaTOP::execute(TOP_Output* output, const OP_Inputs* inputs, void* reserved){
myError = nullptr;
myExecuteCount++;
TOP_CUDAOutputInfo info;
info.textureDesc.width = 256;
info.textureDesc.height = 256;
info.textureDesc.texDim = OP_TexDim::e2D;
info.textureDesc.pixelFormat = OP_PixelFormat::BGRA8Fixed;
info.stream = myStream;
float ratio = static_cast<float>(info.textureDesc.height) / static_cast<float>(info.textureDesc.width);
const OP_CUDAArrayInfo* inputArray = nullptr;
const OP_CUDAArrayInfo* inputArray2 = nullptr;
std::cout << "Number of inputs: " << inputs->getNumInputs() << std::endl;
if (inputs->getNumInputs() > 0)
{
const OP_TOPInput* topInput = inputs->getInputTOP(0);
if (!topInput)
{
std::cout << "Input 1 TOP is null" << std::endl;
}
else
{
std::cout << "Input 1 TOP acquired, width: " << topInput->textureDesc.width
<< " height: " << topInput->textureDesc.height << std::endl;
// Make our output texture match our input texture.
info.textureDesc = topInput->textureDesc;
OP_CUDAAcquireInfo acquireInfo;
acquireInfo.stream = myStream;
inputArray = topInput->getCUDAArray(acquireInfo, nullptr);
// Validate first input CUDA array acquisition
if (!inputArray)
{
std::cout << "Failed to acquire CUDA array for input 1" << std::endl;
}
else
{
std::cout << "Input 1 CUDA array acquired (cudaArray will be filled after beginCUDAOperations)" << std::endl;
}
}
}
// Get second input if available
if (inputs->getNumInputs() > 1)
{
const OP_TOPInput* topInput2 = inputs->getInputTOP(1);
if (!topInput2)
{
std::cout << "Input 2 TOP is null" << std::endl;
}
else
{
std::cout << "Input 2 TOP acquired, width: " << topInput2->textureDesc.width
<< " height: " << topInput2->textureDesc.height << std::endl;
OP_CUDAAcquireInfo acquireInfo2;
acquireInfo2.stream = myStream;
inputArray2 = topInput2->getCUDAArray(acquireInfo2, nullptr);
// Validate second input CUDA array acquisition
if (!inputArray2)
{
std::cout << "Failed to acquire CUDA array for input 2" << std::endl;
}
else
{
std::cout << "Input 2 CUDA array acquired (cudaArray will be filled after beginCUDAOperations)" << std::endl;
}
}
}
// Primary output
const OP_CUDAArrayInfo* outputInfo = output->createCUDAArray(info, nullptr);
if (!outputInfo)
return;
// Output to a second color buffer, with a different resolution. Use a Render Select TOP
// to get this output.
TOP_CUDAOutputInfo auxInfo;
auxInfo.textureDesc.pixelFormat = OP_PixelFormat::BGRA8Fixed;
auxInfo.textureDesc.width = 1280;
auxInfo.textureDesc.height = 720;
auxInfo.textureDesc.texDim = OP_TexDim::e2D;
auxInfo.colorBufferIndex = 1;
auxInfo.stream = myStream;
const OP_CUDAArrayInfo* auxOutputInfo = output->createCUDAArray(auxInfo, nullptr);
if (!auxOutputInfo)
return;
// All calls to the 'inputs' need to be made before beginCUDAOperations() is called
double color1[3];
inputs->getParDouble3("Color1", color1[0], color1[1], color1[2]);
double color2[3];
inputs->getParDouble3("Color2", color2[0], color2[1], color2[2]);
// Now that we have gotten all of the pointers to the OP_CUDAArrayInfos that we may want, we can tell the context
// that we are going to start doing CUDA operations. This will cause the cudaArray members of the OP_CUDAArrayInfo
// to get filled in with valid addresses.
if (!myContext->beginCUDAOperations(nullptr))
return;
// Now validate the CUDA arrays after beginCUDAOperations has filled them in
if (inputArray)
{
if (!inputArray->cudaArray)
{
std::cout << "WARNING: Input 1 cudaArray is null after beginCUDAOperations" << std::endl;
// Set to nullptr so we don't try to use it
inputArray = nullptr;
}
else
{
std::cout << "Input 1 cudaArray is valid after beginCUDAOperations" << std::endl;
}
}
if (inputArray2)
{
if (!inputArray2->cudaArray)
{
std::cout << "WARNING: Input 2 cudaArray is null after beginCUDAOperations - will not be used" << std::endl;
// Set to nullptr so we don't try to use it
//inputArray2 = nullptr;
}
else
{
std::cout << "Input 2 cudaArray is valid after beginCUDAOperations" << std::endl;
}
}
// Setup output surface and validate
if (outputInfo && outputInfo->cudaArray)
{
setupCudaSurface(&myOutputSurfaces[0], outputInfo->cudaArray);
if (!myOutputSurfaces[0])
{
std::cout << "Failed to create surface object for primary output" << std::endl;
}
else
{
std::cout << "Primary output surface created successfully" << std::endl;
}
}
else
{
std::cout << "Failed to create output CUDA array" << std::endl;
myError = "Failed to create output CUDA array";
return;
}
// Setup first input surface if available and validate
if (inputArray)
{
setupCudaSurface(&myInputSurface, inputArray->cudaArray);
if (!myInputSurface)
{
std::cout << "Failed to create surface object for input 1" << std::endl;
}
else
{
std::cout << "Input 1 surface created successfully" << std::endl;
}
}
else
{
if (myInputSurface)
{
cudaDestroySurfaceObject(myInputSurface);
myInputSurface = 0;
}
}
// Setup second input surface if available and validate
if (inputArray2)
{
setupCudaSurface(&myInputSurface2, inputArray2->cudaArray);
if (!myInputSurface2)
{
std::cout << "Failed to create surface object for input 2" << std::endl;
}
else
{
std::cout << "Input 2 surface created successfully" << std::endl;
}
}
else
{
if (myInputSurface2)
{
cudaDestroySurfaceObject(myInputSurface2);
myInputSurface2 = 0;
}
}
// Validate surfaces before passing to kernel
if (!myOutputSurfaces[info.colorBufferIndex])
{
std::cout << "Invalid output surface for primary buffer" << std::endl;
myError = "Invalid output surface for primary buffer";
return;
}
float4 c;
c.x = (float)color1[0];
c.y = (float)color1[1];
c.z = (float)color1[2];
c.w = 1.0f;
doCUDAOperation(info.textureDesc.width, info.textureDesc.height, info.textureDesc.depth, info.textureDesc.texDim, c, myInputSurface, myInputSurface2, myOutputSurfaces[info.colorBufferIndex], myStream);
// Setup auxiliary output surface and validate
if (auxOutputInfo && auxOutputInfo->cudaArray)
{
setupCudaSurface(&myOutputSurfaces[auxInfo.colorBufferIndex], auxOutputInfo->cudaArray);
if (!myOutputSurfaces[auxInfo.colorBufferIndex])
{
std::cout << "Failed to create surface object for auxiliary output" << std::endl;
myError = "Invalid output surface for auxiliary buffer";
return;
}
else
{
std::cout << "Auxiliary output surface created successfully" << std::endl;
}
}
else
{
std::cout << "Failed to create auxiliary output CUDA array" << std::endl;
myError = "Failed to create auxiliary output CUDA array";
return;
}
c.x = (float)color2[0];
c.y = (float)color2[1];
c.z = (float)color2[2];
c.w = 1.0f;
//doCUDAOperation(auxInfo.textureDesc.width, auxInfo.textureDesc.height, auxInfo.textureDesc.depth, auxInfo.textureDesc.texDim, c, 0, myOutputSurfaces[auxInfo.colorBufferIndex], myStream);
myContext->endCUDAOperations(nullptr);
}
My Output is as follows:
Number of inputs: 2
Input 1 TOP acquired, width: 1280 height: 720
Input 1 CUDA array acquired (cudaArray will be filled after beginCUDAOperations)
Input 2 TOP acquired, width: 1280 height: 720
Input 2 CUDA array acquired (cudaArray will be filled after beginCUDAOperations)
Input 1 cudaArray is valid after beginCUDAOperations
WARNING: Input 2 cudaArray is null after beginCUDAOperations - will not be used
Primary output surface created successfully
Input 1 surface created successfully
Failed to create surface object for input 2
Auxiliary output surface created successfully
I have done multiple output CudaTop multiple times, this is my first try with multiple inputs.
I dont know what i am missing.
Thanks a lot for taking a look!!!