From f4d2f16c5baaf7386a56f148146584e76a381a88 Mon Sep 17 00:00:00 2001
From: Your Name <you@example.com>
Date: Mon, 12 Sep 2022 04:31:06 +0000
Subject: [PATCH] Update to use CPU buffer

---
 rawstream_consumer.c | 149 ++++++++++++++------------------------
 rawstream_producer.c | 169 +++++++++++++++++--------------------------
 2 files changed, 119 insertions(+), 199 deletions(-)

diff --git a/rawstream_consumer.c b/rawstream_consumer.c
index fb8e5ab..b5c74f8 100644
--- a/rawstream_consumer.c
+++ b/rawstream_consumer.c
@@ -12,18 +12,12 @@
 
 void* consumerFunc(void* arg)
 {
-    CudaClientInfo cudaInfo;
     NvSciError     sciErr;
     int            cudaErr;
 
     *(int*)arg = 1;
     fprintf(stderr, "Consumer starting\n");
 
-    // Do common cuda initialization
-    if (!setupCuda(&cudaInfo)) {
-        goto done;
-    }
-
     // Create an empty sync attribute list for signaling permissions.
     sciErr = NvSciSyncAttrListCreate(syncModule, &consumerSignalAttrs);
     if (NvSciError_Success != sciErr) {
@@ -33,14 +27,22 @@ void* consumerFunc(void* arg)
         goto done;
     }
 
-    // Query CUDA for attributes needed to signal syncs
-    cudaErr = cudaDeviceGetNvSciSyncAttributes(consumerSignalAttrs,
-                                               cudaInfo.deviceId,
-                                               cudaNvSciSyncAttrSignal);
-    if (cudaSuccess != cudaErr) {
+    bool cpuSignaler = true;
+    NvSciSyncAccessPerm cpuPermSignal = NvSciSyncAccessPerm_SignalOnly;
+    NvSciSyncAttrKeyValuePair keyValueSignal[2] = {0};
+
+    keyValueSignal[0].attrKey = NvSciSyncAttrKey_NeedCpuAccess;
+    keyValueSignal[0].value   = (void*) &cpuSignaler;
+    keyValueSignal[0].len     = sizeof(cpuSignaler);
+    keyValueSignal[1].attrKey = NvSciSyncAttrKey_RequiredPerm;
+    keyValueSignal[1].value   = (void*) &cpuPermSignal;
+    keyValueSignal[1].len     = sizeof(cpuPermSignal);
+
+    sciErr = NvSciSyncAttrListSetAttrs(consumerSignalAttrs, keyValueSignal, 2);
+    if (NvSciError_Success != sciErr) {
         fprintf(stderr,
-                "Could not query signal attributes from CUDA (%d)\n",
-                cudaErr);
+                "Could not query signal attributes for CPU (%d)\n",
+                sciErr);
         goto done;
     }
 
@@ -55,14 +57,22 @@ void* consumerFunc(void* arg)
         goto done;
     }
 
-    // Query CUDA for attributes needed to wait for syncs
-    cudaErr = cudaDeviceGetNvSciSyncAttributes(consumerWaitAttrs,
-                                               cudaInfo.deviceId,
-                                               cudaNvSciSyncAttrWait);
-    if (cudaSuccess != cudaErr) {
+    bool cpuWaiter = true;
+    NvSciSyncAccessPerm cpuPermWait = NvSciSyncAccessPerm_WaitOnly;
+    NvSciSyncAttrKeyValuePair keyValueWait[2] = {0};
+
+    keyValueWait[0].attrKey = NvSciSyncAttrKey_NeedCpuAccess;
+    keyValueWait[0].value   = (void*) &cpuWaiter;
+    keyValueWait[0].len     = sizeof(cpuWaiter);
+    keyValueWait[1].attrKey = NvSciSyncAttrKey_RequiredPerm;
+    keyValueWait[1].value   = (void*) &cpuPermWait;
+    keyValueWait[1].len     = sizeof(cpuPermWait);
+
+    sciErr = NvSciSyncAttrListSetAttrs(consumerWaitAttrs, keyValueWait, 2);
+    if (NvSciError_Success != sciErr) {
         fprintf(stderr,
-                "Could not query wait attributes from CUDA (%d)\n",
-                cudaErr);
+                "Could not query wait attributes for CPU (%d)\n",
+                sciErr);
         goto done;
     }
 
