Is NvMedia2DFillNvSciSyncAttrList needed to use NvSciSyncObj with NvMedia2D?

Software Version
DRIVE OS Linux 6.0.8.1 and DriveWorks 5.10

Hardware Platform
DRIVE AGX Orin

Hi,

According to the documentation of NvMedia2DFillNvSciSyncAttrList, it sets NvSciSyncAttrKey_RequiredPerm and NvSciSyncAttrKey_PrimitiveInfo.

I try to manually fill a NvSciSyncAttrList with all the attributes that would be filled by NvMedia2DFillNvSciSyncAttrList:

// fill hwSignalerSyncAttrs
{
    /* If I uncomment, it works
    if(auto const error{NvMedia2DFillNvSciSyncAttrList(nvMedia2D, hwSignalerSyncAttrs.get(), NVMEDIA_SIGNALER)}; error != NVMEDIA_STATUS_OK)
    {
        LOG_ERR("Couldn't set NvSciSyncAttrList: %d", error);
        return {};
    }*/
    static constexpr bool cpuSignaler{false};
    static constexpr NvSciSyncAccessPerm hwPerm{NvSciSyncAccessPerm_SignalOnly};
    static constexpr NvSciSyncAttrValPrimitiveType hwPrimType[]{
        NvSciSyncAttrValPrimitiveType_Syncpoint,
        NvSciSyncAttrValPrimitiveType_SysmemSemaphore,
        NvSciSyncAttrValPrimitiveType_SysmemSemaphorePayload64b,
    };
    static constexpr NvSciBufPeerHwEngine hwEngines[]{
        NvSciBufPeerHwEngine{ NvSciBufHwEngName_Vic, NvSciBufPlatformName_Orin },
        NvSciBufPeerHwEngine{ NvSciBufHwEngName_MSENC, NvSciBufPlatformName_Orin },
        NvSciBufPeerHwEngine{ NvSciBufHwEngName_Gpu, NvSciBufPlatformName_Orin },
    };
    static std::vector<NvSciRmGpuId> const& gpuIds{getGpuIds()};

    if(gpuIds.empty())
    {
        LOG_ERR("Couldn't get GPU vector.");
        return {};
    }

    NvSciSyncAttrKeyValuePair hwKeyValuePairs[] = {
        { NvSciSyncAttrKey_NeedCpuAccess, &cpuSignaler, sizeof(cpuSignaler) },       
        { NvSciSyncAttrKey_RequiredPerm, &hwPerm, sizeof(hwPerm) },
        { NvSciSyncAttrKey_PrimitiveInfo, &hwPrimType, sizeof(hwPrimType) },
        { NvSciSyncAttrKey_GpuId, gpuIds.data(), sizeof(NvSciRmGpuId) * gpuIds.size() },
        { NvSciSyncAttrKey_PeerHwEngineArray, &hwEngines, sizeof(hwEngines) },
    };

    if(auto const error{NvSciSyncAttrListSetAttrs(hwSignalerSyncAttrs.get(), hwKeyValuePairs, sizeof(hwKeyValuePairs) / sizeof(hwKeyValuePairs))}; error != NvSciError_Success)
    {
        LOG_ERR("Couldn't set NvSciSyncAttrList: %d", error);
        return {};
    }
}

// fill waiterSyncAttrs
{
    /* If I uncomment, it works
    if(auto const error{NvMedia2DFillNvSciSyncAttrList(nvMedia2D, waiterSyncAttrs.get(), NVMEDIA_WAITER)}; error != NVMEDIA_STATUS_OK)
    {
        LOG_ERR("Couldn't set NvSciSyncAttrList: %d", error);
        return {};
    }*/
    static constexpr bool cpuWaiter{true};
    static constexpr NvSciSyncAccessPerm cpuPerm{NvSciSyncAccessPerm_WaitOnly};
    static constexpr NvSciSyncAttrValPrimitiveType cpuPrimType[]{
        NvSciSyncAttrValPrimitiveType_Syncpoint,
        NvSciSyncAttrValPrimitiveType_SysmemSemaphore,
        NvSciSyncAttrValPrimitiveType_SysmemSemaphorePayload64b,
    };
    static auto const& gpuIds{getGpuIds()};

    if(gpuIds.empty())
    {
        LOG_ERR("Couldn't get GPU vector.");
        return {};
    }

    NvSciSyncAttrKeyValuePair cpuWaiterKeyValuePairs[] = {
        { NvSciSyncAttrKey_NeedCpuAccess, &cpuWaiter, sizeof(cpuWaiter) },       
        { NvSciSyncAttrKey_RequiredPerm, &cpuPerm, sizeof(cpuPerm) },
        { NvSciSyncAttrKey_PrimitiveInfo, &cpuPrimType, sizeof(cpuPrimType) },
        { NvSciSyncAttrKey_GpuId, gpuIds.data(), sizeof(NvSciRmGpuId) * gpuIds.size() },
    };

    if(auto const error{NvSciSyncAttrListSetAttrs(waiterSyncAttrs.get(), cpuWaiterKeyValuePairs, sizeof(cpuWaiterKeyValuePairs) / sizeof(cpuWaiterKeyValuePairs))}; error != NvSciError_Success)
    {
        LOG_ERR("Couldn't set NvSciSyncAttrList: %d", error);
        return {};
    }
}

