// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto.  Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#include <omni/graph/core/GpuArray.h>

#include <OgnTutorialCudaDataCpuDatabase.h>

// This function exercises referencing of array data on the GPU.
// The CUDA code takes its own "float3" data types, which are castable equivalents to the generated GfVec3f.
// The GpuArray/ConstGpuArray wrappers isolate the GPU pointers from the CPU code.
extern "C" void applyDeformationCpuToGpu(pxr::GfVec3f* outputPoints,
                                         const pxr::GfVec3f* inputPoints,
                                         const pxr::GfVec3f* multiplier,
                                         size_t numberOfPoints);

// This node runs a couple of algorithms on the GPU, while accessing parameters from the CPU
class OgnTutorialCudaDataCpu
{
public:
    static bool compute(OgnTutorialCudaDataCpuDatabase& db)
    {
        size_t numberOfPoints = db.inputs.points.size();
        db.outputs.points.resize(numberOfPoints);
        if (numberOfPoints > 0)
        {
            // The main point to note here is how the pointer can be dereferenced on the CPU side, whereas normally
            // you would have to send it to the GPU for dereferencing. (The long term purpose of the latter is to make
            // it more efficient to handle arrays-of-arrays on the GPU, however since that is not yet implemented
            // we can get away with a single dereference here.)
            applyDeformationCpuToGpu(*db.outputs.points(), *db.inputs.points.gpu(), db.inputs.multiplier(), numberOfPoints);

            // Just as a test now also reference the points as CPU data to ensure the value casts correctly
            const float* pointsAsCpu = reinterpret_cast<const float*>(db.inputs.points.cpu().data());
        }

        return true;
    }
};

REGISTER_OGN_NODE()