@@ -255,11 +265,6 @@ void* consumerFunc(void* arg)
         goto done;
     }
 
-    // Set up CUDA sync objects, importing NvSciSync objects
-    if (!setupCudaSync(&cudaInfo, consumerSignalObj, consumerWaitObj)) {
-        goto done;
-    }
-
     fprintf(stderr, "Consumer exchanged sync objects with producer\n");
 
     // Create an empty buffer attribute list for consumer buffers
@@ -272,26 +277,21 @@ void* consumerFunc(void* arg)
     }
 
     // Fill consumer buffer attribute list with values
-    NvSciBufAttrKeyValuePair bufKeyValue[4];
-    NvSciRmGpuId gpuId;
-    memcpy(&gpuId.bytes, &cudaInfo.uuid.bytes, sizeof(cudaInfo.uuid.bytes));
-    bufKeyValue[0].key   = NvSciBufGeneralAttrKey_GpuId;
-    bufKeyValue[0].value = &gpuId;
-    bufKeyValue[0].len   = sizeof(gpuId);
+    NvSciBufAttrKeyValuePair bufKeyValue[3];
     NvSciBufType bufType = NvSciBufType_RawBuffer;
-    bufKeyValue[1].key   = NvSciBufGeneralAttrKey_Types;
-    bufKeyValue[1].value = &bufType;
-    bufKeyValue[1].len   = sizeof(bufType);
+    bufKeyValue[0].key   = NvSciBufGeneralAttrKey_Types;
+    bufKeyValue[0].value = &bufType;
+    bufKeyValue[0].len   = sizeof(bufType);
     NvSciBufAttrValAccessPerm bufPerm = NvSciBufAccessPerm_Readonly;
-    bufKeyValue[2].key   = NvSciBufGeneralAttrKey_RequiredPerm;
-    bufKeyValue[2].value = &bufPerm;
-    bufKeyValue[2].len   = sizeof(bufPerm);
+    bufKeyValue[1].key   = NvSciBufGeneralAttrKey_RequiredPerm;
+    bufKeyValue[1].value = &bufPerm;
+    bufKeyValue[1].len   = sizeof(bufPerm);
     bool   bufAccessFlag = true;
-    bufKeyValue[3].key   = NvSciBufGeneralAttrKey_NeedCpuAccess;
-    bufKeyValue[3].value = &bufAccessFlag;
-    bufKeyValue[3].len   = sizeof(bufAccessFlag);
+    bufKeyValue[2].key   = NvSciBufGeneralAttrKey_NeedCpuAccess;
+    bufKeyValue[2].value = &bufAccessFlag;
+    bufKeyValue[2].len   = sizeof(bufAccessFlag);
 
-    sciErr = NvSciBufAttrListSetAttrs(consumerReadAttrs, bufKeyValue, 4);
+    sciErr = NvSciBufAttrListSetAttrs(consumerReadAttrs, bufKeyValue, 3);
     if (NvSciError_Success != sciErr) {
         fprintf(stderr, "Unable to fill consumer buffer attrs (%x)\n", sciErr);
         goto done;
@@ -380,11 +380,6 @@ void* consumerFunc(void* arg)
         goto done;
     }
 
-    // Extract attributes needed by CUDA
-    if (!setupCudaBufAttr(&cudaInfo, combinedBufAttrs)) {
-        goto done;
-    }
-
     // Receive all buffers
     for (uint32_t i=0U; i<totalBuffers; ++i) {
 
@@ -415,11 +410,6 @@ void* consumerFunc(void* arg)
                     i, sciErr);
             goto done;
         }