// Reconcile
std::vector<NvSciSyncAttrList> const hwSignalerAttrs{hwSignalerSyncAttrs.get(), waiterSyncAttrs.get()};
ScopedNvSciSyncAttrList hwSignalerReconciledSyncAttrs{nullptr};
{
    NvSciSyncAttrList hwConflictSyncAttrs{nullptr};
    NvSciSyncAttrList rawHWReconciledSyncAttrs{nullptr};
    if(auto const error{NvSciSyncAttrListReconcile(hwSignalerAttrs.data(), hwSignalerAttrs.size(), &rawHWReconciledSyncAttrs, &hwConflictSyncAttrs)}; error != NvSciError_Success)
    {
        LOG_ERR("Couldn't reconcile HW sync obj %d", error);
        if(hwConflictSyncAttrs != nullptr)
        {
            void* dump{};
            size_t len{};
            if (auto const err{NvSciSyncAttrListDebugDump(hwConflictSyncAttrs, &dump, &len)}; NvSciError_Success != err) {
                LOG_ERR("NvSciSyncAttrListDebugDump failed: %d", err);
            } else {
                LOG_ERR("Conflicted args: %-*s", len, static_cast<char*>(dump));
            }
            NvSciSyncAttrListFree(hwConflictSyncAttrs);
        } else {
            LOG_ERR("No conflict list");
        }
        return {};
    }
    hwSignalerReconciledSyncAttrs.reset(rawHWReconciledSyncAttrs);
}

With the outcommented NvMedia2DFillNvSciSyncAttrList I get:

nvmedia: ERROR: Couldn't reconcile HW sync obj 65792 (NvSciError_ReconciliationFailed) at generateHwSciSyncAttrs():616
nvmedia: ERROR: No conflict list at generateHwSciSyncAttrs():628

But with the NvMedia2DFillNvSciSyncAttrList calls the code works without any error. Is it mandatory to call NvMedia2DFillNvSciSyncAttrList on the NvSciSyncObjs’ attribute list, so there is a special, undocumented side effect of that call? Is it possible to create NvSciSyncObjs without calling NvMedia2DFillNvSciSyncAttrList?

Dear @AdamBalazsVay,
Is the ask what extra operations performed by this functions apart from what mentioned in document (i.e setting NvSciSyncAttrKey_RequiredPerm and NvSciSyncAttrKey_PrimitiveInfo )?

Dear @SivaRamaKrishnaNV,

If it is possible we would like to avoid calling NvMedia2DFillNvSciSyncAttrList/cudaDeviceGetNvSciSyncAttributes/NvMediaLdcFillNvSciSyncAttrList and fill the attribute lists manually simply with calling NvSciSyncAttrListSetAttrs with the right NvSciSyncAttrKeyValuePair combinations, and then create NvSciSyncObjs and use them with NvMedia2D after registering.

The documentation doesn’t say that we need to call NvMedia2DFillNvSciSyncAttrList with the same NvMedia2D instance we want to register the NvSciSyncObj with later on.

The reason is that we create our NvSciBufObjs and NvSciSyncObjs in an initialization phase. By that time we don’t have the NvMedia2D/NvMediaLDC objectst that will use the buffers/sync objects, those are created in a later stage.

In DriveOS 5.2.6 it is possible, to create a temporary NvMedia2D object, call NvMedia2DFillNvSciSyncAttrList on an attribute list, create an NvSciSyncObj based on the reconciled attribute list and delete the temporary NvMedia2D object. Then the created NvSciSyncObj can be registered with CUDA, different NvMedia2D instances, different NvMediaLDC instances without any error.

Seemingly this behavior has changed in DriveOS 6.0.8.1, an NvSciSyncObj can be registered with only the very same NvMedia2D object that was part of the argument list of the NvMedia2DFillNvSciSyncAttrList call.

This is why we would like to manually construct the attribute list, but when we manually fill it we get the mentioned reconciliation error:

nvmedia: ERROR: Couldn't reconcile HW sync obj 65792 (NvSciError_ReconciliationFailed) at generateHwSciSyncAttrs():616
nvmedia: ERROR: No conflict list at generateHwSciSyncAttrs():628

Dear @AdamBalazsVay,

No. It fills few internal attribute Keys which are needed to use NvSciSyncObjs with NvMedia2D.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.