-
-        // Import the buffer into CUDA
-        if (!setupCudaBuffer(&cudaInfo, buf)) {
-            goto done;
-        }
     }
 
     fprintf(stderr, "Consumer buffers received and established\n");
@@ -463,56 +453,27 @@ void* consumerFunc(void* arg)
             buffers[packet.bufferId].owner = 1U;
         }
 
-        // Wait for fence generated by producer before reading
-        if (!waitCudaFence(&cudaInfo, buf)) {
-            goto done;
-        }
 
-        // Read the buffer to the local copy
-        cudaErr = cudaMemcpy2DAsync(cudaInfo.bufCopy,
-                                    cudaInfo.bufSize,
-                                    buf->ptr,
-                                    cudaInfo.bufSize,
-                                    cudaInfo.bufSize,
-                                    1,
-                                    cudaMemcpyDeviceToHost,
-                                    cudaInfo.stream);
-        if (cudaSuccess != cudaErr) {
-            fprintf(stderr, "Unable to initiate CUDA copy (%d)\n", cudaErr);
+        // get CPU buffer pointer
+        int* data_ptr;
+        sciErr = NvSciBufObjGetCpuPtr(buf->obj, (void**)&data_ptr);
+        if (NvSciError_Success != sciErr) {
+            fprintf(stderr,
+                    "Cannot get CPU buffer pointer (%x)\n",
+                    sciErr);
             goto done;
         }
 
-        // Wait for operation to finish, then compute and compare checksum
-        // IMPORTANT NOTE:
-        //   A normal stream application would not perform these steps.
-        //   A checksum is not required for streaming, and waiting for
-        //     operations to finish (which we only need because the
-        //     checksum is calculated by the CPU) introduces bubbles
-        //     in the hardware pipeline. A real application can rely on
-        //     the generated NvSciSync fences for synchronization.
-        //   These steps are only taken in this sample application
-        //     because the consumer has no output visible to the user,
-        //     so the checksum allows us to verify that the application
-        //     is behaving properly.
-        cudaDeviceSynchronize();
-        uint32_t crc = GenerateCRC(cudaInfo.bufCopy,
-                                   1,
-                                   cudaInfo.bufSize,
-                                   cudaInfo.bufSize);
-        if (buf->crc != crc) {
-            fprintf(stderr, "Checksums don't match (%x vs %x)\n",
-                    crc, buf->crc);
-            goto done;
+        /* do some CPU jobs */
+        printf("frame %d: val= ", currFrame);
+        for( size_t i=0; i<10; i++ ) {
+            printf("%d, ", data_ptr[i]);
         }
+        printf("\n");
 
         fprintf(stderr, "Consumer read frame %d in buffer %d\n",
                 currFrame, currBuffer);
 
-        // Generate new fence indicating when reading has finished
-        if (!signalCudaFence(&cudaInfo, buf)) {
-            goto done;
-        }
-
         // Mark buffer as owned by producer now
         buf->owner = 0U;
 
@@ -548,10 +509,6 @@ void* consumerFunc(void* arg)
     // Success
     *(int*)arg = 0;
 done:
-    // Free CUDA resources
-    deinitCudaBuffer(buffers, totalBuffers);
-    deinitCuda(&cudaInfo);
-
     // Free NvSci objects
     if (NULL != consumerSignalAttrs)
         NvSciSyncAttrListFree(consumerSignalAttrs);
diff --git a/rawstream_producer.c b/rawstream_producer.c
index 7339047..9c9d226 100644
--- a/rawstream_producer.c
+++ b/rawstream_producer.c
@@ -8,22 +8,17 @@
  * is strictly prohibited.
  */
 
+#include <stdlib.h>
 #include "rawstream.h"
 
 void* producerFunc(void* arg)
 {
-    CudaClientInfo cudaInfo;
     NvSciError     sciErr;
     int            cudaErr;
 
     *(int*)arg = 1;
     fprintf(stderr, "Producer starting\n");
 
-    // Do common cuda initialization
-    if (!setupCuda(&cudaInfo)) {
-        goto done;
-    }
-
     // Create an empty sync attribute list for signaling permissions.
     sciErr = NvSciSyncAttrListCreate(syncModule, &producerSignalAttrs);
     if (NvSciError_Success != sciErr) {
@@ -33,14 +28,22 @@ void* producerFunc(void* arg)
         goto done;
     }
 
-    // Query CUDA for attributes needed to signal syncs
-    cudaErr = cudaDeviceGetNvSciSyncAttributes(producerSignalAttrs,
-                                               cudaInfo.deviceId,
-                                               cudaNvSciSyncAttrSignal);
-    if (cudaSuccess != cudaErr) {
+    bool cpuSignaler = true;
+    NvSciSyncAccessPerm cpuPermSignal = NvSciSyncAccessPerm_SignalOnly;
+    NvSciSyncAttrKeyValuePair keyValueSignal[2] = {0};
+
+    keyValueSignal[0].attrKey = NvSciSyncAttrKey_NeedCpuAccess;
+    keyValueSignal[0].value   = (void*) &cpuSignaler;
+    keyValueSignal[0].len     = sizeof(cpuSignaler);
+    keyValueSignal[1].attrKey = NvSciSyncAttrKey_RequiredPerm;
+    keyValueSignal[1].value   = (void*) &cpuPermSignal;
+    keyValueSignal[1].len     = sizeof(cpuPermSignal);
+
+    sciErr = NvSciSyncAttrListSetAttrs(producerSignalAttrs, keyValueSignal, 2);
+    if (NvSciError_Success != sciErr) {
         fprintf(stderr,
-                "Could not query signal attributes from CUDA (%d)\n",
-                cudaErr);
+                "Could not query signal attributes for CPU (%d)\n",
+                sciErr);
         goto done;
     }
 
@@ -55,14 +58,22 @@ void* producerFunc(void* arg)
         goto done;
     }
 
-    // Query CUDA for attributes needed to wait for syncs
-    cudaErr = cudaDeviceGetNvSciSyncAttributes(producerWaitAttrs,
-                                               cudaInfo.deviceId,
-                                               cudaNvSciSyncAttrWait);
-    if (cudaSuccess != cudaErr) {
+    bool cpuWaiter = true;
+    NvSciSyncAccessPerm cpuPermWait = NvSciSyncAccessPerm_WaitOnly;
+    NvSciSyncAttrKeyValuePair keyValueWait[2] = {0};
+
+    keyValueWait[0].attrKey = NvSciSyncAttrKey_NeedCpuAccess;
+    keyValueWait[0].value   = (void*) &cpuWaiter;
+    keyValueWait[0].len     = sizeof(cpuWaiter);
+    keyValueWait[1].attrKey = NvSciSyncAttrKey_RequiredPerm;
+    keyValueWait[1].value   = (void*) &cpuPermWait;
+    keyValueWait[1].len     = sizeof(cpuPermWait);
+
+    sciErr = NvSciSyncAttrListSetAttrs(producerWaitAttrs, keyValueWait, 2);
+    if (NvSciError_Success != sciErr) {
         fprintf(stderr,
-                "Could not query wait attributes from CUDA (%d)\n",
-                cudaErr);
+                "Could not query wait attributes for CPU (%d)\n",
+                sciErr);
         goto done;
     }
 
@@ -259,11 +270,6 @@ void* producerFunc(void* arg)
         goto done;
     }
 
-    // Set up CUDA sync objects, importing NvSciSync objects
-    if (!setupCudaSync(&cudaInfo, producerSignalObj, producerWaitObj)) {
-        goto done;
-    }
-
     fprintf(stderr, "Producer exchanged sync objects with consumer\n");
 
     // Create an empty buffer attribute list for producer buffers
@@ -276,34 +282,29 @@ void* producerFunc(void* arg)
     }
 
     // Fill producer buffer attribute list with values
-    NvSciBufAttrKeyValuePair bufKeyValue[6];
-    NvSciRmGpuId gpuId;
-    memcpy(&gpuId.bytes, &cudaInfo.uuid.bytes, sizeof(cudaInfo.uuid.bytes));
-    bufKeyValue[0].key   = NvSciBufGeneralAttrKey_GpuId;
-    bufKeyValue[0].value = &gpuId;
-    bufKeyValue[0].len   = sizeof(gpuId);
+    NvSciBufAttrKeyValuePair bufKeyValue[5];
     NvSciBufType bufType = NvSciBufType_RawBuffer;
-    bufKeyValue[1].key   = NvSciBufGeneralAttrKey_Types;
-    bufKeyValue[1].value = &bufType;
-    bufKeyValue[1].len   = sizeof(bufType);
+    bufKeyValue[0].key   = NvSciBufGeneralAttrKey_Types;
+    bufKeyValue[0].value = &bufType;
+    bufKeyValue[0].len   = sizeof(bufType);
     NvSciBufAttrValAccessPerm bufPerm = NvSciBufAccessPerm_ReadWrite;
-    bufKeyValue[2].key   = NvSciBufGeneralAttrKey_RequiredPerm;
-    bufKeyValue[2].value = &bufPerm;
-    bufKeyValue[2].len   = sizeof(bufPerm);
+    bufKeyValue[1].key   = NvSciBufGeneralAttrKey_RequiredPerm;
+    bufKeyValue[1].value = &bufPerm;
+    bufKeyValue[1].len   = sizeof(bufPerm);
     bool   bufAccessFlag = true;
-    bufKeyValue[3].key   = NvSciBufGeneralAttrKey_NeedCpuAccess;
-    bufKeyValue[3].value = &bufAccessFlag;
-    bufKeyValue[3].len   = sizeof(bufAccessFlag);
+    bufKeyValue[2].key   = NvSciBufGeneralAttrKey_NeedCpuAccess;
+    bufKeyValue[2].value = &bufAccessFlag;
+    bufKeyValue[2].len   = sizeof(bufAccessFlag);
     uint64_t rawsize     = (128 * 1024);
-    bufKeyValue[4].key   = NvSciBufRawBufferAttrKey_Size;
-    bufKeyValue[4].value = &rawsize;
-    bufKeyValue[4].len   = sizeof(rawsize);
+    bufKeyValue[3].key   = NvSciBufRawBufferAttrKey_Size;
+    bufKeyValue[3].value = &rawsize;
+    bufKeyValue[3].len   = sizeof(rawsize);
     uint64_t align       = (4 * 1024);
-    bufKeyValue[5].key   = NvSciBufRawBufferAttrKey_Align;
-    bufKeyValue[5].value = &align;
-    bufKeyValue[5].len   = sizeof(align);
+    bufKeyValue[4].key   = NvSciBufRawBufferAttrKey_Align;
+    bufKeyValue[4].value = &align;
+    bufKeyValue[4].len   = sizeof(align);
 
-    sciErr = NvSciBufAttrListSetAttrs(producerWriteAttrs, bufKeyValue, 6);
+    sciErr = NvSciBufAttrListSetAttrs(producerWriteAttrs, bufKeyValue, 5);
     if (NvSciError_Success != sciErr) {
         fprintf(stderr, "Unable to fill producer buffer attrs (%x)\n", sciErr);
         goto done;
@@ -399,11 +400,6 @@ void* producerFunc(void* arg)
         goto done;
     }
 
-    // Extract attributes needed by CUDA
-    if (!setupCudaBufAttr(&cudaInfo, combinedBufAttrs)) {
-        goto done;
-    }
-
     // Allocate all buffers
     for (uint32_t i=0U; i<totalBuffers; ++i) {
 
@@ -439,11 +435,6 @@ void* producerFunc(void* arg)
             fprintf(stderr, "Unable to send buffer %d (%x)\n", i, sciErr);
             goto done;
         }
-
-        // Import the buffer into CUDA
-        if (!setupCudaBuffer(&cudaInfo, buf)) {
-            goto done;
-        }
     }
 
     fprintf(stderr, "Producer buffers established and transmitted\n");
@@ -452,6 +443,10 @@ void* producerFunc(void* arg)
     uint32_t currFrame  = 0;
     uint32_t currBuffer = 0;
     Packet packet;
+    NvSciSyncFence sharedFence = NvSciSyncFenceInitializer;
+    NvSciSyncFence localFence = NvSciSyncFenceInitializer;
+
+    srand(time(NULL));
     while (currFrame < totalFrames) {
         fprintf(stderr, "Producer starting frame %d in buffer %d\n",
                 currFrame, currBuffer);
@@ -490,52 +485,25 @@ void* producerFunc(void* arg)
             buffers[packet.bufferId].owner = 0U;
         }
 
-        // Wait for fence returned by consumer before rendering
-        if (!waitCudaFence(&cudaInfo, buf)) {
-            goto done;
-        }
 
-        // CUDA rendering to buffer
-        (void)memset(cudaInfo.bufCopy, (currFrame & 0xFF), cudaInfo.bufSize);
-
-        cudaErr = cudaMemcpy2DAsync(buf->ptr,
-                                    cudaInfo.bufSize,
-                                    cudaInfo.bufCopy,
-                                    cudaInfo.bufSize,
-                                    cudaInfo.bufSize,
-                                    1,
-                                    cudaMemcpyHostToDevice,
-                                    cudaInfo.stream);
-        if (cudaSuccess != cudaErr) {
-            fprintf(stderr, "Unable to initiate CUDA copy (%d)\n", cudaErr);
+        // get CPU buffer pointer
+        int* data_ptr;
+        sciErr = NvSciBufObjGetCpuPtr(buf->obj, (void**)&data_ptr);
+        if (NvSciError_Success != sciErr) {
+            fprintf(stderr,
+                    "Cannot get CPU buffer pointer (%x)\n",
+                    sciErr);
             goto done;
-        }
+	}
 
-        // Generate new fence for the sync object
-        if (!signalCudaFence(&cudaInfo, buf)) {
-            goto done;
+        // do some CPU jobs
+        printf("frame %d: val= ", currFrame);
+        for( size_t i=0; i<10; i++ ) {
+            data_ptr[i] = rand();
+            printf("%d, ", data_ptr[i]);
         }
+        printf("\n");
 
-        // Wait for operation to finish and compute checksum
-        // IMPORTANT NOTE:
-        //   A normal stream application would not perform these steps.
-        //   A checksum is not required for streaming, and waiting for
-        //     operations to finish (which we only need because the
-        //     checksum is calculated by the CPU) introduces bubbles
-        //     in the hardware pipeline. A real application can rely on
-        //     the generated NvSciSync fences for synchronization.
-        //   These steps are only taken in this sample application
-        //     because the consumer has no output visible to the user,
-        //     so the checksum allows us to verify that the application
-        //     is behaving properly.
-        cudaDeviceSynchronize();
-        buf->crc = GenerateCRC(cudaInfo.bufCopy,
-                               1,
-                               cudaInfo.bufSize,
-                               cudaInfo.bufSize);
-
-        fprintf(stderr, "Producer wrote frame %d in buffer %d\n",
-                currFrame, currBuffer);
 
         // Mark buffer as owned by consumer now
         buf->owner = 1U;
@@ -568,14 +536,9 @@ void* producerFunc(void* arg)
         currFrame++;
     }
 
-
     // Success
     *(int*)arg = 0;
 done:
-    // Free CUDA resources
-    deinitCudaBuffer(buffers, totalBuffers);
-    deinitCuda(&cudaInfo);
-
     // Free NvSci objects
     if (NULL != producerSignalAttrs)
         NvSciSyncAttrListFree(producerSignalAttrs);
-- 
2.25.1

