Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.

This commit is contained in:
Rob Armstrong
2025-03-27 10:30:07 -07:00
parent 2cd58fbc9a
commit ceab6e8bcc
782 changed files with 107230 additions and 106548 deletions

View File

@@ -37,4 +37,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -32,13 +32,14 @@
#ifndef _EGL_COMMON_H_
#define _EGL_COMMON_H_
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include "cuda.h"
#include "cudaEGL.h"
@@ -54,18 +55,18 @@ EGLImageKHR eglImage;
T(PFNEGLCREATESYNC64KHRPROC, eglCreateSync64KHR) \
T(PFNEGLWAITSYNCKHRPROC, eglWaitSyncKHR)
#define eglCreateImageKHR my_eglCreateImageKHR
#define eglDestroyImageKHR my_eglDestroyImageKHR
#define eglCreateSyncKHR my_eglCreateSyncKHR
#define eglDestroySyncKHR my_eglDestroySyncKHR
#define eglCreateImageKHR my_eglCreateImageKHR
#define eglDestroyImageKHR my_eglDestroyImageKHR
#define eglCreateSyncKHR my_eglCreateSyncKHR
#define eglDestroySyncKHR my_eglDestroySyncKHR
#define eglClientWaitSyncKHR my_eglClientWaitSyncKHR
#define eglGetSyncAttribKHR my_eglGetSyncAttribKHR
#define eglCreateSync64KHR my_eglCreateSync64KHR
#define eglWaitSyncKHR my_eglWaitSyncKHR
#define eglGetSyncAttribKHR my_eglGetSyncAttribKHR
#define eglCreateSync64KHR my_eglCreateSync64KHR
#define eglWaitSyncKHR my_eglWaitSyncKHR
#define EXTLST_DECL(tx, x) tx my_##x = NULL;
#define EXTLST_DECL(tx, x) tx my_##x = NULL;
#define EXTLST_EXTERN(tx, x) extern tx my_##x;
#define EXTLST_ENTRY(tx, x) {(extlst_fnptr_t *)&my_##x, #x},
#define EXTLST_ENTRY(tx, x) {(extlst_fnptr_t *)&my_##x, #x},
int eglSetupExtensions(void);
#endif

View File

@@ -27,178 +27,197 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
Display *display;
int screen;
Window win = 0;
int screen;
Window win = 0;
void error_exit(const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
void error_exit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
#include <EGL/egl.h>
#include <EGL/eglext.h>
#define GET_GLERROR(ret) \
{ \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, \
err); \
fflush(stderr); \
\
switch (err) { \
case GL_INVALID_ENUM: \
printf("GL_INVALID_ENUM\n"); \
break; \
case GL_INVALID_VALUE: \
printf("GL_INVALID_VALUE\n"); \
break; \
case GL_INVALID_OPERATION: \
printf("GL_INVALID_OPERATION\n"); \
break; \
case GL_OUT_OF_MEMORY: \
printf("GL_OUT_OF_MEMORY\n"); \
break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \
break; \
default: \
printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \
}; \
} \
}
#define GET_GLERROR(ret) \
{ \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, err); \
fflush(stderr); \
\
switch (err) { \
case GL_INVALID_ENUM: \
printf("GL_INVALID_ENUM\n"); \
break; \
case GL_INVALID_VALUE: \
printf("GL_INVALID_VALUE\n"); \
break; \
case GL_INVALID_OPERATION: \
printf("GL_INVALID_OPERATION\n"); \
break; \
case GL_OUT_OF_MEMORY: \
printf("GL_OUT_OF_MEMORY\n"); \
break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \
break; \
default: \
printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \
}; \
} \
}
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLSurface eglSurface = EGL_NO_SURFACE;
EGLContext eglContext = EGL_NO_CONTEXT;
int graphics_setup_window(int xpos, int ypos, int width, int height,
const char *windowname) {
EGLint configAttrs[] = {
EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_DEPTH_SIZE, 16,
EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0,
// EGL_CONFORMANT, EGL_OPENGL_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // 3_BIT_KHR,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
int graphics_setup_window(int xpos, int ypos, int width, int height, const char *windowname)
{
EGLint configAttrs[] = {EGL_RED_SIZE,
1,
EGL_GREEN_SIZE,
1,
EGL_BLUE_SIZE,
1,
EGL_DEPTH_SIZE,
16,
EGL_SAMPLE_BUFFERS,
0,
EGL_SAMPLES,
0,
// EGL_CONFORMANT, EGL_OPENGL_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT, // 3_BIT_KHR,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLConfig *configList = NULL;
EGLint configCount;
EGLConfig *configList = NULL;
EGLint configCount;
display = XOpenDisplay(NULL);
if (!display) error_exit("Error opening X display.\n");
display = XOpenDisplay(NULL);
if (!display)
error_exit("Error opening X display.\n");
screen = DefaultScreen(display);
screen = DefaultScreen(display);
eglDisplay = eglGetDisplay(0);
eglDisplay = eglGetDisplay(0);
if (eglDisplay == EGL_NO_DISPLAY)
error_exit("EGL failed to obtain display\n");
if (eglDisplay == EGL_NO_DISPLAY)
error_exit("EGL failed to obtain display\n");
if (!eglInitialize(eglDisplay, 0, 0))
error_exit("EGL failed to initialize\n");
if (!eglInitialize(eglDisplay, 0, 0))
error_exit("EGL failed to initialize\n");
if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) ||
!configCount)
error_exit("EGL failed to return any matching configurations\n");
if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) || !configCount)
error_exit("EGL failed to return any matching configurations\n");
configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig));
configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig));
if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount,
&configCount) ||
!configCount)
error_exit("EGL failed to populate configuration list\n");
if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount, &configCount) || !configCount)
error_exit("EGL failed to populate configuration list\n");
Window xRootWindow = DefaultRootWindow(display);
XSetWindowAttributes xCreateWindowAttributes;
xCreateWindowAttributes.event_mask = ExposureMask;
win = XCreateWindow(display, xRootWindow, 0, 0, width, height, 0,
CopyFromParent, InputOutput, CopyFromParent, CWEventMask,
&xCreateWindowAttributes);
XMapWindow(display, win);
Window xRootWindow = DefaultRootWindow(display);
XSetWindowAttributes xCreateWindowAttributes;
xCreateWindowAttributes.event_mask = ExposureMask;
win = XCreateWindow(display,
xRootWindow,
0,
0,
width,
height,
0,
CopyFromParent,
InputOutput,
CopyFromParent,
CWEventMask,
&xCreateWindowAttributes);
XMapWindow(display, win);
Atom netWmStateAtom = XInternAtom(display, "_NET_WM_STATE", false);
XEvent xEvent;
memset(&xEvent, 0, sizeof(xEvent));
xEvent.type = ClientMessage;
xEvent.xclient.window = win;
xEvent.xclient.message_type = netWmStateAtom;
xEvent.xclient.format = 32;
xEvent.xclient.data.l[0] = 1;
xEvent.xclient.data.l[1] = false;
XSendEvent(display, xRootWindow, false, SubstructureNotifyMask, &xEvent);
Atom netWmStateAtom = XInternAtom(display, "_NET_WM_STATE", false);
XEvent xEvent;
memset(&xEvent, 0, sizeof(xEvent));
xEvent.type = ClientMessage;
xEvent.xclient.window = win;
xEvent.xclient.message_type = netWmStateAtom;
xEvent.xclient.format = 32;
xEvent.xclient.data.l[0] = 1;
xEvent.xclient.data.l[1] = false;
XSendEvent(display, xRootWindow, false, SubstructureNotifyMask, &xEvent);
XStoreName(display, win, windowname);
XStoreName(display, win, windowname);
XSelectInput(display, win,
ExposureMask | KeyPressMask | ButtonPressMask |
ButtonReleaseMask | KeyReleaseMask | VisibilityChangeMask |
PointerMotionMask);
XSelectInput(display,
win,
ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask
| VisibilityChangeMask | PointerMotionMask);
EGLint windowAttrs[] = {EGL_NONE};
EGLint windowAttrs[] = {EGL_NONE};
eglSurface = eglCreateWindowSurface(eglDisplay, configList[0],
(EGLNativeWindowType)win, windowAttrs);
eglSurface = eglCreateWindowSurface(eglDisplay, configList[0], (EGLNativeWindowType)win, windowAttrs);
if (!eglSurface) error_exit("EGL couldn't create window\n");
if (!eglSurface)
error_exit("EGL couldn't create window\n");
eglBindAPI(EGL_OPENGL_ES_API);
eglBindAPI(EGL_OPENGL_ES_API);
eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs);
if (!eglContext) error_exit("EGL couldn't create context\n");
eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs);
if (!eglContext)
error_exit("EGL couldn't create context\n");
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
error_exit("EGL couldn't make context/surface current\n");
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
error_exit("EGL couldn't make context/surface current\n");
EGLint Context_RendererType;
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE,
&Context_RendererType);
EGLint Context_RendererType;
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE, &Context_RendererType);
switch (Context_RendererType) {
switch (Context_RendererType) {
case EGL_OPENGL_API:
printf("Using OpenGL API is not supported\n");
exit(EXIT_FAILURE);
break;
printf("Using OpenGL API is not supported\n");
exit(EXIT_FAILURE);
break;
case EGL_OPENGL_ES_API:
printf("Using OpenGL ES API\n");
break;
printf("Using OpenGL ES API\n");
break;
case EGL_OPENVG_API:
error_exit("Context Query Returned OpenVG. This is Unsupported\n");
error_exit("Context Query Returned OpenVG. This is Unsupported\n");
default:
error_exit("Unknown Context Type. %04X\n", Context_RendererType);
}
error_exit("Unknown Context Type. %04X\n", Context_RendererType);
}
return 1;
return 1;
}
void graphics_set_windowtitle(const char *windowname) {
XStoreName(display, win, windowname);
}
void graphics_set_windowtitle(const char *windowname) { XStoreName(display, win, windowname); }
void graphics_swap_buffers() { eglSwapBuffers(eglDisplay, eglSurface); }
void graphics_close_window() {
if (eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
void graphics_close_window()
{
if (eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (eglContext != EGL_NO_CONTEXT) eglDestroyContext(eglDisplay, eglContext);
if (eglContext != EGL_NO_CONTEXT)
eglDestroyContext(eglDisplay, eglContext);
if (eglSurface != EGL_NO_SURFACE) eglDestroySurface(eglDisplay, eglSurface);
if (eglSurface != EGL_NO_SURFACE)
eglDestroySurface(eglDisplay, eglSurface);
eglTerminate(eglDisplay);
}
eglTerminate(eglDisplay);
}
if (display) {
if (win) XDestroyWindow(display, win);
if (display) {
if (win)
XDestroyWindow(display, win);
XCloseDisplay(display);
}
XCloseDisplay(display);
}
}

View File

@@ -30,4 +30,3 @@ cudaStreamCreateWithFlags, cudaStreamDestroy, cudaFree, cudaGetErrorName, cudaSe
Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
## References (for more details)

View File

@@ -25,407 +25,399 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cudla.h"
#include "cuda_runtime.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/stat.h>
#include <fstream>
#include <sstream>
#include <sys/stat.h>
#include "cuda_runtime.h"
#include "cudla.h"
#define DPRINTF(...) printf(__VA_ARGS__)
static void printTensorDesc(cudlaModuleTensorDescriptor* tensorDesc) {
DPRINTF("\tTENSOR NAME : %s\n", tensorDesc->name);
DPRINTF("\tsize: %lu\n", tensorDesc->size);
static void printTensorDesc(cudlaModuleTensorDescriptor *tensorDesc)
{
DPRINTF("\tTENSOR NAME : %s\n", tensorDesc->name);
DPRINTF("\tsize: %lu\n", tensorDesc->size);
DPRINTF("\tdims: [%lu, %lu, %lu, %lu]\n", tensorDesc->n, tensorDesc->c,
tensorDesc->h, tensorDesc->w);
DPRINTF("\tdims: [%lu, %lu, %lu, %lu]\n", tensorDesc->n, tensorDesc->c, tensorDesc->h, tensorDesc->w);
DPRINTF("\tdata fmt: %d\n", tensorDesc->dataFormat);
DPRINTF("\tdata type: %d\n", tensorDesc->dataType);
DPRINTF("\tdata category: %d\n", tensorDesc->dataCategory);
DPRINTF("\tpixel fmt: %d\n", tensorDesc->pixelFormat);
DPRINTF("\tpixel mapping: %d\n", tensorDesc->pixelMapping);
DPRINTF("\tstride[0]: %d\n", tensorDesc->stride[0]);
DPRINTF("\tstride[1]: %d\n", tensorDesc->stride[1]);
DPRINTF("\tstride[2]: %d\n", tensorDesc->stride[2]);
DPRINTF("\tstride[3]: %d\n", tensorDesc->stride[3]);
DPRINTF("\tdata fmt: %d\n", tensorDesc->dataFormat);
DPRINTF("\tdata type: %d\n", tensorDesc->dataType);
DPRINTF("\tdata category: %d\n", tensorDesc->dataCategory);
DPRINTF("\tpixel fmt: %d\n", tensorDesc->pixelFormat);
DPRINTF("\tpixel mapping: %d\n", tensorDesc->pixelMapping);
DPRINTF("\tstride[0]: %d\n", tensorDesc->stride[0]);
DPRINTF("\tstride[1]: %d\n", tensorDesc->stride[1]);
DPRINTF("\tstride[2]: %d\n", tensorDesc->stride[2]);
DPRINTF("\tstride[3]: %d\n", tensorDesc->stride[3]);
}
typedef struct {
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
unsigned char* loadableData;
cudaStream_t stream;
unsigned char* inputBuffer;
unsigned char* outputBuffer;
void* inputBufferGPU;
void* outputBufferGPU;
cudlaModuleTensorDescriptor* inputTensorDesc;
cudlaModuleTensorDescriptor* outputTensorDesc;
typedef struct
{
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
unsigned char *loadableData;
cudaStream_t stream;
unsigned char *inputBuffer;
unsigned char *outputBuffer;
void *inputBufferGPU;
void *outputBufferGPU;
cudlaModuleTensorDescriptor *inputTensorDesc;
cudlaModuleTensorDescriptor *outputTensorDesc;
} ResourceList;
void cleanUp(ResourceList* resourceList);
void cleanUp(ResourceList *resourceList);
void cleanUp(ResourceList* resourceList) {
if (resourceList->inputTensorDesc != NULL) {
free(resourceList->inputTensorDesc);
resourceList->inputTensorDesc = NULL;
}
if (resourceList->outputTensorDesc != NULL) {
free(resourceList->outputTensorDesc);
resourceList->outputTensorDesc = NULL;
}
void cleanUp(ResourceList *resourceList)
{
if (resourceList->inputTensorDesc != NULL) {
free(resourceList->inputTensorDesc);
resourceList->inputTensorDesc = NULL;
}
if (resourceList->outputTensorDesc != NULL) {
free(resourceList->outputTensorDesc);
resourceList->outputTensorDesc = NULL;
}
if (resourceList->loadableData != NULL) {
free(resourceList->loadableData);
resourceList->loadableData = NULL;
}
if (resourceList->loadableData != NULL) {
free(resourceList->loadableData);
resourceList->loadableData = NULL;
}
if (resourceList->moduleHandle != NULL) {
cudlaModuleUnload(resourceList->moduleHandle, 0);
resourceList->moduleHandle = NULL;
}
if (resourceList->moduleHandle != NULL) {
cudlaModuleUnload(resourceList->moduleHandle, 0);
resourceList->moduleHandle = NULL;
}
if (resourceList->devHandle != NULL) {
cudlaDestroyDevice(resourceList->devHandle);
resourceList->devHandle = NULL;
}
if (resourceList->devHandle != NULL) {
cudlaDestroyDevice(resourceList->devHandle);
resourceList->devHandle = NULL;
}
if (resourceList->inputBufferGPU != 0) {
cudaFree(resourceList->inputBufferGPU);
resourceList->inputBufferGPU = 0;
}
if (resourceList->outputBufferGPU != 0) {
cudaFree(resourceList->outputBufferGPU);
resourceList->outputBufferGPU = 0;
}
if (resourceList->inputBufferGPU != 0) {
cudaFree(resourceList->inputBufferGPU);
resourceList->inputBufferGPU = 0;
}
if (resourceList->outputBufferGPU != 0) {
cudaFree(resourceList->outputBufferGPU);
resourceList->outputBufferGPU = 0;
}
if (resourceList->inputBuffer != NULL) {
free(resourceList->inputBuffer);
resourceList->inputBuffer = NULL;
}
if (resourceList->outputBuffer != NULL) {
free(resourceList->outputBuffer);
resourceList->outputBuffer = NULL;
}
if (resourceList->inputBuffer != NULL) {
free(resourceList->inputBuffer);
resourceList->inputBuffer = NULL;
}
if (resourceList->outputBuffer != NULL) {
free(resourceList->outputBuffer);
resourceList->outputBuffer = NULL;
}
if (resourceList->stream != NULL) {
cudaStreamDestroy(resourceList->stream);
resourceList->stream = NULL;
}
if (resourceList->stream != NULL) {
cudaStreamDestroy(resourceList->stream);
resourceList->stream = NULL;
}
}
int main(int argc, char** argv) {
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
cudlaStatus err;
FILE* fp = NULL;
struct stat st;
size_t file_size;
size_t actually_read = 0;
unsigned char* loadableData = NULL;
int main(int argc, char **argv)
{
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
cudlaStatus err;
FILE *fp = NULL;
struct stat st;
size_t file_size;
size_t actually_read = 0;
unsigned char *loadableData = NULL;
cudaStream_t stream;
cudaError_t result;
const char* errPtr = NULL;
cudaStream_t stream;
cudaError_t result;
const char *errPtr = NULL;
ResourceList resourceList;
ResourceList resourceList;
memset(&resourceList, 0x00, sizeof(ResourceList));
memset(&resourceList, 0x00, sizeof(ResourceList));
if (argc != 2) {
DPRINTF("Usage : ./cuDLAErrorReporting <loadable>\n");
return 1;
}
// Read loadable into buffer.
fp = fopen(argv[1], "rb");
if (fp == NULL) {
DPRINTF("Cannot open file %s\n", argv[1]);
return 1;
}
if (stat(argv[1], &st) != 0) {
DPRINTF("Cannot stat file\n");
return 1;
}
file_size = st.st_size;
DPRINTF("The file size = %ld\n", file_size);
loadableData = (unsigned char*)malloc(file_size);
if (loadableData == NULL) {
DPRINTF("Cannot Allocate memory for loadable\n");
return 1;
}
actually_read = fread(loadableData, 1, file_size, fp);
if (actually_read != file_size) {
free(loadableData);
DPRINTF("Read wrong size\n");
return 1;
}
fclose(fp);
resourceList.loadableData = loadableData;
// Initialize CUDA.
result = cudaFree(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaFree = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
result = cudaSetDevice(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaSetDevice = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
err = cudlaCreateDevice(0, &devHandle, CUDLA_CUDA_DLA);
if (err != cudlaSuccess) {
DPRINTF("Error in cuDLA create device = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Device created successfully\n");
resourceList.devHandle = devHandle;
err = cudlaModuleLoadFromMemory(devHandle, loadableData, file_size,
&moduleHandle, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in cudlaModuleLoadFromMemory = %d\n", err);
cleanUp(&resourceList);
return 1;
} else {
DPRINTF("Successfully loaded module\n");
}
resourceList.moduleHandle = moduleHandle;
// Create CUDA stream.
result = cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cuda stream = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
resourceList.stream = stream;
// Get tensor attributes.
uint32_t numInputTensors = 0;
uint32_t numOutputTensors = 0;
cudlaModuleAttribute attribute;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_INPUT_TENSORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numInputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numInputTensors = attribute.numInputTensors;
DPRINTF("numInputTensors = %d\n", numInputTensors);
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_OUTPUT_TENSORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numOutputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numOutputTensors = attribute.numOutputTensors;
DPRINTF("numOutputTensors = %d\n", numOutputTensors);
cudlaModuleTensorDescriptor* inputTensorDesc =
(cudlaModuleTensorDescriptor*)malloc(sizeof(cudlaModuleTensorDescriptor) *
numInputTensors);
cudlaModuleTensorDescriptor* outputTensorDesc =
(cudlaModuleTensorDescriptor*)malloc(sizeof(cudlaModuleTensorDescriptor) *
numOutputTensors);
if ((inputTensorDesc == NULL) || (outputTensorDesc == NULL)) {
if (inputTensorDesc != NULL) {
free(inputTensorDesc);
inputTensorDesc = NULL;
if (argc != 2) {
DPRINTF("Usage : ./cuDLAErrorReporting <loadable>\n");
return 1;
}
if (outputTensorDesc != NULL) {
free(outputTensorDesc);
outputTensorDesc = NULL;
// Read loadable into buffer.
fp = fopen(argv[1], "rb");
if (fp == NULL) {
DPRINTF("Cannot open file %s\n", argv[1]);
return 1;
}
if (stat(argv[1], &st) != 0) {
DPRINTF("Cannot stat file\n");
return 1;
}
file_size = st.st_size;
DPRINTF("The file size = %ld\n", file_size);
loadableData = (unsigned char *)malloc(file_size);
if (loadableData == NULL) {
DPRINTF("Cannot Allocate memory for loadable\n");
return 1;
}
actually_read = fread(loadableData, 1, file_size, fp);
if (actually_read != file_size) {
free(loadableData);
DPRINTF("Read wrong size\n");
return 1;
}
fclose(fp);
resourceList.loadableData = loadableData;
// Initialize CUDA.
result = cudaFree(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaFree = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
result = cudaSetDevice(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaSetDevice = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
err = cudlaCreateDevice(0, &devHandle, CUDLA_CUDA_DLA);
if (err != cudlaSuccess) {
DPRINTF("Error in cuDLA create device = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Device created successfully\n");
resourceList.devHandle = devHandle;
err = cudlaModuleLoadFromMemory(devHandle, loadableData, file_size, &moduleHandle, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in cudlaModuleLoadFromMemory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
else {
DPRINTF("Successfully loaded module\n");
}
resourceList.moduleHandle = moduleHandle;
// Create CUDA stream.
result = cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cuda stream = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
resourceList.stream = stream;
// Get tensor attributes.
uint32_t numInputTensors = 0;
uint32_t numOutputTensors = 0;
cudlaModuleAttribute attribute;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_INPUT_TENSORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numInputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numInputTensors = attribute.numInputTensors;
DPRINTF("numInputTensors = %d\n", numInputTensors);
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_OUTPUT_TENSORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numOutputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numOutputTensors = attribute.numOutputTensors;
DPRINTF("numOutputTensors = %d\n", numOutputTensors);
cudlaModuleTensorDescriptor *inputTensorDesc =
(cudlaModuleTensorDescriptor *)malloc(sizeof(cudlaModuleTensorDescriptor) * numInputTensors);
cudlaModuleTensorDescriptor *outputTensorDesc =
(cudlaModuleTensorDescriptor *)malloc(sizeof(cudlaModuleTensorDescriptor) * numOutputTensors);
if ((inputTensorDesc == NULL) || (outputTensorDesc == NULL)) {
if (inputTensorDesc != NULL) {
free(inputTensorDesc);
inputTensorDesc = NULL;
}
if (outputTensorDesc != NULL) {
free(outputTensorDesc);
outputTensorDesc = NULL;
}
cleanUp(&resourceList);
return 1;
}
resourceList.inputTensorDesc = inputTensorDesc;
resourceList.outputTensorDesc = outputTensorDesc;
attribute.inputTensorDesc = inputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_INPUT_TENSOR_DESCRIPTORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting input tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing input tensor descriptor\n");
printTensorDesc(inputTensorDesc);
attribute.outputTensorDesc = outputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_OUTPUT_TENSOR_DESCRIPTORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting output tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing output tensor descriptor\n");
printTensorDesc(outputTensorDesc);
// Setup the input and output buffers which will be used as an input to CUDA.
unsigned char *inputBuffer = (unsigned char *)malloc(inputTensorDesc[0].size);
if (inputBuffer == NULL) {
DPRINTF("Error in allocating input memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBuffer = inputBuffer;
unsigned char *outputBuffer = (unsigned char *)malloc(outputTensorDesc[0].size);
if (outputBuffer == NULL) {
DPRINTF("Error in allocating output memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBuffer = outputBuffer;
memset(inputBuffer, 0x01, inputTensorDesc[0].size);
memset(outputBuffer, 0x00, outputTensorDesc[0].size);
// Allocate memory on GPU.
void *inputBufferGPU;
void *outputBufferGPU;
result = cudaMalloc(&inputBufferGPU, inputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating input memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBufferGPU = inputBufferGPU;
result = cudaMalloc(&outputBufferGPU, outputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating output memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBufferGPU = outputBufferGPU;
// Register the CUDA-allocated buffers.
uint64_t *inputBufferRegisteredPtr = NULL;
uint64_t *outputBufferRegisteredPtr = NULL;
err =
cudlaMemRegister(devHandle, (uint64_t *)inputBufferGPU, inputTensorDesc[0].size, &inputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering input memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
err = cudlaMemRegister(
devHandle, (uint64_t *)outputBufferGPU, outputTensorDesc[0].size, &outputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("ALL MEMORY REGISTERED SUCCESSFULLY\n");
// Copy data from CPU buffers to GPU buffers.
result = cudaMemcpyAsync(inputBufferGPU, inputBuffer, inputTensorDesc[0].size, cudaMemcpyHostToDevice, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memcpy for input\n");
cleanUp(&resourceList);
return 1;
}
result = cudaMemsetAsync(outputBufferGPU, 0, outputTensorDesc[0].size, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memset for output\n");
cleanUp(&resourceList);
return 1;
}
// Enqueue a cuDLA task.
cudlaTask task;
task.moduleHandle = moduleHandle;
task.outputTensor = &outputBufferRegisteredPtr;
task.numOutputTensors = 1;
task.numInputTensors = 1;
task.inputTensor = &inputBufferRegisteredPtr;
task.waitEvents = NULL;
task.signalEvents = NULL;
err = cudlaSubmitTask(devHandle, &task, 1, stream, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in submitting task\n");
cleanUp(&resourceList);
return 1;
}
DPRINTF("SUBMIT IS DONE !!!\n");
// Wait for stream operations to finish and bring output buffer to CPU.
result = cudaMemcpyAsync(outputBuffer, outputBufferGPU, outputTensorDesc[0].size, cudaMemcpyDeviceToHost, stream);
if (result != cudaSuccess) {
if (result != cudaErrorExternalDevice) {
DPRINTF("Error in bringing result back to CPU\n");
cleanUp(&resourceList);
return 1;
}
else {
cudlaStatus hwStatus = cudlaGetLastError(devHandle);
if (hwStatus != cudlaSuccess) {
DPRINTF("Asynchronous error in HW = %u\n", hwStatus);
}
}
}
result = cudaStreamSynchronize(stream);
if (result != cudaSuccess) {
DPRINTF("Error in synchronizing stream = %s\n", cudaGetErrorName(result));
if (result == cudaErrorExternalDevice) {
cudlaStatus hwStatus = cudlaGetLastError(devHandle);
if (hwStatus != cudlaSuccess) {
DPRINTF("Asynchronous error in HW = %u\n", hwStatus);
}
}
}
cleanUp(&resourceList);
return 1;
}
resourceList.inputTensorDesc = inputTensorDesc;
resourceList.outputTensorDesc = outputTensorDesc;
DPRINTF("cuDLAErrorReporting DONE !!!\n");
attribute.inputTensorDesc = inputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_INPUT_TENSOR_DESCRIPTORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting input tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing input tensor descriptor\n");
printTensorDesc(inputTensorDesc);
attribute.outputTensorDesc = outputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_OUTPUT_TENSOR_DESCRIPTORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting output tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing output tensor descriptor\n");
printTensorDesc(outputTensorDesc);
// Setup the input and output buffers which will be used as an input to CUDA.
unsigned char* inputBuffer = (unsigned char*)malloc(inputTensorDesc[0].size);
if (inputBuffer == NULL) {
DPRINTF("Error in allocating input memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBuffer = inputBuffer;
unsigned char* outputBuffer =
(unsigned char*)malloc(outputTensorDesc[0].size);
if (outputBuffer == NULL) {
DPRINTF("Error in allocating output memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBuffer = outputBuffer;
memset(inputBuffer, 0x01, inputTensorDesc[0].size);
memset(outputBuffer, 0x00, outputTensorDesc[0].size);
// Allocate memory on GPU.
void* inputBufferGPU;
void* outputBufferGPU;
result = cudaMalloc(&inputBufferGPU, inputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating input memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBufferGPU = inputBufferGPU;
result = cudaMalloc(&outputBufferGPU, outputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating output memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBufferGPU = outputBufferGPU;
// Register the CUDA-allocated buffers.
uint64_t* inputBufferRegisteredPtr = NULL;
uint64_t* outputBufferRegisteredPtr = NULL;
err = cudlaMemRegister(devHandle, (uint64_t*)inputBufferGPU,
inputTensorDesc[0].size, &inputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering input memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
err =
cudlaMemRegister(devHandle, (uint64_t*)outputBufferGPU,
outputTensorDesc[0].size, &outputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("ALL MEMORY REGISTERED SUCCESSFULLY\n");
// Copy data from CPU buffers to GPU buffers.
result = cudaMemcpyAsync(inputBufferGPU, inputBuffer, inputTensorDesc[0].size,
cudaMemcpyHostToDevice, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memcpy for input\n");
cleanUp(&resourceList);
return 1;
}
result =
cudaMemsetAsync(outputBufferGPU, 0, outputTensorDesc[0].size, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memset for output\n");
cleanUp(&resourceList);
return 1;
}
// Enqueue a cuDLA task.
cudlaTask task;
task.moduleHandle = moduleHandle;
task.outputTensor = &outputBufferRegisteredPtr;
task.numOutputTensors = 1;
task.numInputTensors = 1;
task.inputTensor = &inputBufferRegisteredPtr;
task.waitEvents = NULL;
task.signalEvents = NULL;
err = cudlaSubmitTask(devHandle, &task, 1, stream, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in submitting task\n");
cleanUp(&resourceList);
return 1;
}
DPRINTF("SUBMIT IS DONE !!!\n");
// Wait for stream operations to finish and bring output buffer to CPU.
result =
cudaMemcpyAsync(outputBuffer, outputBufferGPU, outputTensorDesc[0].size,
cudaMemcpyDeviceToHost, stream);
if (result != cudaSuccess) {
if (result != cudaErrorExternalDevice) {
DPRINTF("Error in bringing result back to CPU\n");
cleanUp(&resourceList);
return 1;
} else {
cudlaStatus hwStatus = cudlaGetLastError(devHandle);
if (hwStatus != cudlaSuccess) {
DPRINTF("Asynchronous error in HW = %u\n", hwStatus);
}
}
}
result = cudaStreamSynchronize(stream);
if (result != cudaSuccess) {
DPRINTF("Error in synchronizing stream = %s\n", cudaGetErrorName(result));
if (result == cudaErrorExternalDevice) {
cudlaStatus hwStatus = cudlaGetLastError(devHandle);
if (hwStatus != cudlaSuccess) {
DPRINTF("Asynchronous error in HW = %u\n", hwStatus);
}
}
}
cleanUp(&resourceList);
DPRINTF("cuDLAErrorReporting DONE !!!\n");
return 0;
return 0;
}

View File

@@ -30,4 +30,3 @@ cudaStreamCreateWithFlags, cudaStreamDestroy, cudaFree, cudaGetErrorName, cudaSe
Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
## References (for more details)

View File

@@ -25,472 +25,463 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cudla.h"
#include "cuda_runtime.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/stat.h>
#include <fstream>
#include <sstream>
#include <sys/stat.h>
#include "cuda_runtime.h"
#include "cudla.h"
#define DPRINTF(...) printf(__VA_ARGS__)
static void printTensorDesc(cudlaModuleTensorDescriptor* tensorDesc) {
DPRINTF("\tTENSOR NAME : %s\n", tensorDesc->name);
DPRINTF("\tsize: %lu\n", tensorDesc->size);
static void printTensorDesc(cudlaModuleTensorDescriptor *tensorDesc)
{
DPRINTF("\tTENSOR NAME : %s\n", tensorDesc->name);
DPRINTF("\tsize: %lu\n", tensorDesc->size);
DPRINTF("\tdims: [%lu, %lu, %lu, %lu]\n", tensorDesc->n, tensorDesc->c,
tensorDesc->h, tensorDesc->w);
DPRINTF("\tdims: [%lu, %lu, %lu, %lu]\n", tensorDesc->n, tensorDesc->c, tensorDesc->h, tensorDesc->w);
DPRINTF("\tdata fmt: %d\n", tensorDesc->dataFormat);
DPRINTF("\tdata type: %d\n", tensorDesc->dataType);
DPRINTF("\tdata category: %d\n", tensorDesc->dataCategory);
DPRINTF("\tpixel fmt: %d\n", tensorDesc->pixelFormat);
DPRINTF("\tpixel mapping: %d\n", tensorDesc->pixelMapping);
DPRINTF("\tstride[0]: %d\n", tensorDesc->stride[0]);
DPRINTF("\tstride[1]: %d\n", tensorDesc->stride[1]);
DPRINTF("\tstride[2]: %d\n", tensorDesc->stride[2]);
DPRINTF("\tstride[3]: %d\n", tensorDesc->stride[3]);
DPRINTF("\tdata fmt: %d\n", tensorDesc->dataFormat);
DPRINTF("\tdata type: %d\n", tensorDesc->dataType);
DPRINTF("\tdata category: %d\n", tensorDesc->dataCategory);
DPRINTF("\tpixel fmt: %d\n", tensorDesc->pixelFormat);
DPRINTF("\tpixel mapping: %d\n", tensorDesc->pixelMapping);
DPRINTF("\tstride[0]: %d\n", tensorDesc->stride[0]);
DPRINTF("\tstride[1]: %d\n", tensorDesc->stride[1]);
DPRINTF("\tstride[2]: %d\n", tensorDesc->stride[2]);
DPRINTF("\tstride[3]: %d\n", tensorDesc->stride[3]);
}
static int initializeInputBuffers(char* filePath,
cudlaModuleTensorDescriptor* tensorDesc,
unsigned char* buf) {
// Read the file in filePath and fill up 'buf' according to format
// specified by the user.
static int initializeInputBuffers(char *filePath, cudlaModuleTensorDescriptor *tensorDesc, unsigned char *buf)
{
// Read the file in filePath and fill up 'buf' according to format
// specified by the user.
return 0;
return 0;
}
typedef struct {
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
unsigned char* loadableData;
cudaStream_t stream;
unsigned char* inputBuffer;
unsigned char* outputBuffer;
void* inputBufferGPU;
void* outputBufferGPU;
cudlaModuleTensorDescriptor* inputTensorDesc;
cudlaModuleTensorDescriptor* outputTensorDesc;
typedef struct
{
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
unsigned char *loadableData;
cudaStream_t stream;
unsigned char *inputBuffer;
unsigned char *outputBuffer;
void *inputBufferGPU;
void *outputBufferGPU;
cudlaModuleTensorDescriptor *inputTensorDesc;
cudlaModuleTensorDescriptor *outputTensorDesc;
} ResourceList;
void cleanUp(ResourceList* resourceList);
void cleanUp(ResourceList *resourceList);
void cleanUp(ResourceList* resourceList) {
if (resourceList->inputTensorDesc != NULL) {
free(resourceList->inputTensorDesc);
resourceList->inputTensorDesc = NULL;
}
if (resourceList->outputTensorDesc != NULL) {
free(resourceList->outputTensorDesc);
resourceList->outputTensorDesc = NULL;
}
void cleanUp(ResourceList *resourceList)
{
if (resourceList->inputTensorDesc != NULL) {
free(resourceList->inputTensorDesc);
resourceList->inputTensorDesc = NULL;
}
if (resourceList->outputTensorDesc != NULL) {
free(resourceList->outputTensorDesc);
resourceList->outputTensorDesc = NULL;
}
if (resourceList->loadableData != NULL) {
free(resourceList->loadableData);
resourceList->loadableData = NULL;
}
if (resourceList->loadableData != NULL) {
free(resourceList->loadableData);
resourceList->loadableData = NULL;
}
if (resourceList->moduleHandle != NULL) {
cudlaModuleUnload(resourceList->moduleHandle, 0);
resourceList->moduleHandle = NULL;
}
if (resourceList->moduleHandle != NULL) {
cudlaModuleUnload(resourceList->moduleHandle, 0);
resourceList->moduleHandle = NULL;
}
if (resourceList->devHandle != NULL) {
cudlaDestroyDevice(resourceList->devHandle);
resourceList->devHandle = NULL;
}
if (resourceList->devHandle != NULL) {
cudlaDestroyDevice(resourceList->devHandle);
resourceList->devHandle = NULL;
}
if (resourceList->inputBufferGPU != 0) {
cudaFree(resourceList->inputBufferGPU);
resourceList->inputBufferGPU = 0;
}
if (resourceList->outputBufferGPU != 0) {
cudaFree(resourceList->outputBufferGPU);
resourceList->outputBufferGPU = 0;
}
if (resourceList->inputBufferGPU != 0) {
cudaFree(resourceList->inputBufferGPU);
resourceList->inputBufferGPU = 0;
}
if (resourceList->outputBufferGPU != 0) {
cudaFree(resourceList->outputBufferGPU);
resourceList->outputBufferGPU = 0;
}
if (resourceList->inputBuffer != NULL) {
free(resourceList->inputBuffer);
resourceList->inputBuffer = NULL;
}
if (resourceList->outputBuffer != NULL) {
free(resourceList->outputBuffer);
resourceList->outputBuffer = NULL;
}
if (resourceList->inputBuffer != NULL) {
free(resourceList->inputBuffer);
resourceList->inputBuffer = NULL;
}
if (resourceList->outputBuffer != NULL) {
free(resourceList->outputBuffer);
resourceList->outputBuffer = NULL;
}
if (resourceList->stream != NULL) {
cudaStreamDestroy(resourceList->stream);
resourceList->stream = NULL;
}
if (resourceList->stream != NULL) {
cudaStreamDestroy(resourceList->stream);
resourceList->stream = NULL;
}
}
int main(int argc, char** argv) {
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
cudlaStatus err;
FILE* fp = NULL;
struct stat st;
size_t file_size;
size_t actually_read = 0;
unsigned char* loadableData = NULL;
int main(int argc, char **argv)
{
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
cudlaStatus err;
FILE *fp = NULL;
struct stat st;
size_t file_size;
size_t actually_read = 0;
unsigned char *loadableData = NULL;
cudaStream_t stream;
cudaError_t result;
const char* errPtr = NULL;
cudaStream_t stream;
cudaError_t result;
const char *errPtr = NULL;
ResourceList resourceList;
ResourceList resourceList;
memset(&resourceList, 0x00, sizeof(ResourceList));
memset(&resourceList, 0x00, sizeof(ResourceList));
if (argc != 3) {
DPRINTF("Usage : ./cuDLAHybridMode <loadable> <imageFile>\n");
return 1;
}
if (argc != 3) {
DPRINTF("Usage : ./cuDLAHybridMode <loadable> <imageFile>\n");
return 1;
}
// Read loadable into buffer.
fp = fopen(argv[1], "rb");
if (fp == NULL) {
DPRINTF("Cannot open file %s\n", argv[1]);
return 1;
}
// Read loadable into buffer.
fp = fopen(argv[1], "rb");
if (fp == NULL) {
DPRINTF("Cannot open file %s\n", argv[1]);
return 1;
}
if (stat(argv[1], &st) != 0) {
DPRINTF("Cannot stat file\n");
return 1;
}
if (stat(argv[1], &st) != 0) {
DPRINTF("Cannot stat file\n");
return 1;
}
file_size = st.st_size;
DPRINTF("The file size = %ld\n", file_size);
file_size = st.st_size;
DPRINTF("The file size = %ld\n", file_size);
loadableData = (unsigned char*)malloc(file_size);
if (loadableData == NULL) {
DPRINTF("Cannot Allocate memory for loadable\n");
return 1;
}
loadableData = (unsigned char *)malloc(file_size);
if (loadableData == NULL) {
DPRINTF("Cannot Allocate memory for loadable\n");
return 1;
}
actually_read = fread(loadableData, 1, file_size, fp);
if (actually_read != file_size) {
actually_read = fread(loadableData, 1, file_size, fp);
if (actually_read != file_size) {
free(loadableData);
DPRINTF("Read wrong size\n");
return 1;
}
fclose(fp);
resourceList.loadableData = loadableData;
// Initialize CUDA.
result = cudaFree(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaFree = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
result = cudaSetDevice(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaSetDevice = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
err = cudlaCreateDevice(0, &devHandle, CUDLA_CUDA_DLA);
if (err != cudlaSuccess) {
DPRINTF("Error in cuDLA create device = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Device created successfully\n");
resourceList.devHandle = devHandle;
err = cudlaModuleLoadFromMemory(devHandle, loadableData, file_size, &moduleHandle, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in cudlaModuleLoadFromMemory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
else {
DPRINTF("Successfully loaded module\n");
}
resourceList.moduleHandle = moduleHandle;
// Create CUDA stream.
result = cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cuda stream = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
resourceList.stream = stream;
// Get tensor attributes.
uint32_t numInputTensors = 0;
uint32_t numOutputTensors = 0;
cudlaModuleAttribute attribute;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_INPUT_TENSORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numInputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numInputTensors = attribute.numInputTensors;
DPRINTF("numInputTensors = %d\n", numInputTensors);
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_OUTPUT_TENSORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numOutputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numOutputTensors = attribute.numOutputTensors;
DPRINTF("numOutputTensors = %d\n", numOutputTensors);
cudlaModuleTensorDescriptor *inputTensorDesc =
(cudlaModuleTensorDescriptor *)malloc(sizeof(cudlaModuleTensorDescriptor) * numInputTensors);
cudlaModuleTensorDescriptor *outputTensorDesc =
(cudlaModuleTensorDescriptor *)malloc(sizeof(cudlaModuleTensorDescriptor) * numOutputTensors);
if ((inputTensorDesc == NULL) || (outputTensorDesc == NULL)) {
if (inputTensorDesc != NULL) {
free(inputTensorDesc);
inputTensorDesc = NULL;
}
if (outputTensorDesc != NULL) {
free(outputTensorDesc);
outputTensorDesc = NULL;
}
cleanUp(&resourceList);
return 1;
}
resourceList.inputTensorDesc = inputTensorDesc;
resourceList.outputTensorDesc = outputTensorDesc;
attribute.inputTensorDesc = inputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_INPUT_TENSOR_DESCRIPTORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting input tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing input tensor descriptor\n");
printTensorDesc(inputTensorDesc);
attribute.outputTensorDesc = outputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_OUTPUT_TENSOR_DESCRIPTORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting output tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing output tensor descriptor\n");
printTensorDesc(outputTensorDesc);
// Setup the input and output buffers which will be used as an input to CUDA.
unsigned char *inputBuffer = (unsigned char *)malloc(inputTensorDesc[0].size);
if (inputBuffer == NULL) {
DPRINTF("Error in allocating input memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBuffer = inputBuffer;
unsigned char *outputBuffer = (unsigned char *)malloc(outputTensorDesc[0].size);
if (outputBuffer == NULL) {
DPRINTF("Error in allocating output memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBuffer = outputBuffer;
memset(inputBuffer, 0x00, inputTensorDesc[0].size);
memset(outputBuffer, 0x00, outputTensorDesc[0].size);
// Fill up the buffers with data.
if (initializeInputBuffers(argv[2], inputTensorDesc, inputBuffer) != 0) {
DPRINTF("Error in initializing input buffer\n");
cleanUp(&resourceList);
return 1;
}
// Allocate memory on GPU.
void *inputBufferGPU;
void *outputBufferGPU;
result = cudaMalloc(&inputBufferGPU, inputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating input memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBufferGPU = inputBufferGPU;
result = cudaMalloc(&outputBufferGPU, outputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating output memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBufferGPU = outputBufferGPU;
// Register the CUDA-allocated buffers.
uint64_t *inputBufferRegisteredPtr = NULL;
uint64_t *outputBufferRegisteredPtr = NULL;
err =
cudlaMemRegister(devHandle, (uint64_t *)inputBufferGPU, inputTensorDesc[0].size, &inputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering input memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
err = cudlaMemRegister(
devHandle, (uint64_t *)outputBufferGPU, outputTensorDesc[0].size, &outputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("ALL MEMORY REGISTERED SUCCESSFULLY\n");
// Copy data from CPU buffers to GPU buffers.
result = cudaMemcpyAsync(inputBufferGPU, inputBuffer, inputTensorDesc[0].size, cudaMemcpyHostToDevice, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memcpy for input\n");
cleanUp(&resourceList);
return 1;
}
result = cudaMemsetAsync(outputBufferGPU, 0, outputTensorDesc[0].size, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memset for output\n");
cleanUp(&resourceList);
return 1;
}
// Enqueue a cuDLA task.
cudlaTask task;
task.moduleHandle = moduleHandle;
task.outputTensor = &outputBufferRegisteredPtr;
task.numOutputTensors = 1;
task.numInputTensors = 1;
task.inputTensor = &inputBufferRegisteredPtr;
task.waitEvents = NULL;
task.signalEvents = NULL;
err = cudlaSubmitTask(devHandle, &task, 1, stream, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in submitting task\n");
cleanUp(&resourceList);
return 1;
}
DPRINTF("SUBMIT IS DONE !!!\n");
// Wait for stream operations to finish and bring output buffer to CPU.
result = cudaMemcpyAsync(outputBuffer, outputBufferGPU, outputTensorDesc[0].size, cudaMemcpyDeviceToHost, stream);
if (result != cudaSuccess) {
DPRINTF("Error in bringing result back to CPU\n");
cleanUp(&resourceList);
return 1;
}
result = cudaStreamSynchronize(stream);
if (result != cudaSuccess) {
DPRINTF("Error in synchronizing stream\n");
cleanUp(&resourceList);
return 1;
}
// Output is available in outputBuffer.
// Teardown.
err = cudlaMemUnregister(devHandle, inputBufferRegisteredPtr);
if (err != cudlaSuccess) {
DPRINTF("Error in unregistering input memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
err = cudlaMemUnregister(devHandle, outputBufferRegisteredPtr);
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("ALL MEMORY UNREGISTERED SUCCESSFULLY\n");
free(inputTensorDesc);
free(outputTensorDesc);
free(loadableData);
DPRINTF("Read wrong size\n");
return 1;
}
fclose(fp);
free(inputBuffer);
free(outputBuffer);
cudaFree(inputBufferGPU);
cudaFree(outputBufferGPU);
resourceList.loadableData = loadableData;
resourceList.inputTensorDesc = NULL;
resourceList.outputTensorDesc = NULL;
resourceList.loadableData = NULL;
resourceList.inputBuffer = NULL;
resourceList.outputBuffer = NULL;
resourceList.inputBufferGPU = 0;
resourceList.outputBufferGPU = 0;
// Initialize CUDA.
result = cudaFree(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaFree = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
result = cudaSetDevice(0);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cudaSetDevice = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
err = cudlaCreateDevice(0, &devHandle, CUDLA_CUDA_DLA);
if (err != cudlaSuccess) {
DPRINTF("Error in cuDLA create device = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Device created successfully\n");
resourceList.devHandle = devHandle;
err = cudlaModuleLoadFromMemory(devHandle, loadableData, file_size,
&moduleHandle, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in cudlaModuleLoadFromMemory = %d\n", err);
cleanUp(&resourceList);
return 1;
} else {
DPRINTF("Successfully loaded module\n");
}
resourceList.moduleHandle = moduleHandle;
// Create CUDA stream.
result = cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in creating cuda stream = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
resourceList.stream = stream;
// Get tensor attributes.
uint32_t numInputTensors = 0;
uint32_t numOutputTensors = 0;
cudlaModuleAttribute attribute;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_INPUT_TENSORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numInputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numInputTensors = attribute.numInputTensors;
DPRINTF("numInputTensors = %d\n", numInputTensors);
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_NUM_OUTPUT_TENSORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting numOutputTensors = %d\n", err);
cleanUp(&resourceList);
return 1;
}
numOutputTensors = attribute.numOutputTensors;
DPRINTF("numOutputTensors = %d\n", numOutputTensors);
cudlaModuleTensorDescriptor* inputTensorDesc =
(cudlaModuleTensorDescriptor*)malloc(sizeof(cudlaModuleTensorDescriptor) *
numInputTensors);
cudlaModuleTensorDescriptor* outputTensorDesc =
(cudlaModuleTensorDescriptor*)malloc(sizeof(cudlaModuleTensorDescriptor) *
numOutputTensors);
if ((inputTensorDesc == NULL) || (outputTensorDesc == NULL)) {
if (inputTensorDesc != NULL) {
free(inputTensorDesc);
inputTensorDesc = NULL;
result = cudaStreamDestroy(stream);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in destroying cuda stream = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
if (outputTensorDesc != NULL) {
free(outputTensorDesc);
outputTensorDesc = NULL;
resourceList.stream = NULL;
err = cudlaModuleUnload(moduleHandle, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in cudlaModuleUnload = %d\n", err);
cleanUp(&resourceList);
return 1;
}
else {
DPRINTF("Successfully unloaded module\n");
}
cleanUp(&resourceList);
return 1;
}
resourceList.moduleHandle = NULL;
resourceList.inputTensorDesc = inputTensorDesc;
resourceList.outputTensorDesc = outputTensorDesc;
err = cudlaDestroyDevice(devHandle);
if (err != cudlaSuccess) {
DPRINTF("Error in cuDLA destroy device = %d\n", err);
return 1;
}
DPRINTF("Device destroyed successfully\n");
attribute.inputTensorDesc = inputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_INPUT_TENSOR_DESCRIPTORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting input tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing input tensor descriptor\n");
printTensorDesc(inputTensorDesc);
resourceList.devHandle = NULL;
attribute.outputTensorDesc = outputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_OUTPUT_TENSOR_DESCRIPTORS,
&attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting output tensor descriptor = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("Printing output tensor descriptor\n");
printTensorDesc(outputTensorDesc);
DPRINTF("cuDLAHybridMode DONE !!!\n");
// Setup the input and output buffers which will be used as an input to CUDA.
unsigned char* inputBuffer = (unsigned char*)malloc(inputTensorDesc[0].size);
if (inputBuffer == NULL) {
DPRINTF("Error in allocating input memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBuffer = inputBuffer;
unsigned char* outputBuffer =
(unsigned char*)malloc(outputTensorDesc[0].size);
if (outputBuffer == NULL) {
DPRINTF("Error in allocating output memory\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBuffer = outputBuffer;
memset(inputBuffer, 0x00, inputTensorDesc[0].size);
memset(outputBuffer, 0x00, outputTensorDesc[0].size);
// Fill up the buffers with data.
if (initializeInputBuffers(argv[2], inputTensorDesc, inputBuffer) != 0) {
DPRINTF("Error in initializing input buffer\n");
cleanUp(&resourceList);
return 1;
}
// Allocate memory on GPU.
void* inputBufferGPU;
void* outputBufferGPU;
result = cudaMalloc(&inputBufferGPU, inputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating input memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.inputBufferGPU = inputBufferGPU;
result = cudaMalloc(&outputBufferGPU, outputTensorDesc[0].size);
if (result != cudaSuccess) {
DPRINTF("Error in allocating output memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
resourceList.outputBufferGPU = outputBufferGPU;
// Register the CUDA-allocated buffers.
uint64_t* inputBufferRegisteredPtr = NULL;
uint64_t* outputBufferRegisteredPtr = NULL;
err = cudlaMemRegister(devHandle, (uint64_t*)inputBufferGPU,
inputTensorDesc[0].size, &inputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering input memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
err =
cudlaMemRegister(devHandle, (uint64_t*)outputBufferGPU,
outputTensorDesc[0].size, &outputBufferRegisteredPtr, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("ALL MEMORY REGISTERED SUCCESSFULLY\n");
// Copy data from CPU buffers to GPU buffers.
result = cudaMemcpyAsync(inputBufferGPU, inputBuffer, inputTensorDesc[0].size,
cudaMemcpyHostToDevice, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memcpy for input\n");
cleanUp(&resourceList);
return 1;
}
result =
cudaMemsetAsync(outputBufferGPU, 0, outputTensorDesc[0].size, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memset for output\n");
cleanUp(&resourceList);
return 1;
}
// Enqueue a cuDLA task.
cudlaTask task;
task.moduleHandle = moduleHandle;
task.outputTensor = &outputBufferRegisteredPtr;
task.numOutputTensors = 1;
task.numInputTensors = 1;
task.inputTensor = &inputBufferRegisteredPtr;
task.waitEvents = NULL;
task.signalEvents = NULL;
err = cudlaSubmitTask(devHandle, &task, 1, stream, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in submitting task\n");
cleanUp(&resourceList);
return 1;
}
DPRINTF("SUBMIT IS DONE !!!\n");
// Wait for stream operations to finish and bring output buffer to CPU.
result =
cudaMemcpyAsync(outputBuffer, outputBufferGPU, outputTensorDesc[0].size,
cudaMemcpyDeviceToHost, stream);
if (result != cudaSuccess) {
DPRINTF("Error in bringing result back to CPU\n");
cleanUp(&resourceList);
return 1;
}
result = cudaStreamSynchronize(stream);
if (result != cudaSuccess) {
DPRINTF("Error in synchronizing stream\n");
cleanUp(&resourceList);
return 1;
}
// Output is available in outputBuffer.
// Teardown.
err = cudlaMemUnregister(devHandle, inputBufferRegisteredPtr);
if (err != cudlaSuccess) {
DPRINTF("Error in unregistering input memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
err = cudlaMemUnregister(devHandle, outputBufferRegisteredPtr);
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
return 1;
}
DPRINTF("ALL MEMORY UNREGISTERED SUCCESSFULLY\n");
free(inputTensorDesc);
free(outputTensorDesc);
free(loadableData);
free(inputBuffer);
free(outputBuffer);
cudaFree(inputBufferGPU);
cudaFree(outputBufferGPU);
resourceList.inputTensorDesc = NULL;
resourceList.outputTensorDesc = NULL;
resourceList.loadableData = NULL;
resourceList.inputBuffer = NULL;
resourceList.outputBuffer = NULL;
resourceList.inputBufferGPU = 0;
resourceList.outputBufferGPU = 0;
result = cudaStreamDestroy(stream);
if (result != cudaSuccess) {
errPtr = cudaGetErrorName(result);
DPRINTF("Error in destroying cuda stream = %s\n", errPtr);
cleanUp(&resourceList);
return 1;
}
resourceList.stream = NULL;
err = cudlaModuleUnload(moduleHandle, 0);
if (err != cudlaSuccess) {
DPRINTF("Error in cudlaModuleUnload = %d\n", err);
cleanUp(&resourceList);
return 1;
} else {
DPRINTF("Successfully unloaded module\n");
}
resourceList.moduleHandle = NULL;
err = cudlaDestroyDevice(devHandle);
if (err != cudlaSuccess) {
DPRINTF("Error in cuDLA destroy device = %d\n", err);
return 1;
}
DPRINTF("Device destroyed successfully\n");
resourceList.devHandle = NULL;
DPRINTF("cuDLAHybridMode DONE !!!\n");
return 0;
return 0;
}

View File

@@ -30,4 +30,3 @@ cudaStreamCreateWithFlags, cudaStreamDestroy, cudaFree, cudaGetErrorName, cudaSe
Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
## References (for more details)

View File

@@ -25,28 +25,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "cudla.h"
#include "cuda_runtime.h"
#include "cudlaExternalEtbl.hpp"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/stat.h>
#include <fstream>
#include <sstream>
#include <sys/stat.h>
#define MAX_FILENAME_LEN 200
#include "cuda_runtime.h"
#include "cudla.h"
#include "cudlaExternalEtbl.hpp"
#define MAX_FILENAME_LEN 200
#define RESERVED_SUFFIX_LEN 10
#define DPRINTF(...) printf(__VA_ARGS__)
static void printTensorDesc(cudlaModuleTensorDescriptor* tensorDesc) {
static void printTensorDesc(cudlaModuleTensorDescriptor *tensorDesc)
{
DPRINTF("\tTENSOR NAME : %s\n", tensorDesc->name);
DPRINTF("\tsize: %lu\n", tensorDesc->size);
DPRINTF("\tdims: [%lu, %lu, %lu, %lu]\n", tensorDesc->n, tensorDesc->c,
tensorDesc->h, tensorDesc->w);
DPRINTF("\tdims: [%lu, %lu, %lu, %lu]\n", tensorDesc->n, tensorDesc->c, tensorDesc->h, tensorDesc->w);
DPRINTF("\tdata fmt: %d\n", tensorDesc->dataFormat);
DPRINTF("\tdata type: %d\n", tensorDesc->dataType);
@@ -59,33 +59,35 @@ static void printTensorDesc(cudlaModuleTensorDescriptor* tensorDesc) {
DPRINTF("\tstride[3]: %d\n", tensorDesc->stride[3]);
}
typedef struct {
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
unsigned char* loadableData;
cudaStream_t stream;
uint32_t numInputTensors;
uint32_t numOutputTensors;
uint32_t numOutputTaskStatistics;
unsigned char** inputBuffer;
unsigned char** outputBuffer;
unsigned char** statisticsOutputBuffer;
void** inputBufferGPU;
void** outputBufferGPU;
void** outputTaskStatisticsGPU;
void **csv;
cudlaModuleTensorDescriptor* inputTensorDesc;
cudlaModuleTensorDescriptor* outputTensorDesc;
cudlaModuleTensorDescriptor* outputTaskStatisticsDesc;
uint64_t** inputBufferRegisteredPtr;
uint64_t** outputBufferRegisteredPtr;
uint64_t** outputTaskStatisticsRegisteredPtr;
uint64_t** outputStatisticsBufferRegisteredPtr;
typedef struct
{
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
unsigned char *loadableData;
cudaStream_t stream;
uint32_t numInputTensors;
uint32_t numOutputTensors;
uint32_t numOutputTaskStatistics;
unsigned char **inputBuffer;
unsigned char **outputBuffer;
unsigned char **statisticsOutputBuffer;
void **inputBufferGPU;
void **outputBufferGPU;
void **outputTaskStatisticsGPU;
void **csv;
cudlaModuleTensorDescriptor *inputTensorDesc;
cudlaModuleTensorDescriptor *outputTensorDesc;
cudlaModuleTensorDescriptor *outputTaskStatisticsDesc;
uint64_t **inputBufferRegisteredPtr;
uint64_t **outputBufferRegisteredPtr;
uint64_t **outputTaskStatisticsRegisteredPtr;
uint64_t **outputStatisticsBufferRegisteredPtr;
} ResourceList;
void cleanUp(ResourceList* resourceList);
void cleanUp(ResourceList *resourceList);
void cleanUp(ResourceList* resourceList) {
void cleanUp(ResourceList *resourceList)
{
uint32_t ii = 0;
if (resourceList->inputTensorDesc != NULL) {
free(resourceList->inputTensorDesc);
@@ -152,8 +154,7 @@ void cleanUp(ResourceList* resourceList) {
if (resourceList->csv != NULL) {
for (ii = 0; ii < resourceList->numOutputTaskStatistics; ii++) {
if ((resourceList->csv)[ii] != NULL)
{
if ((resourceList->csv)[ii] != NULL) {
free((resourceList->csv)[ii]);
(resourceList->csv)[ii] = NULL;
}
@@ -175,8 +176,7 @@ void cleanUp(ResourceList* resourceList) {
if (resourceList->outputBuffer != NULL) {
for (ii = 0; ii < resourceList->numOutputTensors; ii++) {
if ((resourceList->outputBuffer)[ii] != NULL)
{
if ((resourceList->outputBuffer)[ii] != NULL) {
free((resourceList->outputBuffer)[ii]);
(resourceList->outputBuffer)[ii] = NULL;
}
@@ -221,42 +221,44 @@ void cleanUp(ResourceList* resourceList) {
resourceList->outputStatisticsBufferRegisteredPtr = NULL;
}
resourceList->numInputTensors = 0;
resourceList->numOutputTensors = 0;
resourceList->numInputTensors = 0;
resourceList->numOutputTensors = 0;
resourceList->numOutputTaskStatistics = 0;
}
int main(int argc, char** argv) {
int main(int argc, char **argv)
{
cudlaDevHandle devHandle;
cudlaModule moduleHandle;
cudlaStatus err;
uint32_t statSupport = 0;
uint32_t dlaFreqInMHz = 0;
FILE* fp = NULL;
struct stat st;
size_t file_size;
size_t actually_read = 0;
unsigned char *loadableData = NULL;
char filename[MAX_FILENAME_LEN];
const char* suffix = ".csv";
cudlaModule moduleHandle;
cudlaStatus err;
uint32_t statSupport = 0;
uint32_t dlaFreqInMHz = 0;
FILE *fp = NULL;
struct stat st;
size_t file_size;
size_t actually_read = 0;
unsigned char *loadableData = NULL;
char filename[MAX_FILENAME_LEN];
const char *suffix = ".csv";
cudaStream_t stream;
cudaError_t result;
const char* errPtr = NULL;
cudaError_t result;
const char *errPtr = NULL;
ResourceList resourceList;
memset(&resourceList, 0x00, sizeof(ResourceList));
if ((argc != 4) && (argc != 5)) {
DPRINTF("Usage : ./test_cudla_layerwise_stats_L0_hybrid_test1 <loadable> <freqMHZ> <statSupport> <filename prefix>\n");
DPRINTF("Usage : ./test_cudla_layerwise_stats_L0_hybrid_test1 <loadable> <freqMHZ> <statSupport> <filename "
"prefix>\n");
return 1;
}
if (argc == 5) {
if((strlen(argv[4])) > (MAX_FILENAME_LEN - RESERVED_SUFFIX_LEN))
{
DPRINTF("Filename prefix length is too big, greater than maximum permissible prefix length of %u \n",(MAX_FILENAME_LEN - RESERVED_SUFFIX_LEN));
if ((strlen(argv[4])) > (MAX_FILENAME_LEN - RESERVED_SUFFIX_LEN)) {
DPRINTF("Filename prefix length is too big, greater than maximum permissible prefix length of %u \n",
(MAX_FILENAME_LEN - RESERVED_SUFFIX_LEN));
return 1;
}
}
@@ -277,7 +279,7 @@ int main(int argc, char** argv) {
DPRINTF("The file size = %ld\n", file_size);
dlaFreqInMHz = atoi(argv[2]);
statSupport = atoi(argv[3]);
statSupport = atoi(argv[3]);
loadableData = (unsigned char *)malloc(file_size);
if (loadableData == NULL) {
@@ -286,7 +288,7 @@ int main(int argc, char** argv) {
}
actually_read = fread(loadableData, 1, file_size, fp);
if ( actually_read != file_size ) {
if (actually_read != file_size) {
free(loadableData);
DPRINTF("Read wrong size\n");
return 1;
@@ -327,8 +329,9 @@ int main(int argc, char** argv) {
DPRINTF("Error in cudlaModuleLoadFromMemory = %d\n", err);
cleanUp(&resourceList);
return 1;
} else {
DPRINTF("Successfully loaded module\n");
}
else {
DPRINTF("Successfully loaded module\n");
}
resourceList.moduleHandle = moduleHandle;
@@ -346,8 +349,8 @@ int main(int argc, char** argv) {
resourceList.stream = stream;
// Get tensor attributes.
uint32_t numInputTensors = 0;
uint32_t numOutputTensors = 0;
uint32_t numInputTensors = 0;
uint32_t numOutputTensors = 0;
uint32_t numOutputTaskStatistics = 0;
cudlaModuleAttribute attribute;
@@ -382,20 +385,20 @@ int main(int argc, char** argv) {
numOutputTaskStatistics = attribute.numOutputTensors;
DPRINTF("numOutputTaskStatistics = %d\n", numOutputTaskStatistics);
if(numOutputTaskStatistics == 0) {
if (numOutputTaskStatistics == 0) {
DPRINTF("Layerwise stats is not supported for this Loadable \n");
cleanUp(&resourceList);
return 1;
}
resourceList.numInputTensors = numInputTensors;
resourceList.numOutputTensors = numOutputTensors;
resourceList.numInputTensors = numInputTensors;
resourceList.numOutputTensors = numOutputTensors;
resourceList.numOutputTaskStatistics = numOutputTaskStatistics;
cudlaModuleTensorDescriptor* inputTensorDesc =
(cudlaModuleTensorDescriptor*)malloc(sizeof(cudlaModuleTensorDescriptor)*numInputTensors);
cudlaModuleTensorDescriptor* outputTensorDesc =
(cudlaModuleTensorDescriptor*)malloc(sizeof(cudlaModuleTensorDescriptor)*numOutputTensors);
cudlaModuleTensorDescriptor *inputTensorDesc =
(cudlaModuleTensorDescriptor *)malloc(sizeof(cudlaModuleTensorDescriptor) * numInputTensors);
cudlaModuleTensorDescriptor *outputTensorDesc =
(cudlaModuleTensorDescriptor *)malloc(sizeof(cudlaModuleTensorDescriptor) * numOutputTensors);
if ((inputTensorDesc == NULL) || (outputTensorDesc == NULL)) {
if (inputTensorDesc != NULL) {
@@ -412,11 +415,11 @@ int main(int argc, char** argv) {
return 1;
}
resourceList.inputTensorDesc = inputTensorDesc;
resourceList.inputTensorDesc = inputTensorDesc;
resourceList.outputTensorDesc = outputTensorDesc;
cudlaModuleTensorDescriptor* outputTaskStatisticsDesc =
(cudlaModuleTensorDescriptor*)malloc(sizeof(cudlaModuleTensorDescriptor)*numOutputTaskStatistics);
cudlaModuleTensorDescriptor *outputTaskStatisticsDesc =
(cudlaModuleTensorDescriptor *)malloc(sizeof(cudlaModuleTensorDescriptor) * numOutputTaskStatistics);
if (outputTaskStatisticsDesc == NULL) {
free(outputTaskStatisticsDesc);
outputTaskStatisticsDesc = NULL;
@@ -427,9 +430,7 @@ int main(int argc, char** argv) {
resourceList.outputTaskStatisticsDesc = outputTaskStatisticsDesc;
attribute.inputTensorDesc = inputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle,
CUDLA_INPUT_TENSOR_DESCRIPTORS,
&attribute);
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_INPUT_TENSOR_DESCRIPTORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting input tensor descriptor = %d\n", err);
cleanUp(&resourceList);
@@ -439,9 +440,7 @@ int main(int argc, char** argv) {
printTensorDesc(inputTensorDesc);
attribute.outputTensorDesc = outputTensorDesc;
err = cudlaModuleGetAttributes(moduleHandle,
CUDLA_OUTPUT_TENSOR_DESCRIPTORS,
&attribute);
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_OUTPUT_TENSOR_DESCRIPTORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting output tensor descriptor = %d\n", err);
cleanUp(&resourceList);
@@ -451,9 +450,7 @@ int main(int argc, char** argv) {
printTensorDesc(outputTensorDesc);
attribute.outputTensorDesc = outputTaskStatisticsDesc;
err = cudlaModuleGetAttributes(moduleHandle,
CUDLA_OUTPUT_TASK_STATISTICS_DESCRIPTORS,
&attribute);
err = cudlaModuleGetAttributes(moduleHandle, CUDLA_OUTPUT_TASK_STATISTICS_DESCRIPTORS, &attribute);
if (err != cudlaSuccess) {
DPRINTF("Error in getting task statistics descriptor = %d\n", err);
cleanUp(&resourceList);
@@ -462,20 +459,20 @@ int main(int argc, char** argv) {
DPRINTF("Printing output task statistics descriptor size\n");
for (uint32_t ii = 0; ii < numOutputTaskStatistics; ii++) {
DPRINTF("The size of %u descriptor is %lu\n", ii,outputTaskStatisticsDesc[ii].size);
DPRINTF("The size of %u descriptor is %lu\n", ii, outputTaskStatisticsDesc[ii].size);
}
// Setup the input and output buffers which will be used as an input to CUDA.
unsigned char** inputBuffer = (unsigned char **)malloc(sizeof(unsigned char *)*numInputTensors);
unsigned char **inputBuffer = (unsigned char **)malloc(sizeof(unsigned char *) * numInputTensors);
if (inputBuffer == NULL) {
DPRINTF("Error in allocating memory for input buffer array\n");
cleanUp(&resourceList);
return 1;
}
memset(inputBuffer, 0x00, sizeof(unsigned char *)*numInputTensors);
memset(inputBuffer, 0x00, sizeof(unsigned char *) * numInputTensors);
resourceList.inputBuffer = inputBuffer;
for (uint32_t ii = 0; ii < numInputTensors; ii++) {
inputBuffer[ii] = (unsigned char* )malloc(inputTensorDesc[ii].size);
inputBuffer[ii] = (unsigned char *)malloc(inputTensorDesc[ii].size);
if (inputBuffer[ii] == NULL) {
DPRINTF("Error in allocating input memory\n");
cleanUp(&resourceList);
@@ -484,17 +481,17 @@ int main(int argc, char** argv) {
memset(inputBuffer[ii], 0x01, inputTensorDesc[ii].size);
}
unsigned char** outputBuffer = (unsigned char **)malloc(sizeof(unsigned char *)*numOutputTensors);
unsigned char **outputBuffer = (unsigned char **)malloc(sizeof(unsigned char *) * numOutputTensors);
if (outputBuffer == NULL) {
DPRINTF("Error in allocating memory for output buffer array\n");
cleanUp(&resourceList);
return 1;
}
memset(outputBuffer, 0x00, sizeof(unsigned char *)*numOutputTensors);
memset(outputBuffer, 0x00, sizeof(unsigned char *) * numOutputTensors);
resourceList.outputBuffer = outputBuffer;
for (uint32_t ii = 0; ii < numOutputTensors; ii++) {
outputBuffer[ii] = (unsigned char* )malloc(outputTensorDesc[ii].size);
outputBuffer[ii] = (unsigned char *)malloc(outputTensorDesc[ii].size);
if (outputBuffer[ii] == NULL) {
DPRINTF("Error in allocating output memory\n");
cleanUp(&resourceList);
@@ -503,17 +500,18 @@ int main(int argc, char** argv) {
memset(outputBuffer[ii], 0x00, outputTensorDesc[ii].size);
}
unsigned char** statisticsOutputBuffer = (unsigned char **)malloc(sizeof(unsigned char *)*numOutputTaskStatistics);
unsigned char **statisticsOutputBuffer =
(unsigned char **)malloc(sizeof(unsigned char *) * numOutputTaskStatistics);
if (statisticsOutputBuffer == NULL) {
DPRINTF("Error in allocating memory for output buffer array\n");
cleanUp(&resourceList);
return 1;
}
memset(statisticsOutputBuffer, 0x00, sizeof(unsigned char *)*numOutputTaskStatistics);
memset(statisticsOutputBuffer, 0x00, sizeof(unsigned char *) * numOutputTaskStatistics);
resourceList.statisticsOutputBuffer = statisticsOutputBuffer;
for (uint32_t ii = 0; ii < numOutputTaskStatistics; ii++) {
statisticsOutputBuffer[ii] = (unsigned char* )malloc(outputTaskStatisticsDesc[ii].size);
statisticsOutputBuffer[ii] = (unsigned char *)malloc(outputTaskStatisticsDesc[ii].size);
if (outputBuffer[ii] == NULL) {
DPRINTF("Error in allocating output memory\n");
cleanUp(&resourceList);
@@ -523,32 +521,31 @@ int main(int argc, char** argv) {
}
// Allocate memory on GPU.
void** inputBufferGPU = (void **)malloc(sizeof(void *)*numInputTensors);
void **inputBufferGPU = (void **)malloc(sizeof(void *) * numInputTensors);
if (inputBufferGPU == NULL) {
DPRINTF("Error in allocating memory for input buffer GPU array\n");
cleanUp(&resourceList);
return 1;
}
memset(inputBufferGPU, 0x00, sizeof(void *)*numInputTensors);
memset(inputBufferGPU, 0x00, sizeof(void *) * numInputTensors);
resourceList.inputBufferGPU = inputBufferGPU;
for (uint32_t ii = 0; ii < numInputTensors; ii++) {
result = cudaMalloc(&(inputBufferGPU[ii]), inputTensorDesc[ii].size);
if (result != cudaSuccess)
{
if (result != cudaSuccess) {
DPRINTF("Error in allocating input memory on GPU\n");
cleanUp(&resourceList);
return 1;
}
}
void** outputBufferGPU = (void **)malloc(sizeof(void *)*numOutputTensors);
void **outputBufferGPU = (void **)malloc(sizeof(void *) * numOutputTensors);
if (outputBufferGPU == NULL) {
DPRINTF("Error in allocating memory for output buffer GPU array\n");
cleanUp(&resourceList);
return 1;
}
memset(outputBufferGPU, 0x00, sizeof(void *)*numOutputTensors);
memset(outputBufferGPU, 0x00, sizeof(void *) * numOutputTensors);
resourceList.outputBufferGPU = outputBufferGPU;
for (uint32_t ii = 0; ii < numOutputTensors; ii++) {
@@ -560,13 +557,13 @@ int main(int argc, char** argv) {
}
}
void** outputTaskStatisticsGPU = (void **)malloc(sizeof(void *)*numOutputTaskStatistics);
void **outputTaskStatisticsGPU = (void **)malloc(sizeof(void *) * numOutputTaskStatistics);
if (outputTaskStatisticsGPU == NULL) {
DPRINTF("Error in allocating memory for output task statistics GPU array\n");
cleanUp(&resourceList);
return 1;
}
memset(outputTaskStatisticsGPU, 0x00, sizeof(void *)*numOutputTaskStatistics);
memset(outputTaskStatisticsGPU, 0x00, sizeof(void *) * numOutputTaskStatistics);
resourceList.outputTaskStatisticsGPU = outputTaskStatisticsGPU;
for (uint32_t ii = 0; ii < numOutputTaskStatistics; ii++) {
@@ -578,11 +575,12 @@ int main(int argc, char** argv) {
}
}
uint64_t** inputBufferRegisteredPtr = (uint64_t **)malloc(sizeof(uint64_t*)*numInputTensors);
uint64_t** outputBufferRegisteredPtr = (uint64_t **)malloc(sizeof(uint64_t*)*numOutputTensors);
uint64_t** outputTaskStatisticsRegisteredPtr = (uint64_t **)malloc(sizeof(uint64_t*)*numOutputTaskStatistics);
uint64_t **inputBufferRegisteredPtr = (uint64_t **)malloc(sizeof(uint64_t *) * numInputTensors);
uint64_t **outputBufferRegisteredPtr = (uint64_t **)malloc(sizeof(uint64_t *) * numOutputTensors);
uint64_t **outputTaskStatisticsRegisteredPtr = (uint64_t **)malloc(sizeof(uint64_t *) * numOutputTaskStatistics);
if ((inputBufferRegisteredPtr == NULL) || (outputBufferRegisteredPtr == NULL) || (outputTaskStatisticsRegisteredPtr == NULL)) {
if ((inputBufferRegisteredPtr == NULL) || (outputBufferRegisteredPtr == NULL)
|| (outputTaskStatisticsRegisteredPtr == NULL)) {
if (inputBufferRegisteredPtr != NULL) {
free(inputBufferRegisteredPtr);
inputBufferRegisteredPtr = NULL;
@@ -602,17 +600,14 @@ int main(int argc, char** argv) {
return 1;
}
resourceList.inputBufferRegisteredPtr = inputBufferRegisteredPtr;
resourceList.outputBufferRegisteredPtr = outputBufferRegisteredPtr;
resourceList.inputBufferRegisteredPtr = inputBufferRegisteredPtr;
resourceList.outputBufferRegisteredPtr = outputBufferRegisteredPtr;
resourceList.outputTaskStatisticsRegisteredPtr = outputTaskStatisticsRegisteredPtr;
// Register the CUDA-allocated buffers.
for (uint32_t ii = 0; ii < numInputTensors; ii++) {
err = cudlaMemRegister(devHandle,
(uint64_t* )(inputBufferGPU[ii]),
inputTensorDesc[ii].size,
&(inputBufferRegisteredPtr[ii]),
0);
err = cudlaMemRegister(
devHandle, (uint64_t *)(inputBufferGPU[ii]), inputTensorDesc[ii].size, &(inputBufferRegisteredPtr[ii]), 0);
if (err != cudlaSuccess) {
DPRINTF("Error in registering input memory = %d\n", err);
cleanUp(&resourceList);
@@ -622,7 +617,7 @@ int main(int argc, char** argv) {
for (uint32_t ii = 0; ii < numOutputTensors; ii++) {
err = cudlaMemRegister(devHandle,
(uint64_t* )(outputBufferGPU[ii]),
(uint64_t *)(outputBufferGPU[ii]),
outputTensorDesc[ii].size,
&(outputBufferRegisteredPtr[ii]),
0);
@@ -635,7 +630,7 @@ int main(int argc, char** argv) {
for (uint32_t ii = 0; ii < numOutputTaskStatistics; ii++) {
err = cudlaMemRegister(devHandle,
(uint64_t* )(outputTaskStatisticsGPU[ii]),
(uint64_t *)(outputTaskStatisticsGPU[ii]),
outputTaskStatisticsDesc[ii].size,
&(outputTaskStatisticsRegisteredPtr[ii]),
CUDLA_TASK_STATISTICS);
@@ -650,7 +645,8 @@ int main(int argc, char** argv) {
// Copy data from CPU buffers to GPU buffers.
for (uint32_t ii = 0; ii < numInputTensors; ii++) {
result = cudaMemcpyAsync(inputBufferGPU[ii], inputBuffer[ii], inputTensorDesc[ii].size, cudaMemcpyHostToDevice, stream);
result = cudaMemcpyAsync(
inputBufferGPU[ii], inputBuffer[ii], inputTensorDesc[ii].size, cudaMemcpyHostToDevice, stream);
if (result != cudaSuccess) {
DPRINTF("Error in enqueueing memcpy for input\n");
cleanUp(&resourceList);
@@ -677,36 +673,37 @@ int main(int argc, char** argv) {
}
uint64_t *outputStatisticsBufferRegisteredPtr[numOutputTensors + numOutputTaskStatistics] = {0};
uint32_t index = 0;
for (; index < numOutputTensors ; index++) {
uint32_t index = 0;
for (; index < numOutputTensors; index++) {
outputStatisticsBufferRegisteredPtr[index] = ((outputBufferRegisteredPtr[index]));
}
for (uint32_t jj=0; jj < numOutputTaskStatistics ; jj++) {
for (uint32_t jj = 0; jj < numOutputTaskStatistics; jj++) {
outputStatisticsBufferRegisteredPtr[index++] = ((outputTaskStatisticsRegisteredPtr[jj]));
}
// Enqueue a cuDLA task.
cudlaTask task;
task.moduleHandle = moduleHandle;
task.outputTensor = (uint64_t * const*)&outputStatisticsBufferRegisteredPtr;
task.outputTensor = (uint64_t *const *)&outputStatisticsBufferRegisteredPtr;
if(statSupport == 1) {
if (statSupport == 1) {
task.numOutputTensors = (numOutputTensors + numOutputTaskStatistics);
DPRINTF("Layerwise profiling is requested \n");
} else {
task.numOutputTensors = numOutputTensors;
DPRINTF("Layerwise profiling is not requested \n");
}
else {
task.numOutputTensors = numOutputTensors;
DPRINTF("Layerwise profiling is not requested \n");
}
task.numInputTensors = numInputTensors;
task.inputTensor = inputBufferRegisteredPtr;
task.waitEvents = NULL;
task.signalEvents = NULL;
task.inputTensor = inputBufferRegisteredPtr;
task.waitEvents = NULL;
task.signalEvents = NULL;
err = cudlaSubmitTask(devHandle, &task, 1, stream, 0);
if (err != cudlaSuccess) {
DPRINTF("no of output tensor %u \n",(task.numOutputTensors));
DPRINTF("no of output tensor %u \n", (task.numOutputTensors));
DPRINTF("Error in submitting task\n");
cleanUp(&resourceList);
return 1;
@@ -722,8 +719,8 @@ int main(int argc, char** argv) {
// Wait for stream operations to finish and bring output buffer to CPU.
for (uint32_t ii = 0; ii < numOutputTensors; ii++) {
result = cudaMemcpyAsync(outputBuffer[ii], outputBufferGPU[ii],
outputTensorDesc[ii].size, cudaMemcpyDeviceToHost, stream);
result = cudaMemcpyAsync(
outputBuffer[ii], outputBufferGPU[ii], outputTensorDesc[ii].size, cudaMemcpyDeviceToHost, stream);
if (result != cudaSuccess) {
DPRINTF("Error in bringing result back to CPU\n");
cleanUp(&resourceList);
@@ -738,11 +735,14 @@ int main(int argc, char** argv) {
return 1;
}
if(statSupport == 1) {
if (statSupport == 1) {
// copy statistics data to cpu
for (uint32_t ii = 0; ii < numOutputTaskStatistics; ii++) {
result = cudaMemcpyAsync(statisticsOutputBuffer[ii], outputTaskStatisticsGPU[ii],
outputTaskStatisticsDesc[ii].size, cudaMemcpyDeviceToHost, stream);
result = cudaMemcpyAsync(statisticsOutputBuffer[ii],
outputTaskStatisticsGPU[ii],
outputTaskStatisticsDesc[ii].size,
cudaMemcpyDeviceToHost,
stream);
if (result != cudaSuccess) {
DPRINTF("Error in bringing result back to CPU\n");
cleanUp(&resourceList);
@@ -760,35 +760,36 @@ int main(int argc, char** argv) {
// To get the last index of the filename prefix in which statistics will be dumped
uint32_t index = 0;
if (argc == 5) {
while(argv[4][index]!='\0') {
while (argv[4][index] != '\0') {
index++;
}
}
const cudlaExternalEtbl* etbl = NULL;
if (cudlaGetExternalExportTable(&etbl,0) != cudlaSuccess) {
const cudlaExternalEtbl *etbl = NULL;
if (cudlaGetExternalExportTable(&etbl, 0) != cudlaSuccess) {
DPRINTF("Error in getting export table\n");
cleanUp(&resourceList);
return 1;
}
void** csv = (void **)malloc(sizeof(void *)*numOutputTaskStatistics);
void **csv = (void **)malloc(sizeof(void *) * numOutputTaskStatistics);
if (csv == NULL) {
DPRINTF("Error in allocating memory for csv stream\n");
cleanUp(&resourceList);
return 1;
}
memset(csv, 0x00, sizeof(void *)*numOutputTaskStatistics);
memset(csv, 0x00, sizeof(void *) * numOutputTaskStatistics);
resourceList.csv = csv;
for (uint32_t ii = 0; ii < numOutputTaskStatistics; ii++) {
cudlaTranslateCsvAttribute csvAttribute;
uint64_t csvStreamLength = 0;
uint64_t csvStreamLength = 0;
err = etbl->etiTranslateStats(devHandle,statisticsOutputBuffer[ii],dlaFreqInMHz,ii,CUDLA_GET_CSV_LENGTH,&csvAttribute);
csv[ii] = (void* )malloc(csvAttribute.csvStreamLength);
err = etbl->etiTranslateStats(
devHandle, statisticsOutputBuffer[ii], dlaFreqInMHz, ii, CUDLA_GET_CSV_LENGTH, &csvAttribute);
csv[ii] = (void *)malloc(csvAttribute.csvStreamLength);
csvStreamLength = csvAttribute.csvStreamLength;
DPRINTF("size for statistics buffer %u is %lu \n",ii,csvStreamLength);
DPRINTF("size for statistics buffer %u is %lu \n", ii, csvStreamLength);
if (csv[ii] == NULL) {
DPRINTF("Error in allocating memory for csv stream\n");
@@ -798,7 +799,8 @@ int main(int argc, char** argv) {
memset(csv[ii], 0x00, csvAttribute.csvStreamLength);
csvAttribute.csvStreamStats = csv[ii];
err = etbl->etiTranslateStats(devHandle,statisticsOutputBuffer[ii],dlaFreqInMHz,ii,CUDLA_GET_CSV_STATS,&csvAttribute);
err = etbl->etiTranslateStats(
devHandle, statisticsOutputBuffer[ii], dlaFreqInMHz, ii, CUDLA_GET_CSV_STATS, &csvAttribute);
if (err != cudlaSuccess) {
DPRINTF("Error in translating stats\n");
cleanUp(&resourceList);
@@ -806,7 +808,7 @@ int main(int argc, char** argv) {
}
if (argc == 5) {
sprintf(filename,"%s%u%s", argv[4],(ii+1),suffix);
sprintf(filename, "%s%u%s", argv[4], (ii + 1), suffix);
fp = fopen(filename, "w+");
if (fp == NULL) {
DPRINTF("Cannot open file %s\n", filename);
@@ -814,23 +816,23 @@ int main(int argc, char** argv) {
return 1;
}
uint32_t ret_val = fwrite(csv[ii],sizeof(char),csvStreamLength,fp);
if(ret_val != csvStreamLength) {
uint32_t ret_val = fwrite(csv[ii], sizeof(char), csvStreamLength, fp);
if (ret_val != csvStreamLength) {
DPRINTF("number of elements written to file is %u \n", ret_val);
cleanUp(&resourceList);
return 1;
}
fclose(fp);
} else {
DPRINTF("%s \n",(char *)csv[ii]);
}
else {
DPRINTF("%s \n", (char *)csv[ii]);
}
}
}
// unregister the CUDA-allocated buffers.
for (uint32_t ii = 0; ii < numInputTensors; ii++) {
err = cudlaMemUnregister(devHandle,
(inputBufferRegisteredPtr[ii]));
err = cudlaMemUnregister(devHandle, (inputBufferRegisteredPtr[ii]));
if (err != cudlaSuccess) {
DPRINTF("Error in registering input memory = %d\n", err);
cleanUp(&resourceList);
@@ -839,8 +841,7 @@ int main(int argc, char** argv) {
}
for (uint32_t ii = 0; ii < numOutputTensors; ii++) {
err = cudlaMemUnregister(devHandle,
(outputBufferRegisteredPtr[ii]));
err = cudlaMemUnregister(devHandle, (outputBufferRegisteredPtr[ii]));
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
@@ -849,8 +850,7 @@ int main(int argc, char** argv) {
}
for (uint32_t ii = 0; ii < numOutputTaskStatistics; ii++) {
err = cudlaMemUnregister(devHandle,
(outputTaskStatisticsRegisteredPtr[ii]));
err = cudlaMemUnregister(devHandle, (outputTaskStatisticsRegisteredPtr[ii]));
if (err != cudlaSuccess) {
DPRINTF("Error in registering output memory = %d\n", err);
cleanUp(&resourceList);
@@ -875,7 +875,8 @@ int main(int argc, char** argv) {
DPRINTF("Error in cudlaModuleUnload = %d\n", err);
cleanUp(&resourceList);
return 1;
} else {
}
else {
DPRINTF("Successfully unloaded module\n");
}

View File

@@ -31,4 +31,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -31,4 +31,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

File diff suppressed because it is too large Load Diff

View File

@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.8](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -27,162 +27,165 @@
#include "cudaNvSciBufMultiplanar.h"
NvSciBufModule module;
NvSciBufObj buffObj;
CUuuid uuid;
NvSciBufObj buffObj;
CUuuid uuid;
void flipBits(uint8_t *pBuff, uint32_t size) {
void flipBits(uint8_t *pBuff, uint32_t size)
{
for (uint32_t i = 0; i < size; i++) {
pBuff[i] = (~pBuff[i]);
}
}
// Compare input and generated image files
void compareFiles(std::string &path1, std::string &path2) {
bool result = true;
void compareFiles(std::string &path1, std::string &path2)
{
bool result = true;
FILE *fp1, *fp2;
int ch1, ch2;
int ch1, ch2;
fp1 = fopen(path1.c_str(), "rb");
fp2 = fopen(path2.c_str(), "rb");
if (!fp1) {
result = false;
printf("File %s open failed in %s line %d\n", path1.c_str(), __FILE__, __LINE__);
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
if (!fp2) {
result = false;
printf("File %s open failed in %s line %d\n", path2.c_str(), __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
do {
ch1 = getc(fp1);
do {
ch1 = getc(fp1);
ch2 = getc(fp2);
if (ch1 != ch2) {
result = false;
if (ch1 != ch2) {
result = false;
break;
}
} while(ch1 != EOF && ch2 != EOF);
}
} while (ch1 != EOF && ch2 != EOF);
if (result) {
printf("Input file : %s and output file : %s match SUCCESS\n", path1.c_str(), path2.c_str());
}
}
else {
printf("Input file : %s and output file : %s match FAILURE\n", path1.c_str(), path2.c_str());
}
if (fp1) {
fclose(fp1);
}
if (fp2) {
fclose(fp2);
}
}
}
void Caller::init() {
void Caller::init()
{
checkNvSciErrors(NvSciBufAttrListCreate(module, &attrList));
attrListOut = NULL;
}
void Caller::deinit() {
void Caller::deinit()
{
NvSciBufAttrListFree(attrList);
checkCudaErrors(cudaDestroyExternalMemory(extMem));
}
// Set NvSciBufImage attribute values in the attribute list
void Caller::setAttrListImageMultiPlanes(int imageWidth, int imageHeight) {
NvSciBufType bufType = NvSciBufType_Image;
NvSciBufAttrValImageLayoutType layout = NvSciBufImage_BlockLinearType;
bool cpuAccessFlag = false;
NvSciBufAttrValAccessPerm perm = NvSciBufAccessPerm_ReadWrite;
NvSciRmGpuId gpuid;
bool vpr = false;
int32_t planeCount = PLANAR_NUM_PLANES;
int drvVersion;
// Set NvSciBufImage attribute values in the attribute list
void Caller::setAttrListImageMultiPlanes(int imageWidth, int imageHeight)
{
NvSciBufType bufType = NvSciBufType_Image;
NvSciBufAttrValImageLayoutType layout = NvSciBufImage_BlockLinearType;
bool cpuAccessFlag = false;
NvSciBufAttrValAccessPerm perm = NvSciBufAccessPerm_ReadWrite;
NvSciRmGpuId gpuid;
bool vpr = false;
int32_t planeCount = PLANAR_NUM_PLANES;
int drvVersion;
// Dimensions of the imported image in the YUV 420 planar format
int32_t planeWidths[] = {imageWidth, imageWidth/2, imageWidth/2};
int32_t planeHeights[] = {imageHeight, imageHeight/2, imageHeight/2};
int32_t planeWidths[] = {imageWidth, imageWidth / 2, imageWidth / 2};
int32_t planeHeights[] = {imageHeight, imageHeight / 2, imageHeight / 2};
NvSciBufAttrKeyValuePair keyPair;
NvSciBufAttrKeyValuePair pairArray[ATTR_SIZE];
NvSciBufAttrValColorFmt planeColorFmts[] =
{ NvSciColor_Y8, NvSciColor_V8, NvSciColor_U8 };
NvSciBufAttrValImageScanType planeScanType[] =
{ NvSciBufScan_ProgressiveType };
NvSciBufAttrValColorFmt planeColorFmts[] = {NvSciColor_Y8, NvSciColor_V8, NvSciColor_U8};
NvSciBufAttrValImageScanType planeScanType[] = {NvSciBufScan_ProgressiveType};
memcpy(&gpuid.bytes, &uuid.bytes, sizeof(uuid.bytes));
NvSciBufAttrKeyValuePair imgBuffAttrsArr[] = {
{ NvSciBufGeneralAttrKey_Types, &bufType, sizeof(bufType) },
{ NvSciBufGeneralAttrKey_NeedCpuAccess, &cpuAccessFlag,
sizeof(cpuAccessFlag) },
{ NvSciBufGeneralAttrKey_RequiredPerm, &perm, sizeof(perm) },
{ NvSciBufGeneralAttrKey_GpuId, &gpuid, sizeof(gpuid) },
{ NvSciBufImageAttrKey_Layout, &layout, sizeof(layout) },
{ NvSciBufImageAttrKey_VprFlag, &vpr, sizeof(vpr) },
{ NvSciBufImageAttrKey_PlaneCount, &planeCount, sizeof(planeCount) },
{ NvSciBufImageAttrKey_PlaneColorFormat, planeColorFmts,
sizeof(planeColorFmts) },
{ NvSciBufImageAttrKey_PlaneWidth, planeWidths, sizeof(planeWidths) },
{ NvSciBufImageAttrKey_PlaneHeight, planeHeights,
sizeof(planeHeights) },
{ NvSciBufImageAttrKey_PlaneScanType, planeScanType,
sizeof(planeScanType) },
{NvSciBufGeneralAttrKey_Types, &bufType, sizeof(bufType)},
{NvSciBufGeneralAttrKey_NeedCpuAccess, &cpuAccessFlag, sizeof(cpuAccessFlag)},
{NvSciBufGeneralAttrKey_RequiredPerm, &perm, sizeof(perm)},
{NvSciBufGeneralAttrKey_GpuId, &gpuid, sizeof(gpuid)},
{NvSciBufImageAttrKey_Layout, &layout, sizeof(layout)},
{NvSciBufImageAttrKey_VprFlag, &vpr, sizeof(vpr)},
{NvSciBufImageAttrKey_PlaneCount, &planeCount, sizeof(planeCount)},
{NvSciBufImageAttrKey_PlaneColorFormat, planeColorFmts, sizeof(planeColorFmts)},
{NvSciBufImageAttrKey_PlaneWidth, planeWidths, sizeof(planeWidths)},
{NvSciBufImageAttrKey_PlaneHeight, planeHeights, sizeof(planeHeights)},
{NvSciBufImageAttrKey_PlaneScanType, planeScanType, sizeof(planeScanType)},
};
std::vector<NvSciBufAttrKeyValuePair> imgBuffAttrsVec(imgBuffAttrsArr,
imgBuffAttrsArr+(sizeof(imgBuffAttrsArr)/sizeof(imgBuffAttrsArr[0])));
std::vector<NvSciBufAttrKeyValuePair> imgBuffAttrsVec(
imgBuffAttrsArr, imgBuffAttrsArr + (sizeof(imgBuffAttrsArr) / sizeof(imgBuffAttrsArr[0])));
memset(pairArray, 0, sizeof(NvSciBufAttrKeyValuePair) * imgBuffAttrsVec.size());
std::copy(imgBuffAttrsVec.begin(), imgBuffAttrsVec.end(), pairArray);
checkNvSciErrors(NvSciBufAttrListSetAttrs(attrList, pairArray, imgBuffAttrsVec.size()));
}
cudaNvSciBufMultiplanar::cudaNvSciBufMultiplanar(size_t width, size_t height, std::vector<int> &deviceIds)
: imageWidth(width),
imageHeight(height) {
mCudaDeviceId = deviceIds[0];
attrListReconciled = NULL;
attrListConflict = NULL;
checkNvSciErrors(NvSciBufModuleOpen(&module));
initCuda(mCudaDeviceId);
}
: imageWidth(width)
, imageHeight(height)
{
mCudaDeviceId = deviceIds[0];
attrListReconciled = NULL;
attrListConflict = NULL;
checkNvSciErrors(NvSciBufModuleOpen(&module));
initCuda(mCudaDeviceId);
}
void cudaNvSciBufMultiplanar::initCuda(int devId) {
int major = 0, minor = 0, drvVersion;
void cudaNvSciBufMultiplanar::initCuda(int devId)
{
int major = 0, minor = 0, drvVersion;
NvSciRmGpuId gpuid;
checkCudaErrors(cudaSetDevice(mCudaDeviceId));
checkCudaErrors(cudaDeviceGetAttribute(
&major, cudaDevAttrComputeCapabilityMajor, mCudaDeviceId));
checkCudaErrors(cudaDeviceGetAttribute(
&minor, cudaDevAttrComputeCapabilityMinor, mCudaDeviceId));
printf(
"[cudaNvSciBufMultiplanar] GPU Device %d: \"%s\" with compute capability "
"%d.%d\n\n",
mCudaDeviceId, _ConvertSMVer2ArchName(major, minor), major, minor);
checkCudaErrors(cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, mCudaDeviceId));
checkCudaErrors(cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, mCudaDeviceId));
printf("[cudaNvSciBufMultiplanar] GPU Device %d: \"%s\" with compute capability "
"%d.%d\n\n",
mCudaDeviceId,
_ConvertSMVer2ArchName(major, minor),
major,
minor);
checkCudaDrvErrors(cuDriverGetVersion(&drvVersion));
if (drvVersion <= 11030) {
checkCudaDrvErrors(cuDeviceGetUuid(&uuid, devId));
} else {
}
else {
checkCudaDrvErrors(cuDeviceGetUuid_v2(&uuid, devId));
}
}
/*
/*
Caller1 flips a YUV image which is allocated to nvscibuf APIs and copied into CUDA Array.
It is mapped to CUDA surface and bit flip is done. Caller2 in the same thread copies
It is mapped to CUDA surface and bit flip is done. Caller2 in the same thread copies
CUDA Array to a YUV image file. The original image is compared with the double bit
flipped image.
*/
void cudaNvSciBufMultiplanar::runCudaNvSciBufPlanar(std::string &imageFilename, std::string &imageFilenameOut) {
void cudaNvSciBufMultiplanar::runCudaNvSciBufPlanar(std::string &imageFilename, std::string &imageFilenameOut)
{
cudaArray_t levelArray1[PLANAR_NUM_PLANES];
cudaArray_t levelArray2[PLANAR_NUM_PLANES];
Caller caller1;
Caller caller2;
Caller caller1;
Caller caller2;
int numPlanes = PLANAR_NUM_PLANES;
caller1.init();
@@ -191,23 +194,23 @@ void cudaNvSciBufMultiplanar::runCudaNvSciBufPlanar(std::string &imageFilename,
// Set NvSciBufImage attribute values in the attribute list
caller1.setAttrListImageMultiPlanes(imageWidth, imageHeight);
caller2.setAttrListImageMultiPlanes(imageWidth, imageHeight);
// Reconcile attribute lists and allocate NvSciBuf object
reconcileAttrList(&caller1.attrList, &caller2.attrList);
reconcileAttrList(&caller1.attrList, &caller2.attrList);
caller1.copyExtMemToMultiPlanarArrays();
for (int i = 0; i < numPlanes; i++) {
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelArray1[i], caller1.multiPlanarArray[i], 0));
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelArray1[i], caller1.multiPlanarArray[i], 0));
}
caller1.copyYUVToCudaArrayAndFlipBits(imageFilename, levelArray1);
caller2.copyExtMemToMultiPlanarArrays();
for (int i = 0; i < numPlanes; i++) {
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelArray2[i], caller2.multiPlanarArray[i], 0));
checkCudaErrors(cudaGetMipmappedArrayLevel(&levelArray2[i], caller2.multiPlanarArray[i], 0));
}
// Maps cudaArray to surface memory and launches a kernel to flip bits
launchFlipSurfaceBitsKernel(levelArray2, caller2.multiPlanarWidth, caller2.multiPlanarHeight, numPlanes);
// Synchronization can be done using nvSciSync when non CUDA callers and cross-process signaler-waiter
// Synchronization can be done using nvSciSync when non CUDA callers and cross-process signaler-waiter
// applications are involved. Please refer to the cudaNvSci sample library for more details.
checkCudaDrvErrors(cuCtxSynchronize());
printf("Bit flip of the surface memory done\n");
@@ -225,66 +228,69 @@ void cudaNvSciBufMultiplanar::runCudaNvSciBufPlanar(std::string &imageFilename,
}
// Map NvSciBufObj to cudaMipmappedArray
void Caller::copyExtMemToMultiPlanarArrays() {
void Caller::copyExtMemToMultiPlanarArrays()
{
checkNvSciErrors(NvSciBufObjGetAttrList(buffObj, &attrListOut));
memset(pairArrayOut, 0, sizeof(NvSciBufAttrKeyValuePair) * PLANE_ATTR_SIZE);
cudaExternalMemoryHandleDesc memHandleDesc;
cudaExternalMemoryHandleDesc memHandleDesc;
cudaExternalMemoryMipmappedArrayDesc mipmapDesc = {0};
cudaChannelFormatDesc desc = {0};
cudaExtent extent = {0};
pairArrayOut[PLANE_SIZE].key = NvSciBufImageAttrKey_Size; // Datatype: @c uint64_t
pairArrayOut[PLANE_ALIGNED_SIZE].key = NvSciBufImageAttrKey_PlaneAlignedSize; // Datatype: @c uint64_t[]
pairArrayOut[PLANE_OFFSET].key = NvSciBufImageAttrKey_PlaneOffset; // Datatype: @c uint64_t[]
pairArrayOut[PLANE_HEIGHT].key = NvSciBufImageAttrKey_PlaneHeight; // Datatype: @c uint32_t[]
pairArrayOut[PLANE_WIDTH].key = NvSciBufImageAttrKey_PlaneWidth; // Datatype: @c int32_t[]
pairArrayOut[PLANE_CHANNEL_COUNT].key = NvSciBufImageAttrKey_PlaneChannelCount; // Datatype: @c uint8_t
pairArrayOut[PLANE_BITS_PER_PIXEL].key = NvSciBufImageAttrKey_PlaneBitsPerPixel;// Datatype: @c uint32_t[]
pairArrayOut[PLANE_COUNT].key = NvSciBufImageAttrKey_PlaneCount; // Datatype: @c uint32_t
checkNvSciErrors(NvSciBufAttrListGetAttrs(attrListOut, pairArrayOut, (PLANE_ATTR_SIZE)));
uint64_t size = *(uint64_t*)pairArrayOut[PLANE_SIZE].value;
uint64_t *planeAlignedSize = (uint64_t*)pairArrayOut[PLANE_ALIGNED_SIZE].value;
int32_t *planeWidth = (int32_t*)pairArrayOut[PLANE_WIDTH].value;
int32_t *planeHeight = (int32_t*)pairArrayOut[PLANE_HEIGHT].value;
uint64_t *planeOffset = (uint64_t*)pairArrayOut[PLANE_OFFSET].value;
uint8_t planeChannelCount = *(uint8_t*)pairArrayOut[PLANE_CHANNEL_COUNT].value;
uint32_t *planeBitsPerPixel = (uint32_t*)pairArrayOut[PLANE_BITS_PER_PIXEL].value;
uint32_t planeCount = *(uint32_t*)pairArrayOut[PLANE_COUNT].value;
cudaChannelFormatDesc desc = {0};
cudaExtent extent = {0};
pairArrayOut[PLANE_SIZE].key = NvSciBufImageAttrKey_Size; // Datatype: @c uint64_t
pairArrayOut[PLANE_ALIGNED_SIZE].key = NvSciBufImageAttrKey_PlaneAlignedSize; // Datatype: @c uint64_t[]
pairArrayOut[PLANE_OFFSET].key = NvSciBufImageAttrKey_PlaneOffset; // Datatype: @c uint64_t[]
pairArrayOut[PLANE_HEIGHT].key = NvSciBufImageAttrKey_PlaneHeight; // Datatype: @c uint32_t[]
pairArrayOut[PLANE_WIDTH].key = NvSciBufImageAttrKey_PlaneWidth; // Datatype: @c int32_t[]
pairArrayOut[PLANE_CHANNEL_COUNT].key = NvSciBufImageAttrKey_PlaneChannelCount; // Datatype: @c uint8_t
pairArrayOut[PLANE_BITS_PER_PIXEL].key = NvSciBufImageAttrKey_PlaneBitsPerPixel; // Datatype: @c uint32_t[]
pairArrayOut[PLANE_COUNT].key = NvSciBufImageAttrKey_PlaneCount; // Datatype: @c uint32_t
checkNvSciErrors(NvSciBufAttrListGetAttrs(attrListOut, pairArrayOut, (PLANE_ATTR_SIZE)));
uint64_t size = *(uint64_t *)pairArrayOut[PLANE_SIZE].value;
uint64_t *planeAlignedSize = (uint64_t *)pairArrayOut[PLANE_ALIGNED_SIZE].value;
int32_t *planeWidth = (int32_t *)pairArrayOut[PLANE_WIDTH].value;
int32_t *planeHeight = (int32_t *)pairArrayOut[PLANE_HEIGHT].value;
uint64_t *planeOffset = (uint64_t *)pairArrayOut[PLANE_OFFSET].value;
uint8_t planeChannelCount = *(uint8_t *)pairArrayOut[PLANE_CHANNEL_COUNT].value;
uint32_t *planeBitsPerPixel = (uint32_t *)pairArrayOut[PLANE_BITS_PER_PIXEL].value;
uint32_t planeCount = *(uint32_t *)pairArrayOut[PLANE_COUNT].value;
numPlanes = planeCount;
for (int i = 0; i < numPlanes; i++) {
multiPlanarWidth[i] = planeWidth[i];
multiPlanarWidth[i] = planeWidth[i];
multiPlanarHeight[i] = planeHeight[i];
}
memset(&memHandleDesc, 0, sizeof(memHandleDesc));
memHandleDesc.type = cudaExternalMemoryHandleTypeNvSciBuf;
memHandleDesc.type = cudaExternalMemoryHandleTypeNvSciBuf;
memHandleDesc.handle.nvSciBufObject = buffObj;
memHandleDesc.size = size;
memHandleDesc.size = size;
checkCudaErrors(cudaImportExternalMemory(&extMem, &memHandleDesc));
desc = cudaCreateChannelDesc(planeBitsPerPixel[0], 0, 0, 0, cudaChannelFormatKindUnsigned);
memset(&mipmapDesc, 0, sizeof(mipmapDesc));
mipmapDesc.numLevels = 1;
mipmapDesc.numLevels = 1;
for (int i = 0; i < numPlanes; i++) {
for (int i = 0; i < numPlanes; i++) {
memset(&extent, 0, sizeof(extent));
extent.width = planeWidth[i];
extent.height = planeHeight[i];
extent.depth = 0;
mipmapDesc.offset = planeOffset[i];
extent.width = planeWidth[i];
extent.height = planeHeight[i];
extent.depth = 0;
mipmapDesc.offset = planeOffset[i];
mipmapDesc.formatDesc = desc;
mipmapDesc.extent = extent;
mipmapDesc.flags = cudaArraySurfaceLoadStore;;
mipmapDesc.extent = extent;
mipmapDesc.flags = cudaArraySurfaceLoadStore;
;
checkCudaErrors(cudaExternalMemoryGetMappedMipmappedArray(&multiPlanarArray[i], extMem, &mipmapDesc));
}
}
void cudaNvSciBufMultiplanar::reconcileAttrList(NvSciBufAttrList *attrList1, NvSciBufAttrList *attrList2) {
attrList[0] = *attrList1;
attrList[1] = *attrList2;
void cudaNvSciBufMultiplanar::reconcileAttrList(NvSciBufAttrList *attrList1, NvSciBufAttrList *attrList2)
{
attrList[0] = *attrList1;
attrList[1] = *attrList2;
bool isReconciled = false;
checkNvSciErrors(NvSciBufAttrListReconcile(attrList, 2, &attrListReconciled, &attrListConflict));
@@ -294,38 +300,40 @@ void cudaNvSciBufMultiplanar::reconcileAttrList(NvSciBufAttrList *attrList1, NvS
}
// YUV 420 image is flipped and copied to cuda Array which is mapped to nvsciBuf
void Caller::copyYUVToCudaArrayAndFlipBits(std::string &path, cudaArray_t *cudaArr) {
FILE *fp = NULL;
void Caller::copyYUVToCudaArrayAndFlipBits(std::string &path, cudaArray_t *cudaArr)
{
FILE *fp = NULL;
uint8_t *pYBuff, *pUBuff, *pVBuff, *pChroma;
uint8_t *pBuff = NULL;
uint8_t *pBuff = NULL;
uint32_t uvOffset[numPlanes] = {0}, copyWidthInBytes[numPlanes] = {0}, copyHeight[numPlanes] = {0};
uint32_t width = multiPlanarWidth[0];
uint32_t width = multiPlanarWidth[0];
uint32_t height = multiPlanarHeight[0];
fp = fopen(path.c_str(), "rb");
if (!fp) {
printf("CudaProducer: Error opening file: %s in %s line %d\n", path.c_str(), __FILE__, __LINE__);
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
pBuff = (uint8_t*)malloc((width * height * PLANAR_CHROMA_WIDTH_ORDER * PLANAR_CHROMA_HEIGHT_ORDER) * sizeof(unsigned char));
pBuff = (uint8_t *)malloc((width * height * PLANAR_CHROMA_WIDTH_ORDER * PLANAR_CHROMA_HEIGHT_ORDER)
* sizeof(unsigned char));
if (!pBuff) {
printf("CudaProducer: Failed to allocate image buffer in %s line %d\n", __FILE__, __LINE__);
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
// Y V U order in the buffer. Fully planar formats use
// Y V U order in the buffer. Fully planar formats use
// three planes to store the Y, Cb and Cr components separately.
pYBuff = pBuff;
pYBuff = pBuff;
pVBuff = pYBuff + width * height;
pUBuff = pVBuff + (width / PLANAR_CHROMA_WIDTH_ORDER) * (height / PLANAR_CHROMA_HEIGHT_ORDER);
pUBuff = pVBuff + (width / PLANAR_CHROMA_WIDTH_ORDER) * (height / PLANAR_CHROMA_HEIGHT_ORDER);
for (uint32_t i = 0; i < height; i++) {
if (fread(pYBuff, width, 1, fp) != 1) {
printf("ReadYUVFrame: Error reading file: %s in %s line %d\n", path.c_str(), __FILE__, __LINE__);
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
flipBits(pYBuff, width);
pYBuff += width;
}
pChroma = pVBuff;
for (uint32_t i = 0; i < height / PLANAR_CHROMA_HEIGHT_ORDER; i++) {
if (fread(pChroma, width / PLANAR_CHROMA_WIDTH_ORDER, 1, fp) != 1) {
@@ -335,7 +343,7 @@ void Caller::copyYUVToCudaArrayAndFlipBits(std::string &path, cudaArray_t *cudaA
flipBits(pChroma, width);
pChroma += width / PLANAR_CHROMA_WIDTH_ORDER;
}
pChroma = pUBuff;
for (uint32_t i = 0; i < height / PLANAR_CHROMA_HEIGHT_ORDER; i++) {
if (fread(pChroma, width / PLANAR_CHROMA_WIDTH_ORDER, 1, fp) != 1) {
@@ -345,22 +353,26 @@ void Caller::copyYUVToCudaArrayAndFlipBits(std::string &path, cudaArray_t *cudaA
flipBits(pChroma, width);
pChroma += width / PLANAR_CHROMA_WIDTH_ORDER;
}
uvOffset[0] = 0;
copyHeight[0] = height;
copyHeight[1] = height / PLANAR_CHROMA_HEIGHT_ORDER;
copyHeight[2] = height / PLANAR_CHROMA_HEIGHT_ORDER;
uvOffset[0] = 0;
copyHeight[0] = height;
copyHeight[1] = height / PLANAR_CHROMA_HEIGHT_ORDER;
copyHeight[2] = height / PLANAR_CHROMA_HEIGHT_ORDER;
copyWidthInBytes[0] = width;
// Width of the second and third planes is half of the first plane.
copyWidthInBytes[1] = width / PLANAR_CHROMA_WIDTH_ORDER;
copyWidthInBytes[2] = width / PLANAR_CHROMA_WIDTH_ORDER;
uvOffset[1] = width * height;
uvOffset[2] = uvOffset[1] + (width / PLANAR_CHROMA_WIDTH_ORDER) * (height / PLANAR_CHROMA_HEIGHT_ORDER);
// Width of the second and third planes is half of the first plane.
copyWidthInBytes[1] = width / PLANAR_CHROMA_WIDTH_ORDER;
copyWidthInBytes[2] = width / PLANAR_CHROMA_WIDTH_ORDER;
uvOffset[1] = width * height;
uvOffset[2] = uvOffset[1] + (width / PLANAR_CHROMA_WIDTH_ORDER) * (height / PLANAR_CHROMA_HEIGHT_ORDER);
for (int i = 0; i < numPlanes; i++) {
checkCudaDrvErrors(cuCtxSynchronize());
checkCudaErrors(cudaMemcpy2DToArray(
cudaArr[i], 0, 0, (void *)(pBuff + uvOffset[i]), copyWidthInBytes[i],
copyWidthInBytes[i], copyHeight[i],
cudaMemcpyHostToDevice));
checkCudaErrors(cudaMemcpy2DToArray(cudaArr[i],
0,
0,
(void *)(pBuff + uvOffset[i]),
copyWidthInBytes[i],
copyWidthInBytes[i],
copyHeight[i],
cudaMemcpyHostToDevice));
}
if (fp) {
@@ -374,61 +386,67 @@ void Caller::copyYUVToCudaArrayAndFlipBits(std::string &path, cudaArray_t *cudaA
printf("Image %s copied to CUDA Array and bit flip done\n", path.c_str());
}
// Copy Cuda Array in YUV 420 format to a file
void Caller::copyCudaArrayToYUV(std::string &path, cudaArray_t *cudaArr) {
FILE *fp = NULL;
int bufferSize;
uint32_t width = multiPlanarWidth[0];
uint32_t height = multiPlanarHeight[0];
uint32_t copyWidthInBytes=0, copyHeight=0;
// Copy Cuda Array in YUV 420 format to a file
void Caller::copyCudaArrayToYUV(std::string &path, cudaArray_t *cudaArr)
{
FILE *fp = NULL;
int bufferSize;
uint32_t width = multiPlanarWidth[0];
uint32_t height = multiPlanarHeight[0];
uint32_t copyWidthInBytes = 0, copyHeight = 0;
uint8_t *pCudaCopyMem = NULL;
fp = fopen(path.c_str(), "wb+");
if (!fp) {
printf("WriteFrame: file open failed %s in %s line %d\n", path.c_str(), __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
for (int i = 0; i < numPlanes; i++) {
if (i == 0) {
bufferSize = width * height;
bufferSize = width * height;
copyWidthInBytes = width;
copyHeight = height;
copyHeight = height;
pCudaCopyMem = (uint8_t *)malloc(bufferSize);
if (pCudaCopyMem == NULL) {
printf("pCudaCopyMem malloc failed in %s line %d\n", __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
}
}
else {
bufferSize = ((height / PLANAR_CHROMA_HEIGHT_ORDER) * (width / PLANAR_CHROMA_WIDTH_ORDER));
bufferSize = ((height / PLANAR_CHROMA_HEIGHT_ORDER) * (width / PLANAR_CHROMA_WIDTH_ORDER));
copyWidthInBytes = width / PLANAR_CHROMA_WIDTH_ORDER;
copyHeight = height / PLANAR_CHROMA_HEIGHT_ORDER;
copyHeight = height / PLANAR_CHROMA_HEIGHT_ORDER;
}
memset(pCudaCopyMem, 0, bufferSize);
checkCudaErrors(cudaMemcpy2DFromArray(
(void *)pCudaCopyMem, copyWidthInBytes, cudaArr[i], 0, 0,
copyWidthInBytes, copyHeight,
cudaMemcpyDeviceToHost));
checkCudaErrors(cudaMemcpy2DFromArray((void *)pCudaCopyMem,
copyWidthInBytes,
cudaArr[i],
0,
0,
copyWidthInBytes,
copyHeight,
cudaMemcpyDeviceToHost));
checkCudaDrvErrors(cuCtxSynchronize());
if (fwrite(pCudaCopyMem, bufferSize, 1, fp) != 1) {
printf("Cuda consumer: output file write failed in %s line %d\n", __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
}
printf("Output file : %s saved\n", path.c_str());
if (fp) {
fclose(fp);
fp = NULL;
}
}
}
void cudaNvSciBufMultiplanar::tearDown(Caller *caller1, Caller *caller2) {
void cudaNvSciBufMultiplanar::tearDown(Caller *caller1, Caller *caller2)
{
caller1->deinit();
caller2->deinit();
NvSciBufObjFree(buffObj);

View File

@@ -27,61 +27,69 @@
#ifndef CUDA_NVSCIBUF_MULTIPLANAR_H
#define CUDA_NVSCIBUF_MULTIPLANAR_H
#include <cuda.h>
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include <nvscibuf.h>
#include <vector>
#include <cuda.h>
#include <helper_cuda.h>
#define PLANAR_NUM_PLANES 3
#define PLANAR_CHROMA_WIDTH_ORDER 2
#define PLANAR_NUM_PLANES 3
#define PLANAR_CHROMA_WIDTH_ORDER 2
#define PLANAR_CHROMA_HEIGHT_ORDER 2
#define ATTR_SIZE 20
#define ATTR_SIZE 20
#define DEFAULT_GPU 0
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf( \
"NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, __LINE__, _status, NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf("NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, \
__LINE__, \
_status, \
NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define checkCudaDrvErrors(call) \
do { \
CUresult err = call; \
if (CUDA_SUCCESS != err) { \
const char *errorStr = NULL; \
cuGetErrorString(err, &errorStr); \
printf( \
"checkCudaDrvErrors() Driver API error" \
" = %04d \"%s\" from file <%s>, " \
"line %i.\n", \
err, errorStr, __FILE__, __LINE__); \
exit(EXIT_FAILURE); \
} \
} while (0)
do { \
CUresult err = call; \
if (CUDA_SUCCESS != err) { \
const char *errorStr = NULL; \
cuGetErrorString(err, &errorStr); \
printf("checkCudaDrvErrors() Driver API error" \
" = %04d \"%s\" from file <%s>, " \
"line %i.\n", \
err, \
errorStr, \
__FILE__, \
__LINE__); \
exit(EXIT_FAILURE); \
} \
} while (0)
extern void launchFlipSurfaceBitsKernel(cudaArray_t *levelArray, int32_t *multiPlanarWidth,
int32_t *multiPlanarHeight, int numPlanes);
extern void launchFlipSurfaceBitsKernel(cudaArray_t *levelArray,
int32_t *multiPlanarWidth,
int32_t *multiPlanarHeight,
int numPlanes);
class Caller {
class Caller
{
private:
NvSciBufAttrList attrListOut;
NvSciBufAttrList attrListOut;
NvSciBufAttrKeyValuePair pairArrayOut[ATTR_SIZE];
cudaExternalMemory_t extMem;
int32_t numPlanes;
cudaExternalMemory_t extMem;
int32_t numPlanes;
public:
NvSciBufAttrList attrList;
NvSciBufAttrList attrList;
cudaMipmappedArray_t multiPlanarArray[PLANAR_NUM_PLANES];
int32_t multiPlanarWidth[PLANAR_NUM_PLANES];
int32_t multiPlanarHeight[PLANAR_NUM_PLANES];
int32_t multiPlanarWidth[PLANAR_NUM_PLANES];
int32_t multiPlanarHeight[PLANAR_NUM_PLANES];
void init();
void deinit();
@@ -92,15 +100,17 @@ public:
};
class cudaNvSciBufMultiplanar {
class cudaNvSciBufMultiplanar
{
private:
size_t imageWidth;
size_t imageHeight;
int mCudaDeviceId;
int deviceCnt;
size_t imageWidth;
size_t imageHeight;
int mCudaDeviceId;
int deviceCnt;
NvSciBufAttrList attrList[2];
NvSciBufAttrList attrListReconciled;
NvSciBufAttrList attrListConflict;
public:
cudaNvSciBufMultiplanar(size_t imageWidth, size_t imageHeight, std::vector<int> &deviceIds);
void initCuda(int devId);
@@ -110,15 +120,15 @@ public:
};
enum NvSciBufImageAttributes {
PLANE_SIZE,
PLANE_SIZE,
PLANE_ALIGNED_SIZE,
PLANE_OFFSET,
PLANE_HEIGHT,
PLANE_WIDTH,
PLANE_CHANNEL_COUNT,
PLANE_HEIGHT,
PLANE_WIDTH,
PLANE_CHANNEL_COUNT,
PLANE_BITS_PER_PIXEL,
PLANE_COUNT,
PLANE_ATTR_SIZE
};
#endif // CUDA_NVSCIBUF_MULTIPLANAR_H
#endif // CUDA_NVSCIBUF_MULTIPLANAR_H

View File

@@ -27,13 +27,14 @@
#include <cuda.h>
#include <helper_cuda.h>
static __global__ void flipSurfaceBits(cudaSurfaceObject_t surfObj, int width, int height) {
char data;
static __global__ void flipSurfaceBits(cudaSurfaceObject_t surfObj, int width, int height)
{
char data;
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x < width && y < height) {
// Read from input surface
surf2Dread(&data, surfObj, x, y);
surf2Dread(&data, surfObj, x, y);
// Write to output surface
data = ~data;
surf2Dwrite(data, surfObj, x, y);
@@ -41,24 +42,23 @@ static __global__ void flipSurfaceBits(cudaSurfaceObject_t surfObj, int width, i
}
// Copy cudaArray to surface memory and launch the CUDA kernel
void launchFlipSurfaceBitsKernel(
cudaArray_t *levelArray,
int32_t *multiPlanarWidth,
int32_t *multiPlanarHeight,
int numPlanes) {
void launchFlipSurfaceBitsKernel(cudaArray_t *levelArray,
int32_t *multiPlanarWidth,
int32_t *multiPlanarHeight,
int numPlanes)
{
cudaSurfaceObject_t surfObject[numPlanes] = {0};
cudaResourceDesc resDesc;
for (int i = 0; i < numPlanes; i++) {
cudaResourceDesc resDesc;
for (int i = 0; i < numPlanes; i++) {
memset(&resDesc, 0, sizeof(resDesc));
resDesc.resType = cudaResourceTypeArray;
resDesc.resType = cudaResourceTypeArray;
resDesc.res.array.array = levelArray[i];
checkCudaErrors(cudaCreateSurfaceObject(&surfObject[i], &resDesc));
dim3 threadsperBlock(16, 16);
dim3 numBlocks((multiPlanarWidth[i] + threadsperBlock.x - 1) / threadsperBlock.x,
(multiPlanarHeight[i] + threadsperBlock.y - 1) / threadsperBlock.y);
(multiPlanarHeight[i] + threadsperBlock.y - 1) / threadsperBlock.y);
flipSurfaceBits<<<numBlocks, threadsperBlock>>>(surfObject[i], multiPlanarWidth[i], multiPlanarHeight[i]);
}
}

View File

@@ -25,48 +25,48 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cuda.h>
#include <vector>
#include "cudaNvSciBufMultiplanar.h"
#include <helper_image.h>
#include <vector>
#include "cudaNvSciBufMultiplanar.h"
#define MAX_FILE_SIZE 100
int main(int argc, const char **argv) {
int numOfGPUs = 0;
std::vector<int> deviceIds;
(cudaGetDeviceCount(&numOfGPUs));
int main(int argc, const char **argv)
{
int numOfGPUs = 0;
std::vector<int> deviceIds;
(cudaGetDeviceCount(&numOfGPUs));
printf("%d GPUs found\n", numOfGPUs);
if (!numOfGPUs) {
exit(EXIT_WAIVED);
} else {
for (int devID = 0; devID < numOfGPUs; devID++) {
int major = 0, minor = 0;
(cudaDeviceGetAttribute(
&major, cudaDevAttrComputeCapabilityMajor, devID));
(cudaDeviceGetAttribute(
&minor, cudaDevAttrComputeCapabilityMinor, devID));
if (major >= 6) {
deviceIds.push_back(devID);
}
printf("%d GPUs found\n", numOfGPUs);
if (!numOfGPUs) {
exit(EXIT_WAIVED);
}
if (deviceIds.size() == 0) {
printf(
"cudaNvSciBufMultiplanar requires one or more GPUs of Pascal(SM 6.0) or higher "
"archs\nWaiving..\n");
exit(EXIT_WAIVED);
else {
for (int devID = 0; devID < numOfGPUs; devID++) {
int major = 0, minor = 0;
(cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, devID));
(cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, devID));
if (major >= 6) {
deviceIds.push_back(devID);
}
}
if (deviceIds.size() == 0) {
printf("cudaNvSciBufMultiplanar requires one or more GPUs of Pascal(SM 6.0) or higher "
"archs\nWaiving..\n");
exit(EXIT_WAIVED);
}
}
}
std::string image_filename = sdkFindFilePath("yuv_planar_img1.yuv", argv[0]);
std::string image_filename_out = "image_out.yuv";
uint32_t imageWidth = 720;
uint32_t imageHeight = 480;
std::string image_filename = sdkFindFilePath("yuv_planar_img1.yuv", argv[0]);
std::string image_filename_out = "image_out.yuv";
uint32_t imageWidth = 720;
uint32_t imageHeight = 480;
printf("input image %s , width = %d, height = %d\n", image_filename.c_str(), imageWidth, imageHeight);
printf("input image %s , width = %d, height = %d\n", image_filename.c_str(), imageWidth, imageHeight);
cudaNvSciBufMultiplanar cudaNvSciBufMultiplanarApp(imageWidth, imageHeight, deviceIds);
cudaNvSciBufMultiplanarApp.runCudaNvSciBufPlanar(image_filename, image_filename_out);
cudaNvSciBufMultiplanar cudaNvSciBufMultiplanarApp(imageWidth, imageHeight, deviceIds);
cudaNvSciBufMultiplanarApp.runCudaNvSciBufPlanar(image_filename, image_filename_out);
return EXIT_SUCCESS;
}
return EXIT_SUCCESS;
}

View File

@@ -37,4 +37,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -25,404 +25,382 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cuda_runtime.h>
#include <helper_image.h>
#include <iostream>
#include <cuda_runtime.h>
#include "cuda_consumer.h"
#include <helper_image.h>
#include "nvmedia_image_nvscibuf.h"
#include "nvmedia_utils/cmdline.h"
// Enable this to 1 if require cuda processed output to ppm file.
#define WRITE_OUTPUT_IMAGE 0
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf( \
"NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, __LINE__, _status, NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf("NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, \
__LINE__, \
_status, \
NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
__global__ static void yuvToGrayscale(cudaSurfaceObject_t surfaceObject,
unsigned int *dstImage,
int32_t imageWidth, int32_t imageHeight) {
size_t x = blockIdx.x * blockDim.x + threadIdx.x;
size_t y = blockIdx.y * blockDim.y + threadIdx.y;
__global__ static void
yuvToGrayscale(cudaSurfaceObject_t surfaceObject, unsigned int *dstImage, int32_t imageWidth, int32_t imageHeight)
{
size_t x = blockIdx.x * blockDim.x + threadIdx.x;
size_t y = blockIdx.y * blockDim.y + threadIdx.y;
uchar4 *dstImageUchar4 = (uchar4 *)dstImage;
for (; x < imageWidth && y < imageHeight;
x += gridDim.x * blockDim.x, y += gridDim.y * blockDim.y) {
int colInBytes = x * sizeof(unsigned char);
unsigned char luma =
surf2Dread<unsigned char>(surfaceObject, colInBytes, y);
uchar4 grayscalePix = make_uchar4(luma, luma, luma, 0);
uchar4 *dstImageUchar4 = (uchar4 *)dstImage;
for (; x < imageWidth && y < imageHeight; x += gridDim.x * blockDim.x, y += gridDim.y * blockDim.y) {
int colInBytes = x * sizeof(unsigned char);
unsigned char luma = surf2Dread<unsigned char>(surfaceObject, colInBytes, y);
uchar4 grayscalePix = make_uchar4(luma, luma, luma, 0);
dstImageUchar4[y * imageWidth + x] = grayscalePix;
}
dstImageUchar4[y * imageWidth + x] = grayscalePix;
}
}
static void cudaImportNvSciSync(cudaExternalSemaphore_t &extSem,
NvSciSyncObj &syncObj) {
cudaExternalSemaphoreHandleDesc extSemDesc;
memset(&extSemDesc, 0, sizeof(extSemDesc));
extSemDesc.type = cudaExternalSemaphoreHandleTypeNvSciSync;
extSemDesc.handle.nvSciSyncObj = (void *)syncObj;
static void cudaImportNvSciSync(cudaExternalSemaphore_t &extSem, NvSciSyncObj &syncObj)
{
cudaExternalSemaphoreHandleDesc extSemDesc;
memset(&extSemDesc, 0, sizeof(extSemDesc));
extSemDesc.type = cudaExternalSemaphoreHandleTypeNvSciSync;
extSemDesc.handle.nvSciSyncObj = (void *)syncObj;
checkCudaErrors(cudaImportExternalSemaphore(&extSem, &extSemDesc));
checkCudaErrors(cudaImportExternalSemaphore(&extSem, &extSemDesc));
}
static void waitExternalSemaphore(cudaExternalSemaphore_t &waitSem,
NvSciSyncFence *fence, cudaStream_t stream) {
cudaExternalSemaphoreWaitParams waitParams;
memset(&waitParams, 0, sizeof(waitParams));
// For cross-process signaler-waiter applications need to use NvSciIpc
// and NvSciSync[Export|Import] utilities to share the NvSciSyncFence
// across process. This step is optional in single-process.
waitParams.params.nvSciSync.fence = (void *)fence;
waitParams.flags = 0;
static void waitExternalSemaphore(cudaExternalSemaphore_t &waitSem, NvSciSyncFence *fence, cudaStream_t stream)
{
cudaExternalSemaphoreWaitParams waitParams;
memset(&waitParams, 0, sizeof(waitParams));
// For cross-process signaler-waiter applications need to use NvSciIpc
// and NvSciSync[Export|Import] utilities to share the NvSciSyncFence
// across process. This step is optional in single-process.
waitParams.params.nvSciSync.fence = (void *)fence;
waitParams.flags = 0;
checkCudaErrors(
cudaWaitExternalSemaphoresAsync(&waitSem, &waitParams, 1, stream));
checkCudaErrors(cudaWaitExternalSemaphoresAsync(&waitSem, &waitParams, 1, stream));
}
static void signalExternalSemaphore(cudaExternalSemaphore_t &signalSem,
NvSciSyncFence *fence,
cudaStream_t stream) {
cudaExternalSemaphoreSignalParams signalParams;
memset(&signalParams, 0, sizeof(signalParams));
// For cross-process signaler-waiter applications need to use NvSciIpc
// and NvSciSync[Export|Import] utilities to share the NvSciSyncFence
// across process. This step is optional in single-process.
signalParams.params.nvSciSync.fence = (void *)fence;
signalParams.flags = 0;
static void signalExternalSemaphore(cudaExternalSemaphore_t &signalSem, NvSciSyncFence *fence, cudaStream_t stream)
{
cudaExternalSemaphoreSignalParams signalParams;
memset(&signalParams, 0, sizeof(signalParams));
// For cross-process signaler-waiter applications need to use NvSciIpc
// and NvSciSync[Export|Import] utilities to share the NvSciSyncFence
// across process. This step is optional in single-process.
signalParams.params.nvSciSync.fence = (void *)fence;
signalParams.flags = 0;
checkCudaErrors(
cudaSignalExternalSemaphoresAsync(&signalSem, &signalParams, 1, stream));
checkCudaErrors(cudaSignalExternalSemaphoresAsync(&signalSem, &signalParams, 1, stream));
}
static void yuvToGrayscaleCudaKernel(cudaExternalResInterop &cudaExtResObj,
int32_t imageWidth, int32_t imageHeight) {
static void yuvToGrayscaleCudaKernel(cudaExternalResInterop &cudaExtResObj, int32_t imageWidth, int32_t imageHeight)
{
#if WRITE_OUTPUT_IMAGE
unsigned int *h_dstImage;
checkCudaErrors(cudaMallocHost(
&h_dstImage, sizeof(unsigned int) * imageHeight * imageWidth));
unsigned int *h_dstImage;
checkCudaErrors(cudaMallocHost(&h_dstImage, sizeof(unsigned int) * imageHeight * imageWidth));
#endif
dim3 block(16, 16, 1);
dim3 grid((imageWidth / block.x) + 1, (imageHeight / block.y) + 1, 1);
dim3 block(16, 16, 1);
dim3 grid((imageWidth / block.x) + 1, (imageHeight / block.y) + 1, 1);
yuvToGrayscale<<<grid, block, 0, cudaExtResObj.stream>>>(
cudaExtResObj.cudaSurfaceNvmediaBuf[0], cudaExtResObj.d_outputImage,
imageWidth, imageHeight);
yuvToGrayscale<<<grid, block, 0, cudaExtResObj.stream>>>(
cudaExtResObj.cudaSurfaceNvmediaBuf[0], cudaExtResObj.d_outputImage, imageWidth, imageHeight);
#if WRITE_OUTPUT_IMAGE
checkCudaErrors(
cudaMemcpyAsync(h_dstImage, cudaExtResObj.d_outputImage,
sizeof(unsigned int) * imageHeight * imageWidth,
cudaMemcpyDeviceToHost, cudaExtResObj.stream));
checkCudaErrors(cudaStreamSynchronize(cudaExtResObj.stream));
char outputFilename[1024];
std::string image_filename = "Grayscale";
strcpy(outputFilename, image_filename.c_str());
strcpy(outputFilename + image_filename.length(), "_nvsci_out.ppm");
sdkSavePPM4ub(outputFilename, (unsigned char *)h_dstImage, imageWidth,
imageHeight);
printf("Wrote '%s'\n", outputFilename);
checkCudaErrors(cudaFreeHost(h_dstImage));
checkCudaErrors(cudaMemcpyAsync(h_dstImage,
cudaExtResObj.d_outputImage,
sizeof(unsigned int) * imageHeight * imageWidth,
cudaMemcpyDeviceToHost,
cudaExtResObj.stream));
checkCudaErrors(cudaStreamSynchronize(cudaExtResObj.stream));
char outputFilename[1024];
std::string image_filename = "Grayscale";
strcpy(outputFilename, image_filename.c_str());
strcpy(outputFilename + image_filename.length(), "_nvsci_out.ppm");
sdkSavePPM4ub(outputFilename, (unsigned char *)h_dstImage, imageWidth, imageHeight);
printf("Wrote '%s'\n", outputFilename);
checkCudaErrors(cudaFreeHost(h_dstImage));
#endif
}
static void cudaImportNvSciImage(cudaExternalResInterop &cudaExtResObj,
NvSciBufObj &inputBufObj) {
NvSciBufModule module = NULL;
NvSciBufAttrList attrlist = NULL;
NvSciBufAttrKeyValuePair pairArrayOut[10];
static void cudaImportNvSciImage(cudaExternalResInterop &cudaExtResObj, NvSciBufObj &inputBufObj)
{
NvSciBufModule module = NULL;
NvSciBufAttrList attrlist = NULL;
NvSciBufAttrKeyValuePair pairArrayOut[10];
checkNvSciErrors(NvSciBufModuleOpen(&module));
checkNvSciErrors(NvSciBufAttrListCreate(module, &attrlist));
checkNvSciErrors(NvSciBufObjGetAttrList(inputBufObj, &attrlist));
checkNvSciErrors(NvSciBufModuleOpen(&module));
checkNvSciErrors(NvSciBufAttrListCreate(module, &attrlist));
checkNvSciErrors(NvSciBufObjGetAttrList(inputBufObj, &attrlist));
memset(pairArrayOut, 0, sizeof(NvSciBufAttrKeyValuePair) * 10);
memset(pairArrayOut, 0, sizeof(NvSciBufAttrKeyValuePair) * 10);
int numAttrs = 0;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_Size;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneChannelCount;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneCount;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneWidth;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneHeight;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_Layout;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneBitsPerPixel;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneOffset;
int numAttrs = 0;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_Size;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneChannelCount;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneCount;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneWidth;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneHeight;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_Layout;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneBitsPerPixel;
pairArrayOut[numAttrs++].key = NvSciBufImageAttrKey_PlaneOffset;
checkNvSciErrors(NvSciBufAttrListGetAttrs(attrlist, pairArrayOut, numAttrs));
checkNvSciErrors(NvSciBufAttrListGetAttrs(attrlist, pairArrayOut, numAttrs));
uint64_t size = *(uint64_t *)pairArrayOut[0].value;
uint8_t channelCount = *(uint8_t *)pairArrayOut[1].value;
cudaExtResObj.planeCount = *(int32_t *)pairArrayOut[2].value;
cudaExtResObj.imageWidth =
(int32_t *)malloc(sizeof(int32_t) * cudaExtResObj.planeCount);
cudaExtResObj.imageHeight =
(int32_t *)malloc(sizeof(int32_t) * cudaExtResObj.planeCount);
cudaExtResObj.planeOffset =
(uint64_t *)malloc(sizeof(uint64_t) * cudaExtResObj.planeCount);
uint64_t size = *(uint64_t *)pairArrayOut[0].value;
uint8_t channelCount = *(uint8_t *)pairArrayOut[1].value;
cudaExtResObj.planeCount = *(int32_t *)pairArrayOut[2].value;
cudaExtResObj.imageWidth = (int32_t *)malloc(sizeof(int32_t) * cudaExtResObj.planeCount);
cudaExtResObj.imageHeight = (int32_t *)malloc(sizeof(int32_t) * cudaExtResObj.planeCount);
cudaExtResObj.planeOffset = (uint64_t *)malloc(sizeof(uint64_t) * cudaExtResObj.planeCount);
memcpy(cudaExtResObj.imageWidth, (int32_t *)pairArrayOut[3].value,
cudaExtResObj.planeCount * sizeof(int32_t));
memcpy(cudaExtResObj.imageHeight, (int32_t *)pairArrayOut[4].value,
cudaExtResObj.planeCount * sizeof(int32_t));
memcpy(cudaExtResObj.planeOffset, (uint64_t *)pairArrayOut[7].value,
cudaExtResObj.planeCount * sizeof(uint64_t));
memcpy(cudaExtResObj.imageWidth, (int32_t *)pairArrayOut[3].value, cudaExtResObj.planeCount * sizeof(int32_t));
memcpy(cudaExtResObj.imageHeight, (int32_t *)pairArrayOut[4].value, cudaExtResObj.planeCount * sizeof(int32_t));
memcpy(cudaExtResObj.planeOffset, (uint64_t *)pairArrayOut[7].value, cudaExtResObj.planeCount * sizeof(uint64_t));
NvSciBufAttrValImageLayoutType layout =
*(NvSciBufAttrValImageLayoutType *)pairArrayOut[5].value;
uint32_t bitsPerPixel = *(uint32_t *)pairArrayOut[6].value;
NvSciBufAttrValImageLayoutType layout = *(NvSciBufAttrValImageLayoutType *)pairArrayOut[5].value;
uint32_t bitsPerPixel = *(uint32_t *)pairArrayOut[6].value;
if (layout != NvSciBufImage_BlockLinearType) {
printf("Image layout is not block linear.. waiving execution\n");
exit(EXIT_WAIVED);
}
cudaExternalMemoryHandleDesc memHandleDesc;
memset(&memHandleDesc, 0, sizeof(memHandleDesc));
memHandleDesc.type = cudaExternalMemoryHandleTypeNvSciBuf;
memHandleDesc.handle.nvSciBufObject = inputBufObj;
memHandleDesc.size = size;
checkCudaErrors(
cudaImportExternalMemory(&cudaExtResObj.extMemImageBuf, &memHandleDesc));
cudaExtResObj.d_mipmapArray = (cudaMipmappedArray_t *)malloc(
sizeof(cudaMipmappedArray_t) * cudaExtResObj.planeCount);
for (int i = 0; i < cudaExtResObj.planeCount; i++) {
cudaExtent extent = {};
memset(&extent, 0, sizeof(extent));
extent.width = cudaExtResObj.imageWidth[i];
extent.height = cudaExtResObj.imageHeight[i];
extent.depth = 0;
cudaChannelFormatDesc desc;
switch (channelCount) {
case 1:
default:
desc = cudaCreateChannelDesc(bitsPerPixel, 0, 0, 0,
cudaChannelFormatKindUnsigned);
break;
case 2:
desc = cudaCreateChannelDesc(bitsPerPixel, bitsPerPixel, 0, 0,
cudaChannelFormatKindUnsigned);
break;
case 3:
desc = cudaCreateChannelDesc(bitsPerPixel, bitsPerPixel, bitsPerPixel,
0, cudaChannelFormatKindUnsigned);
break;
case 4:
desc =
cudaCreateChannelDesc(bitsPerPixel, bitsPerPixel, bitsPerPixel,
bitsPerPixel, cudaChannelFormatKindUnsigned);
break;
if (layout != NvSciBufImage_BlockLinearType) {
printf("Image layout is not block linear.. waiving execution\n");
exit(EXIT_WAIVED);
}
cudaExternalMemoryMipmappedArrayDesc mipmapDesc = {0};
mipmapDesc.offset = cudaExtResObj.planeOffset[i];
mipmapDesc.formatDesc = desc;
mipmapDesc.extent = extent;
mipmapDesc.flags = 0;
mipmapDesc.numLevels = 1;
checkCudaErrors(cudaExternalMemoryGetMappedMipmappedArray(
&cudaExtResObj.d_mipmapArray[i], cudaExtResObj.extMemImageBuf,
&mipmapDesc));
}
cudaExternalMemoryHandleDesc memHandleDesc;
memset(&memHandleDesc, 0, sizeof(memHandleDesc));
memHandleDesc.type = cudaExternalMemoryHandleTypeNvSciBuf;
memHandleDesc.handle.nvSciBufObject = inputBufObj;
memHandleDesc.size = size;
checkCudaErrors(cudaImportExternalMemory(&cudaExtResObj.extMemImageBuf, &memHandleDesc));
cudaExtResObj.d_mipmapArray =
(cudaMipmappedArray_t *)malloc(sizeof(cudaMipmappedArray_t) * cudaExtResObj.planeCount);
for (int i = 0; i < cudaExtResObj.planeCount; i++) {
cudaExtent extent = {};
memset(&extent, 0, sizeof(extent));
extent.width = cudaExtResObj.imageWidth[i];
extent.height = cudaExtResObj.imageHeight[i];
extent.depth = 0;
cudaChannelFormatDesc desc;
switch (channelCount) {
case 1:
default:
desc = cudaCreateChannelDesc(bitsPerPixel, 0, 0, 0, cudaChannelFormatKindUnsigned);
break;
case 2:
desc = cudaCreateChannelDesc(bitsPerPixel, bitsPerPixel, 0, 0, cudaChannelFormatKindUnsigned);
break;
case 3:
desc = cudaCreateChannelDesc(bitsPerPixel, bitsPerPixel, bitsPerPixel, 0, cudaChannelFormatKindUnsigned);
break;
case 4:
desc = cudaCreateChannelDesc(
bitsPerPixel, bitsPerPixel, bitsPerPixel, bitsPerPixel, cudaChannelFormatKindUnsigned);
break;
}
cudaExternalMemoryMipmappedArrayDesc mipmapDesc = {0};
mipmapDesc.offset = cudaExtResObj.planeOffset[i];
mipmapDesc.formatDesc = desc;
mipmapDesc.extent = extent;
mipmapDesc.flags = 0;
mipmapDesc.numLevels = 1;
checkCudaErrors(cudaExternalMemoryGetMappedMipmappedArray(
&cudaExtResObj.d_mipmapArray[i], cudaExtResObj.extMemImageBuf, &mipmapDesc));
}
}
static cudaSurfaceObject_t createCudaSurface(cudaArray_t &d_mipLevelArray) {
cudaResourceDesc resourceDesc;
memset(&resourceDesc, 0, sizeof(resourceDesc));
resourceDesc.resType = cudaResourceTypeArray;
resourceDesc.res.array.array = d_mipLevelArray;
static cudaSurfaceObject_t createCudaSurface(cudaArray_t &d_mipLevelArray)
{
cudaResourceDesc resourceDesc;
memset(&resourceDesc, 0, sizeof(resourceDesc));
resourceDesc.resType = cudaResourceTypeArray;
resourceDesc.res.array.array = d_mipLevelArray;
cudaSurfaceObject_t surfaceObject;
checkCudaErrors(cudaCreateSurfaceObject(&surfaceObject, &resourceDesc));
return surfaceObject;
cudaSurfaceObject_t surfaceObject;
checkCudaErrors(cudaCreateSurfaceObject(&surfaceObject, &resourceDesc));
return surfaceObject;
}
static cudaStream_t createCudaStream(int deviceId) {
checkCudaErrors(cudaSetDevice(deviceId));
cudaStream_t stream;
checkCudaErrors(cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking));
return stream;
static cudaStream_t createCudaStream(int deviceId)
{
checkCudaErrors(cudaSetDevice(deviceId));
cudaStream_t stream;
checkCudaErrors(cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking));
return stream;
}
// CUDA setup buffers/synchronization objects for interop via NvSci API.
void setupCuda(cudaExternalResInterop &cudaExtResObj, NvSciBufObj &inputBufObj,
NvSciSyncObj &syncObj, NvSciSyncObj &cudaSignalerSyncObj,
int deviceId) {
checkCudaErrors(cudaSetDevice(deviceId));
cudaImportNvSciSync(cudaExtResObj.waitSem, syncObj);
cudaImportNvSciSync(cudaExtResObj.signalSem, cudaSignalerSyncObj);
void setupCuda(cudaExternalResInterop &cudaExtResObj,
NvSciBufObj &inputBufObj,
NvSciSyncObj &syncObj,
NvSciSyncObj &cudaSignalerSyncObj,
int deviceId)
{
checkCudaErrors(cudaSetDevice(deviceId));
cudaImportNvSciSync(cudaExtResObj.waitSem, syncObj);
cudaImportNvSciSync(cudaExtResObj.signalSem, cudaSignalerSyncObj);
cudaImportNvSciImage(cudaExtResObj, inputBufObj);
cudaExtResObj.d_mipLevelArray =
(cudaArray_t *)malloc(sizeof(cudaArray_t) * cudaExtResObj.planeCount);
cudaExtResObj.cudaSurfaceNvmediaBuf = (cudaSurfaceObject_t *)malloc(
sizeof(cudaSurfaceObject_t) * cudaExtResObj.planeCount);
cudaImportNvSciImage(cudaExtResObj, inputBufObj);
cudaExtResObj.d_mipLevelArray = (cudaArray_t *)malloc(sizeof(cudaArray_t) * cudaExtResObj.planeCount);
cudaExtResObj.cudaSurfaceNvmediaBuf =
(cudaSurfaceObject_t *)malloc(sizeof(cudaSurfaceObject_t) * cudaExtResObj.planeCount);
for (int i = 0; i < cudaExtResObj.planeCount; ++i) {
uint32_t mipLevelId = 0;
checkCudaErrors(
cudaGetMipmappedArrayLevel(&cudaExtResObj.d_mipLevelArray[i],
cudaExtResObj.d_mipmapArray[i], mipLevelId));
cudaExtResObj.cudaSurfaceNvmediaBuf[i] =
createCudaSurface(cudaExtResObj.d_mipLevelArray[i]);
}
for (int i = 0; i < cudaExtResObj.planeCount; ++i) {
uint32_t mipLevelId = 0;
checkCudaErrors(
cudaGetMipmappedArrayLevel(&cudaExtResObj.d_mipLevelArray[i], cudaExtResObj.d_mipmapArray[i], mipLevelId));
cudaExtResObj.cudaSurfaceNvmediaBuf[i] = createCudaSurface(cudaExtResObj.d_mipLevelArray[i]);
}
cudaExtResObj.stream = createCudaStream(deviceId);
checkCudaErrors(cudaMalloc(&cudaExtResObj.d_outputImage,
sizeof(unsigned int) *
cudaExtResObj.imageWidth[0] *
cudaExtResObj.imageHeight[0]));
cudaExtResObj.stream = createCudaStream(deviceId);
checkCudaErrors(cudaMalloc(&cudaExtResObj.d_outputImage,
sizeof(unsigned int) * cudaExtResObj.imageWidth[0] * cudaExtResObj.imageHeight[0]));
}
// CUDA clean up buffers used **with** NvSci API.
void cleanupCuda(cudaExternalResInterop &cudaExtResObj) {
for (int i = 0; i < cudaExtResObj.planeCount; i++) {
checkCudaErrors(
cudaDestroySurfaceObject(cudaExtResObj.cudaSurfaceNvmediaBuf[i]));
checkCudaErrors(cudaFreeMipmappedArray(cudaExtResObj.d_mipmapArray[i]));
}
free(cudaExtResObj.d_mipmapArray);
free(cudaExtResObj.d_mipLevelArray);
free(cudaExtResObj.cudaSurfaceNvmediaBuf);
free(cudaExtResObj.imageWidth);
free(cudaExtResObj.imageHeight);
checkCudaErrors(cudaDestroyExternalSemaphore(cudaExtResObj.waitSem));
checkCudaErrors(cudaDestroyExternalSemaphore(cudaExtResObj.signalSem));
checkCudaErrors(cudaDestroyExternalMemory(cudaExtResObj.extMemImageBuf));
checkCudaErrors(cudaStreamDestroy(cudaExtResObj.stream));
checkCudaErrors(cudaFree(cudaExtResObj.d_outputImage));
void cleanupCuda(cudaExternalResInterop &cudaExtResObj)
{
for (int i = 0; i < cudaExtResObj.planeCount; i++) {
checkCudaErrors(cudaDestroySurfaceObject(cudaExtResObj.cudaSurfaceNvmediaBuf[i]));
checkCudaErrors(cudaFreeMipmappedArray(cudaExtResObj.d_mipmapArray[i]));
}
free(cudaExtResObj.d_mipmapArray);
free(cudaExtResObj.d_mipLevelArray);
free(cudaExtResObj.cudaSurfaceNvmediaBuf);
free(cudaExtResObj.imageWidth);
free(cudaExtResObj.imageHeight);
checkCudaErrors(cudaDestroyExternalSemaphore(cudaExtResObj.waitSem));
checkCudaErrors(cudaDestroyExternalSemaphore(cudaExtResObj.signalSem));
checkCudaErrors(cudaDestroyExternalMemory(cudaExtResObj.extMemImageBuf));
checkCudaErrors(cudaStreamDestroy(cudaExtResObj.stream));
checkCudaErrors(cudaFree(cudaExtResObj.d_outputImage));
}
void runCudaOperation(cudaExternalResInterop &cudaExtResObj,
NvSciSyncFence *cudaWaitFence,
NvSciSyncFence *cudaSignalFence, int deviceId,
int iterations) {
checkCudaErrors(cudaSetDevice(deviceId));
static int64_t launch = 0;
NvSciSyncFence *cudaWaitFence,
NvSciSyncFence *cudaSignalFence,
int deviceId,
int iterations)
{
checkCudaErrors(cudaSetDevice(deviceId));
static int64_t launch = 0;
waitExternalSemaphore(cudaExtResObj.waitSem, cudaWaitFence,
cudaExtResObj.stream);
waitExternalSemaphore(cudaExtResObj.waitSem, cudaWaitFence, cudaExtResObj.stream);
// run cuda kernel over surface object of the LUMA surface part to extract
// grayscale.
yuvToGrayscaleCudaKernel(cudaExtResObj, cudaExtResObj.imageWidth[0],
cudaExtResObj.imageHeight[0]);
// run cuda kernel over surface object of the LUMA surface part to extract
// grayscale.
yuvToGrayscaleCudaKernel(cudaExtResObj, cudaExtResObj.imageWidth[0], cudaExtResObj.imageHeight[0]);
// signal fence till the second last iterations for NvMedia2DBlit to wait for
// cuda signal and for final iteration as there is no corresponding NvMedia
// operation pending therefore we end with cudaStreamSynchronize()
if (launch < iterations - 1) {
signalExternalSemaphore(cudaExtResObj.signalSem, cudaSignalFence,
cudaExtResObj.stream);
} else {
checkCudaErrors(cudaStreamSynchronize(cudaExtResObj.stream));
}
launch++;
// signal fence till the second last iterations for NvMedia2DBlit to wait for
// cuda signal and for final iteration as there is no corresponding NvMedia
// operation pending therefore we end with cudaStreamSynchronize()
if (launch < iterations - 1) {
signalExternalSemaphore(cudaExtResObj.signalSem, cudaSignalFence, cudaExtResObj.stream);
}
else {
checkCudaErrors(cudaStreamSynchronize(cudaExtResObj.stream));
}
launch++;
}
// CUDA imports and operates on NvSci buffer/synchronization objects
void setupCuda(Blit2DTest *ctx, cudaResources &cudaResObj, int deviceId) {
checkCudaErrors(cudaSetDevice(deviceId));
cudaResObj.d_yuvArray =
(cudaArray_t *)malloc(sizeof(cudaArray_t) * ctx->numSurfaces);
cudaResObj.cudaSurfaceNvmediaBuf = (cudaSurfaceObject_t *)malloc(
sizeof(cudaSurfaceObject_t) * ctx->numSurfaces);
cudaChannelFormatDesc channelDesc;
switch (ctx->bytesPerPixel) {
void setupCuda(Blit2DTest *ctx, cudaResources &cudaResObj, int deviceId)
{
checkCudaErrors(cudaSetDevice(deviceId));
cudaResObj.d_yuvArray = (cudaArray_t *)malloc(sizeof(cudaArray_t) * ctx->numSurfaces);
cudaResObj.cudaSurfaceNvmediaBuf = (cudaSurfaceObject_t *)malloc(sizeof(cudaSurfaceObject_t) * ctx->numSurfaces);
cudaChannelFormatDesc channelDesc;
switch (ctx->bytesPerPixel) {
case 1:
default:
channelDesc =
cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned);
break;
}
channelDesc = cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned);
break;
}
for (int k = 0; k < ctx->numSurfaces; k++) {
checkCudaErrors(cudaMallocArray(
&cudaResObj.d_yuvArray[k], &channelDesc,
ctx->widthSurface * ctx->xScalePtr[k] * ctx->bytesPerPixel,
ctx->heightSurface * ctx->yScalePtr[k]));
cudaResObj.cudaSurfaceNvmediaBuf[k] =
createCudaSurface(cudaResObj.d_yuvArray[k]);
}
checkCudaErrors(cudaMalloc(
&cudaResObj.d_outputImage,
sizeof(unsigned int) * ctx->widthSurface * ctx->heightSurface));
for (int k = 0; k < ctx->numSurfaces; k++) {
checkCudaErrors(cudaMallocArray(&cudaResObj.d_yuvArray[k],
&channelDesc,
ctx->widthSurface * ctx->xScalePtr[k] * ctx->bytesPerPixel,
ctx->heightSurface * ctx->yScalePtr[k]));
cudaResObj.cudaSurfaceNvmediaBuf[k] = createCudaSurface(cudaResObj.d_yuvArray[k]);
}
checkCudaErrors(
cudaMalloc(&cudaResObj.d_outputImage, sizeof(unsigned int) * ctx->widthSurface * ctx->heightSurface));
cudaResObj.stream = createCudaStream(deviceId);
cudaResObj.stream = createCudaStream(deviceId);
}
// CUDA clean up buffers used **without** NvSci API.
void cleanupCuda(Blit2DTest *ctx, cudaResources &cudaResObj) {
for (int k = 0; k < ctx->numSurfaces; k++) {
checkCudaErrors(
cudaDestroySurfaceObject(cudaResObj.cudaSurfaceNvmediaBuf[k]));
checkCudaErrors(cudaFreeArray(cudaResObj.d_yuvArray[k]));
}
void cleanupCuda(Blit2DTest *ctx, cudaResources &cudaResObj)
{
for (int k = 0; k < ctx->numSurfaces; k++) {
checkCudaErrors(cudaDestroySurfaceObject(cudaResObj.cudaSurfaceNvmediaBuf[k]));
checkCudaErrors(cudaFreeArray(cudaResObj.d_yuvArray[k]));
}
free(cudaResObj.cudaSurfaceNvmediaBuf);
free(cudaResObj.cudaSurfaceNvmediaBuf);
checkCudaErrors(cudaStreamDestroy(cudaResObj.stream));
checkCudaErrors(cudaFree(cudaResObj.d_outputImage));
checkCudaErrors(cudaStreamDestroy(cudaResObj.stream));
checkCudaErrors(cudaFree(cudaResObj.d_outputImage));
}
static void yuvToGrayscaleCudaKernelNonNvSci(cudaResources &cudaResObj,
int deviceId, int32_t imageWidth,
int32_t imageHeight) {
static void
yuvToGrayscaleCudaKernelNonNvSci(cudaResources &cudaResObj, int deviceId, int32_t imageWidth, int32_t imageHeight)
{
#if WRITE_OUTPUT_IMAGE
unsigned int *h_dstImage;
checkCudaErrors(cudaMallocHost(
&h_dstImage, sizeof(unsigned int) * imageHeight * imageWidth));
unsigned int *h_dstImage;
checkCudaErrors(cudaMallocHost(&h_dstImage, sizeof(unsigned int) * imageHeight * imageWidth));
#endif
dim3 block(16, 16, 1);
dim3 grid((imageWidth / block.x) + 1, (imageHeight / block.y) + 1, 1);
dim3 block(16, 16, 1);
dim3 grid((imageWidth / block.x) + 1, (imageHeight / block.y) + 1, 1);
yuvToGrayscale<<<grid, block, 0, cudaResObj.stream>>>(
cudaResObj.cudaSurfaceNvmediaBuf[0], cudaResObj.d_outputImage, imageWidth,
imageHeight);
yuvToGrayscale<<<grid, block, 0, cudaResObj.stream>>>(
cudaResObj.cudaSurfaceNvmediaBuf[0], cudaResObj.d_outputImage, imageWidth, imageHeight);
#if WRITE_OUTPUT_IMAGE
checkCudaErrors(
cudaMemcpyAsync(h_dstImage, cudaResObj.d_outputImage,
sizeof(unsigned int) * imageHeight * imageWidth,
cudaMemcpyDeviceToHost, cudaResObj.stream));
checkCudaErrors(cudaStreamSynchronize(cudaResObj.stream));
char outputFilename[1024];
std::string image_filename = "Grayscale";
strcpy(outputFilename, image_filename.c_str());
strcpy(outputFilename + image_filename.length(), "_non-nvsci_out.ppm");
sdkSavePPM4ub(outputFilename, (unsigned char *)h_dstImage, imageWidth,
imageHeight);
printf("Wrote '%s'\n", outputFilename);
checkCudaErrors(cudaFreeHost(h_dstImage));
checkCudaErrors(cudaMemcpyAsync(h_dstImage,
cudaResObj.d_outputImage,
sizeof(unsigned int) * imageHeight * imageWidth,
cudaMemcpyDeviceToHost,
cudaResObj.stream));
checkCudaErrors(cudaStreamSynchronize(cudaResObj.stream));
char outputFilename[1024];
std::string image_filename = "Grayscale";
strcpy(outputFilename, image_filename.c_str());
strcpy(outputFilename + image_filename.length(), "_non-nvsci_out.ppm");
sdkSavePPM4ub(outputFilename, (unsigned char *)h_dstImage, imageWidth, imageHeight);
printf("Wrote '%s'\n", outputFilename);
checkCudaErrors(cudaFreeHost(h_dstImage));
#else
checkCudaErrors(cudaStreamSynchronize(cudaResObj.stream));
checkCudaErrors(cudaStreamSynchronize(cudaResObj.stream));
#endif
}
// CUDA operates **without** NvSci APIs buffer/synchronization objects.
void runCudaOperation(Blit2DTest *ctx, cudaResources &cudaResObj,
int deviceId) {
for (int k = 0; k < ctx->numSurfaces; k++) {
checkCudaErrors(cudaMemcpy2DToArray(
cudaResObj.d_yuvArray[k], 0, 0, ctx->dstBuff[k],
ctx->widthSurface * ctx->xScalePtr[k] * ctx->bytesPerPixel,
ctx->widthSurface * ctx->xScalePtr[k] * ctx->bytesPerPixel,
ctx->heightSurface * ctx->yScalePtr[k], cudaMemcpyHostToDevice));
}
// run cuda kernel over surface object of the LUMA surface part to extract
// grayscale.
yuvToGrayscaleCudaKernelNonNvSci(cudaResObj, deviceId, ctx->widthSurface,
ctx->heightSurface);
void runCudaOperation(Blit2DTest *ctx, cudaResources &cudaResObj, int deviceId)
{
for (int k = 0; k < ctx->numSurfaces; k++) {
checkCudaErrors(cudaMemcpy2DToArray(cudaResObj.d_yuvArray[k],
0,
0,
ctx->dstBuff[k],
ctx->widthSurface * ctx->xScalePtr[k] * ctx->bytesPerPixel,
ctx->widthSurface * ctx->xScalePtr[k] * ctx->bytesPerPixel,
ctx->heightSurface * ctx->yScalePtr[k],
cudaMemcpyHostToDevice));
}
// run cuda kernel over surface object of the LUMA surface part to extract
// grayscale.
yuvToGrayscaleCudaKernelNonNvSci(cudaResObj, deviceId, ctx->widthSurface, ctx->heightSurface);
}

View File

@@ -29,42 +29,49 @@
#define __CUDA_BUFIMPORT_KERNEL_H__
#include <cuda_runtime.h>
#include "helper_cuda.h"
#include "nvmedia_image_nvscibuf.h"
#include "nvscisync.h"
#include "nvmedia_utils/cmdline.h"
#include "nvscisync.h"
struct cudaExternalResInterop {
cudaMipmappedArray_t *d_mipmapArray;
cudaArray_t *d_mipLevelArray;
cudaSurfaceObject_t *cudaSurfaceNvmediaBuf;
cudaStream_t stream;
cudaExternalMemory_t extMemImageBuf;
cudaExternalSemaphore_t waitSem;
cudaExternalSemaphore_t signalSem;
struct cudaExternalResInterop
{
cudaMipmappedArray_t *d_mipmapArray;
cudaArray_t *d_mipLevelArray;
cudaSurfaceObject_t *cudaSurfaceNvmediaBuf;
cudaStream_t stream;
cudaExternalMemory_t extMemImageBuf;
cudaExternalSemaphore_t waitSem;
cudaExternalSemaphore_t signalSem;
int32_t planeCount;
uint64_t *planeOffset;
int32_t *imageWidth;
int32_t *imageHeight;
unsigned int *d_outputImage;
int32_t planeCount;
uint64_t *planeOffset;
int32_t *imageWidth;
int32_t *imageHeight;
unsigned int *d_outputImage;
};
struct cudaResources {
cudaArray_t *d_yuvArray;
cudaStream_t stream;
cudaSurfaceObject_t *cudaSurfaceNvmediaBuf;
unsigned int *d_outputImage;
struct cudaResources
{
cudaArray_t *d_yuvArray;
cudaStream_t stream;
cudaSurfaceObject_t *cudaSurfaceNvmediaBuf;
unsigned int *d_outputImage;
};
void runCudaOperation(cudaExternalResInterop &cudaExtResObj,
NvSciSyncFence *fence, NvSciSyncFence *cudaSignalfence,
int deviceId, int iterations);
NvSciSyncFence *fence,
NvSciSyncFence *cudaSignalfence,
int deviceId,
int iterations);
void runCudaOperation(Blit2DTest *ctx, cudaResources &cudaResObj, int deviceId);
void setupCuda(cudaExternalResInterop &cudaExtResObj, NvSciBufObj &inputBufObj,
NvSciSyncObj &syncObj, NvSciSyncObj &cudaSignalerSyncObj,
int deviceId);
void setupCuda(cudaExternalResInterop &cudaExtResObj,
NvSciBufObj &inputBufObj,
NvSciSyncObj &syncObj,
NvSciSyncObj &cudaSignalerSyncObj,
int deviceId);
void setupCuda(Blit2DTest *ctx, cudaResources &cudaResObj, int deviceId);
void cleanupCuda(cudaExternalResInterop &cudaObjs);
void cleanupCuda(Blit2DTest *ctx, cudaResources &cudaResObj);

View File

@@ -26,185 +26,186 @@
*/
/* standard headers */
#include <string.h>
#include <iostream>
#include <signal.h>
#include <string.h>
#include <thread>
/* Nvidia headers */
#include <nvscisync.h>
#include "nvmedia_utils/cmdline.h"
#include "nvmedia_image.h"
#include "cuda_consumer.h"
#include "nvmedia_2d.h"
#include "nvmedia_2d_nvscisync.h"
#include "nvmedia_surface.h"
#include "nvmedia_utils/image_utils.h"
#include "nvmedia_image.h"
#include "nvmedia_image_nvscibuf.h"
#include "cuda_consumer.h"
#include "nvmedia_producer.h"
#include "nvmedia_surface.h"
#include "nvmedia_utils/cmdline.h"
#include "nvmedia_utils/image_utils.h"
#include "nvsci_setup.h"
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf( \
"NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, __LINE__, _status, NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf("NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, \
__LINE__, \
_status, \
NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
static void cleanup(Blit2DTest* ctx, NvMediaStatus status) {
if (ctx->i2d != NULL) {
NvMedia2DDestroy(ctx->i2d);
}
if (ctx->device != NULL) {
NvMediaDeviceDestroy(ctx->device);
}
if (status != NVMEDIA_STATUS_OK) {
exit(EXIT_FAILURE);
}
}
int main(int argc, char* argv[]) {
TestArgs args;
Blit2DTest ctx;
NvMediaStatus status = NVMEDIA_STATUS_ERROR;
NvSciSyncFence nvMediaSignalerFence = NvSciSyncFenceInitializer;
NvSciSyncFence cudaSignalerFence = NvSciSyncFenceInitializer;
int cudaDeviceId;
uint64_t startTime, endTime;
uint64_t operationStartTime, operationEndTime;
double processingTime;
/* Read configuration from command line and config file */
memset(&args, 0, sizeof(TestArgs));
memset(&ctx, 0, sizeof(Blit2DTest));
/* ParseArgs parses the command line and the 2D configuration file and
* populates all initParams and run time configuration in to appropriate
* structures within args
*/
if (ParseArgs(argc, argv, &args)) {
PrintUsage();
return -1;
}
/* Check version */
NvMediaVersion version;
status = NvMedia2DGetVersion(&version);
if (status == NVMEDIA_STATUS_OK) {
printf("Library version: %u.%u\n", version.major, version.minor);
printf("Header version: %u.%u\n", NVMEDIA_2D_VERSION_MAJOR,
NVMEDIA_2D_VERSION_MINOR);
if ((version.major != NVMEDIA_2D_VERSION_MAJOR) ||
(version.minor != NVMEDIA_2D_VERSION_MINOR)) {
printf("Library and Header mismatch!\n");
cleanup(&ctx, status);
static void cleanup(Blit2DTest *ctx, NvMediaStatus status)
{
if (ctx->i2d != NULL) {
NvMedia2DDestroy(ctx->i2d);
}
}
// Create NvMedia device
ctx.device = NvMediaDeviceCreate();
if (!ctx.device) {
printf("%s: Failed to create NvMedia device\n", __func__);
cleanup(&ctx, status);
}
// Create 2D blitter
ctx.i2d = NvMedia2DCreate(ctx.device);
if (!ctx.i2d) {
printf("%s: Failed to create NvMedia 2D i2d\n", __func__);
cleanup(&ctx, status);
}
cudaDeviceId = findCudaDevice(argc, (const char**)argv);
// NvMedia-CUDA operations without NvSCI APIs starts
cudaResources cudaResObj;
GetTimeMicroSec(&startTime);
setupNvMedia(&args, &ctx);
setupCuda(&ctx, cudaResObj, cudaDeviceId);
GetTimeMicroSec(&operationStartTime);
for (int i = 0; i < args.iterations; i++) {
runNvMediaBlit2D(&args, &ctx);
runCudaOperation(&ctx, cudaResObj, cudaDeviceId);
}
GetTimeMicroSec(&operationEndTime);
cleanupNvMedia(&ctx);
cleanupCuda(&ctx, cudaResObj);
GetTimeMicroSec(&endTime);
// NvMedia-CUDA operations without NvSCI APIs ends
processingTime = (double)(operationEndTime - operationStartTime) / 1000.0;
printf(
"Overall Processing time of NvMedia-CUDA Operations without NvSCI APIs "
"%.4f ms with %zu iterations\n",
processingTime, args.iterations);
processingTime = (double)(endTime - startTime) / 1000.0;
printf(
"Overall Processing time of NvMedia-CUDA Operations + allocation/cleanup "
"without NvSCI APIs %.4f ms with %zu iterations\n",
processingTime, args.iterations);
NvSciBufObj dstNvSciBufobj, srcNvSciBufobj;
NvSciSyncObj nvMediaSignalerSyncObj, cudaSignalerSyncObj;
cudaExternalResInterop cudaExtResObj;
// NvMedia-CUDA operations via interop with NvSCI APIs starts
GetTimeMicroSec(&startTime);
setupNvMediaSignalerNvSciSync(&ctx, nvMediaSignalerSyncObj, cudaDeviceId);
setupCudaSignalerNvSciSync(&ctx, cudaSignalerSyncObj, cudaDeviceId);
setupNvMedia(&args, &ctx, srcNvSciBufobj, dstNvSciBufobj,
nvMediaSignalerSyncObj, cudaSignalerSyncObj, cudaDeviceId);
setupCuda(cudaExtResObj, dstNvSciBufobj, nvMediaSignalerSyncObj,
cudaSignalerSyncObj, cudaDeviceId);
GetTimeMicroSec(&operationStartTime);
for (int i = 0; i < args.iterations; i++) {
runNvMediaBlit2D(&args, &ctx, nvMediaSignalerSyncObj, &cudaSignalerFence,
&nvMediaSignalerFence);
runCudaOperation(cudaExtResObj, &nvMediaSignalerFence, &cudaSignalerFence,
cudaDeviceId, args.iterations);
}
GetTimeMicroSec(&operationEndTime);
cleanupNvMedia(&ctx, nvMediaSignalerSyncObj, cudaSignalerSyncObj);
cleanupCuda(cudaExtResObj);
cleanupNvSciSync(nvMediaSignalerSyncObj);
cleanupNvSciSync(cudaSignalerSyncObj);
cleanupNvSciBuf(srcNvSciBufobj);
cleanupNvSciBuf(dstNvSciBufobj);
GetTimeMicroSec(&endTime);
// NvMedia-CUDA operations via interop with NvSCI APIs ends
processingTime = (double)(operationEndTime - operationStartTime) / 1000.0;
printf(
"Overall Processing time of NvMedia-CUDA Operations with NvSCI APIs %.4f "
"ms with %zu iterations\n",
processingTime, args.iterations);
processingTime = (double)(endTime - startTime) / 1000.0;
printf(
"Overall Processing time of NvMedia-CUDA Operations + allocation/cleanup "
"with NvSCI APIs %.4f ms with %zu iterations\n",
processingTime, args.iterations);
if (ctx.i2d != NULL) {
NvMedia2DDestroy(ctx.i2d);
}
if (ctx.device != NULL) {
NvMediaDeviceDestroy(ctx.device);
}
if (status == NVMEDIA_STATUS_OK) {
return 0;
} else {
return 1;
}
if (ctx->device != NULL) {
NvMediaDeviceDestroy(ctx->device);
}
if (status != NVMEDIA_STATUS_OK) {
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
TestArgs args;
Blit2DTest ctx;
NvMediaStatus status = NVMEDIA_STATUS_ERROR;
NvSciSyncFence nvMediaSignalerFence = NvSciSyncFenceInitializer;
NvSciSyncFence cudaSignalerFence = NvSciSyncFenceInitializer;
int cudaDeviceId;
uint64_t startTime, endTime;
uint64_t operationStartTime, operationEndTime;
double processingTime;
/* Read configuration from command line and config file */
memset(&args, 0, sizeof(TestArgs));
memset(&ctx, 0, sizeof(Blit2DTest));
/* ParseArgs parses the command line and the 2D configuration file and
* populates all initParams and run time configuration in to appropriate
* structures within args
*/
if (ParseArgs(argc, argv, &args)) {
PrintUsage();
return -1;
}
/* Check version */
NvMediaVersion version;
status = NvMedia2DGetVersion(&version);
if (status == NVMEDIA_STATUS_OK) {
printf("Library version: %u.%u\n", version.major, version.minor);
printf("Header version: %u.%u\n", NVMEDIA_2D_VERSION_MAJOR, NVMEDIA_2D_VERSION_MINOR);
if ((version.major != NVMEDIA_2D_VERSION_MAJOR) || (version.minor != NVMEDIA_2D_VERSION_MINOR)) {
printf("Library and Header mismatch!\n");
cleanup(&ctx, status);
}
}
// Create NvMedia device
ctx.device = NvMediaDeviceCreate();
if (!ctx.device) {
printf("%s: Failed to create NvMedia device\n", __func__);
cleanup(&ctx, status);
}
// Create 2D blitter
ctx.i2d = NvMedia2DCreate(ctx.device);
if (!ctx.i2d) {
printf("%s: Failed to create NvMedia 2D i2d\n", __func__);
cleanup(&ctx, status);
}
cudaDeviceId = findCudaDevice(argc, (const char **)argv);
// NvMedia-CUDA operations without NvSCI APIs starts
cudaResources cudaResObj;
GetTimeMicroSec(&startTime);
setupNvMedia(&args, &ctx);
setupCuda(&ctx, cudaResObj, cudaDeviceId);
GetTimeMicroSec(&operationStartTime);
for (int i = 0; i < args.iterations; i++) {
runNvMediaBlit2D(&args, &ctx);
runCudaOperation(&ctx, cudaResObj, cudaDeviceId);
}
GetTimeMicroSec(&operationEndTime);
cleanupNvMedia(&ctx);
cleanupCuda(&ctx, cudaResObj);
GetTimeMicroSec(&endTime);
// NvMedia-CUDA operations without NvSCI APIs ends
processingTime = (double)(operationEndTime - operationStartTime) / 1000.0;
printf("Overall Processing time of NvMedia-CUDA Operations without NvSCI APIs "
"%.4f ms with %zu iterations\n",
processingTime,
args.iterations);
processingTime = (double)(endTime - startTime) / 1000.0;
printf("Overall Processing time of NvMedia-CUDA Operations + allocation/cleanup "
"without NvSCI APIs %.4f ms with %zu iterations\n",
processingTime,
args.iterations);
NvSciBufObj dstNvSciBufobj, srcNvSciBufobj;
NvSciSyncObj nvMediaSignalerSyncObj, cudaSignalerSyncObj;
cudaExternalResInterop cudaExtResObj;
// NvMedia-CUDA operations via interop with NvSCI APIs starts
GetTimeMicroSec(&startTime);
setupNvMediaSignalerNvSciSync(&ctx, nvMediaSignalerSyncObj, cudaDeviceId);
setupCudaSignalerNvSciSync(&ctx, cudaSignalerSyncObj, cudaDeviceId);
setupNvMedia(
&args, &ctx, srcNvSciBufobj, dstNvSciBufobj, nvMediaSignalerSyncObj, cudaSignalerSyncObj, cudaDeviceId);
setupCuda(cudaExtResObj, dstNvSciBufobj, nvMediaSignalerSyncObj, cudaSignalerSyncObj, cudaDeviceId);
GetTimeMicroSec(&operationStartTime);
for (int i = 0; i < args.iterations; i++) {
runNvMediaBlit2D(&args, &ctx, nvMediaSignalerSyncObj, &cudaSignalerFence, &nvMediaSignalerFence);
runCudaOperation(cudaExtResObj, &nvMediaSignalerFence, &cudaSignalerFence, cudaDeviceId, args.iterations);
}
GetTimeMicroSec(&operationEndTime);
cleanupNvMedia(&ctx, nvMediaSignalerSyncObj, cudaSignalerSyncObj);
cleanupCuda(cudaExtResObj);
cleanupNvSciSync(nvMediaSignalerSyncObj);
cleanupNvSciSync(cudaSignalerSyncObj);
cleanupNvSciBuf(srcNvSciBufobj);
cleanupNvSciBuf(dstNvSciBufobj);
GetTimeMicroSec(&endTime);
// NvMedia-CUDA operations via interop with NvSCI APIs ends
processingTime = (double)(operationEndTime - operationStartTime) / 1000.0;
printf("Overall Processing time of NvMedia-CUDA Operations with NvSCI APIs %.4f "
"ms with %zu iterations\n",
processingTime,
args.iterations);
processingTime = (double)(endTime - startTime) / 1000.0;
printf("Overall Processing time of NvMedia-CUDA Operations + allocation/cleanup "
"with NvSCI APIs %.4f ms with %zu iterations\n",
processingTime,
args.iterations);
if (ctx.i2d != NULL) {
NvMedia2DDestroy(ctx.i2d);
}
if (ctx.device != NULL) {
NvMediaDeviceDestroy(ctx.device);
}
if (status == NVMEDIA_STATUS_OK) {
return 0;
}
else {
return 1;
}
}

View File

@@ -25,447 +25,464 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <iostream>
#include <string.h>
/* Nvidia headers */
#include "nvmedia_utils/cmdline.h"
#include "nvmedia_image.h"
#include "nvmedia_2d.h"
#include "nvmedia_surface.h"
#include "nvmedia_utils/image_utils.h"
#include "nvmedia_2d_nvscisync.h"
#include "nvmedia_image.h"
#include "nvmedia_image_nvscibuf.h"
#include "nvmedia_producer.h"
#include "nvmedia_2d_nvscisync.h"
#include "nvmedia_surface.h"
#include "nvmedia_utils/cmdline.h"
#include "nvmedia_utils/image_utils.h"
#include "nvsci_setup.h"
NvMediaImage *NvMediaImageCreateUsingNvScibuf(NvMediaDevice *device,
NvMediaSurfaceType type,
NvMediaImage *NvMediaImageCreateUsingNvScibuf(NvMediaDevice *device,
NvMediaSurfaceType type,
const NvMediaSurfAllocAttr *attrs,
uint32_t numAttrs, uint32_t flags,
NvSciBufObj &bufobj,
int cudaDeviceId) {
NvSciBufModule module = NULL;
NvSciError err = NvSciError_Success;
NvMediaStatus status = NVMEDIA_STATUS_OK;
NvSciBufAttrList attrlist = NULL;
NvSciBufAttrList conflictlist = NULL;
NvSciBufAttrValAccessPerm access_perm = NvSciBufAccessPerm_ReadWrite;
NvSciBufAttrKeyValuePair attr_kvp = {NvSciBufGeneralAttrKey_RequiredPerm,
&access_perm, sizeof(access_perm)};
NvSciBufAttrKeyValuePair pairArrayOut[10];
uint32_t numAttrs,
uint32_t flags,
NvSciBufObj &bufobj,
int cudaDeviceId)
{
NvSciBufModule module = NULL;
NvSciError err = NvSciError_Success;
NvMediaStatus status = NVMEDIA_STATUS_OK;
NvSciBufAttrList attrlist = NULL;
NvSciBufAttrList conflictlist = NULL;
NvSciBufAttrValAccessPerm access_perm = NvSciBufAccessPerm_ReadWrite;
NvSciBufAttrKeyValuePair attr_kvp = {NvSciBufGeneralAttrKey_RequiredPerm, &access_perm, sizeof(access_perm)};
NvSciBufAttrKeyValuePair pairArrayOut[10];
NvMediaImage *image = NULL;
NvMediaImage *image = NULL;
err = NvSciBufModuleOpen(&module);
if (err != NvSciError_Success) {
printf("%s: NvSciBuffModuleOpen failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
err = NvSciBufModuleOpen(&module);
if (err != NvSciError_Success) {
printf("%s: NvSciBuffModuleOpen failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
err = NvSciBufAttrListCreate(module, &attrlist);
if (err != NvSciError_Success) {
printf("%s: SciBufAttrListCreate failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
err = NvSciBufAttrListCreate(module, &attrlist);
if (err != NvSciError_Success) {
printf("%s: SciBufAttrListCreate failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
err = NvSciBufAttrListSetAttrs(attrlist, &attr_kvp, 1);
if (err != NvSciError_Success) {
printf("%s: AccessPermSetAttr failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
err = NvSciBufAttrListSetAttrs(attrlist, &attr_kvp, 1);
if (err != NvSciError_Success) {
printf("%s: AccessPermSetAttr failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
status =
NvMediaImageFillNvSciBufAttrs(device, type, attrs, numAttrs, 0, attrlist);
status = NvMediaImageFillNvSciBufAttrs(device, type, attrs, numAttrs, 0, attrlist);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: ImageFillSciBufAttrs failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
if (status != NVMEDIA_STATUS_OK) {
printf("%s: ImageFillSciBufAttrs failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
setupNvSciBuf(bufobj, attrlist, cudaDeviceId);
setupNvSciBuf(bufobj, attrlist, cudaDeviceId);
status = NvMediaImageCreateFromNvSciBuf(device, bufobj, &image);
status = NvMediaImageCreateFromNvSciBuf(device, bufobj, &image);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: ImageCreatefromSciBuf failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
if (status != NVMEDIA_STATUS_OK) {
printf("%s: ImageCreatefromSciBuf failed. Error: %d \n", __func__, err);
goto fail_cleanup;
}
NvSciBufAttrListFree(attrlist);
NvSciBufAttrListFree(attrlist);
if (module != NULL) {
NvSciBufModuleClose(module);
}
if (module != NULL) {
NvSciBufModuleClose(module);
}
return image;
return image;
fail_cleanup:
if (attrlist != NULL) {
NvSciBufAttrListFree(attrlist);
}
if (bufobj != NULL) {
NvSciBufObjFree(bufobj);
bufobj = NULL;
}
if (attrlist != NULL) {
NvSciBufAttrListFree(attrlist);
}
if (bufobj != NULL) {
NvSciBufObjFree(bufobj);
bufobj = NULL;
}
if (module != NULL) {
NvSciBufModuleClose(module);
}
NvMediaImageDestroy(image);
return NULL;
if (module != NULL) {
NvSciBufModuleClose(module);
}
NvMediaImageDestroy(image);
return NULL;
}
/* Create NvMediaImage surface based on the input attributes.
* Returns NVMEDIA_STATUS_OK on success
*/
static NvMediaStatus createSurface(Blit2DTest *ctx,
static NvMediaStatus createSurface(Blit2DTest *ctx,
NvMediaSurfFormatAttr *surfFormatAttrs,
NvMediaSurfAllocAttr *surfAllocAttrs,
uint32_t numSurfAllocAttrs,
NvMediaImage **image, NvSciBufObj &bufObj,
int cudaDeviceId) {
NvMediaSurfaceType surfType;
NvMediaSurfAllocAttr *surfAllocAttrs,
uint32_t numSurfAllocAttrs,
NvMediaImage **image,
NvSciBufObj &bufObj,
int cudaDeviceId)
{
NvMediaSurfaceType surfType;
/* create source image */
surfType =
NvMediaSurfaceFormatGetType(surfFormatAttrs, NVM_SURF_FMT_ATTR_MAX);
*image = NvMediaImageCreateUsingNvScibuf(ctx->device, /* device */
surfType, /* surface type */
surfAllocAttrs, numSurfAllocAttrs, 0,
bufObj, cudaDeviceId);
/* create source image */
surfType = NvMediaSurfaceFormatGetType(surfFormatAttrs, NVM_SURF_FMT_ATTR_MAX);
*image = NvMediaImageCreateUsingNvScibuf(ctx->device, /* device */
surfType, /* surface type */
surfAllocAttrs,
numSurfAllocAttrs,
0,
bufObj,
cudaDeviceId);
if (*image == NULL) {
printf("Unable to create image\n");
return NVMEDIA_STATUS_ERROR;
}
InitImage(*image, surfAllocAttrs[0].value, surfAllocAttrs[1].value);
if (*image == NULL) {
printf("Unable to create image\n");
return NVMEDIA_STATUS_ERROR;
}
InitImage(*image, surfAllocAttrs[0].value, surfAllocAttrs[1].value);
/* printf("%s: NvMediaImageCreate:: Image size: %ux%u Image type: %d\n",
__func__, surfAllocAttrs[0].value, surfAllocAttrs[1].value,
surfType);*/
/* printf("%s: NvMediaImageCreate:: Image size: %ux%u Image type: %d\n",
__func__, surfAllocAttrs[0].value, surfAllocAttrs[1].value,
surfType);*/
return NVMEDIA_STATUS_OK;
return NVMEDIA_STATUS_OK;
}
/* Create NvMediaImage surface based on the input attributes.
* Returns NVMEDIA_STATUS_OK on success
*/
static NvMediaStatus createSurfaceNonNvSCI(
Blit2DTest *ctx, NvMediaSurfFormatAttr *surfFormatAttrs,
NvMediaSurfAllocAttr *surfAllocAttrs, uint32_t numSurfAllocAttrs,
NvMediaImage **image) {
NvMediaSurfaceType surfType;
static NvMediaStatus createSurfaceNonNvSCI(Blit2DTest *ctx,
NvMediaSurfFormatAttr *surfFormatAttrs,
NvMediaSurfAllocAttr *surfAllocAttrs,
uint32_t numSurfAllocAttrs,
NvMediaImage **image)
{
NvMediaSurfaceType surfType;
/* create source image */
surfType =
NvMediaSurfaceFormatGetType(surfFormatAttrs, NVM_SURF_FMT_ATTR_MAX);
/* create source image */
surfType = NvMediaSurfaceFormatGetType(surfFormatAttrs, NVM_SURF_FMT_ATTR_MAX);
*image = NvMediaImageCreateNew(ctx->device, surfType, surfAllocAttrs,
numSurfAllocAttrs, 0);
*image = NvMediaImageCreateNew(ctx->device, surfType, surfAllocAttrs, numSurfAllocAttrs, 0);
if (*image == NULL) {
printf("Unable to create image\n");
return NVMEDIA_STATUS_ERROR;
}
InitImage(*image, surfAllocAttrs[0].value, surfAllocAttrs[1].value);
if (*image == NULL) {
printf("Unable to create image\n");
return NVMEDIA_STATUS_ERROR;
}
InitImage(*image, surfAllocAttrs[0].value, surfAllocAttrs[1].value);
/* printf("%s: NvMediaImageCreate:: Image size: %ux%u Image type: %d\n",
__func__, surfAllocAttrs[0].value, surfAllocAttrs[1].value,
surfType);*/
/* printf("%s: NvMediaImageCreate:: Image size: %ux%u Image type: %d\n",
__func__, surfAllocAttrs[0].value, surfAllocAttrs[1].value,
surfType);*/
return NVMEDIA_STATUS_OK;
return NVMEDIA_STATUS_OK;
}
static void destroySurface(NvMediaImage *image) { NvMediaImageDestroy(image); }
static NvMediaStatus blit2DImage(Blit2DTest *ctx, TestArgs *args,
NvSciSyncObj &nvMediaSignalerSyncObj,
static NvMediaStatus blit2DImage(Blit2DTest *ctx,
TestArgs *args,
NvSciSyncObj &nvMediaSignalerSyncObj,
NvSciSyncFence *preSyncFence,
NvSciSyncFence *fence) {
NvMediaStatus status;
NvMediaImageSurfaceMap surfaceMap;
NvSciSyncFence *fence)
{
NvMediaStatus status;
NvMediaImageSurfaceMap surfaceMap;
status = ReadImage(args->inputFileName, /* fileName */
0, /* frameNum */
args->srcSurfAllocAttrs[0].value, /* source image width */
args->srcSurfAllocAttrs[1].value, /* source image height */
ctx->srcImage, /* srcImage */
NVMEDIA_TRUE, /* uvOrderFlag */
1, /* bytesPerPixel */
MSB_ALIGNED); /* pixelAlignment */
status = ReadImage(args->inputFileName, /* fileName */
0, /* frameNum */
args->srcSurfAllocAttrs[0].value, /* source image width */
args->srcSurfAllocAttrs[1].value, /* source image height */
ctx->srcImage, /* srcImage */
NVMEDIA_TRUE, /* uvOrderFlag */
1, /* bytesPerPixel */
MSB_ALIGNED); /* pixelAlignment */
if (status != NVMEDIA_STATUS_OK) {
printf("%s: ReadImage failed for input buffer: %d\n", __func__, status);
return status;
}
if ((args->srcRect.x1 <= args->srcRect.x0) ||
(args->srcRect.y1 <= args->srcRect.y0)) {
ctx->srcRect = NULL;
} else {
ctx->srcRect = &(args->srcRect);
}
if ((args->dstRect.x1 <= args->dstRect.x0) ||
(args->dstRect.y1 <= args->dstRect.y0)) {
ctx->dstRect = NULL;
} else {
ctx->dstRect = &(args->dstRect);
}
static int64_t launch = 0;
// Start inserting pre-fence from second launch inorder to for NvMedia2Blit to
// wait
// for cuda signal on fence.
if (launch) {
status = NvMedia2DInsertPreNvSciSyncFence(ctx->i2d, preSyncFence);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DSetNvSciSyncObjforEOF failed: %d\n", __func__,
status);
return status;
printf("%s: ReadImage failed for input buffer: %d\n", __func__, status);
return status;
}
NvSciSyncFenceClear(preSyncFence);
}
launch++;
status = NvMedia2DSetNvSciSyncObjforEOF(ctx->i2d, nvMediaSignalerSyncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DSetNvSciSyncObjforEOF failed: %d\n", __func__,
status);
return status;
}
if ((args->srcRect.x1 <= args->srcRect.x0) || (args->srcRect.y1 <= args->srcRect.y0)) {
ctx->srcRect = NULL;
}
else {
ctx->srcRect = &(args->srcRect);
}
/* 2DBlit processing on input image */
status = NvMedia2DBlitEx(ctx->i2d, /* i2d */
ctx->dstImage, /* dstSurface */
ctx->dstRect, /* dstRect */
ctx->srcImage, /* srcSurface */
ctx->srcRect, /* srcRect */
&args->blitParams, /* params */
NULL); /* paramsOut */
if ((args->dstRect.x1 <= args->dstRect.x0) || (args->dstRect.y1 <= args->dstRect.y0)) {
ctx->dstRect = NULL;
}
else {
ctx->dstRect = &(args->dstRect);
}
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DBlitEx failed: %d\n", __func__, status);
return status;
}
static int64_t launch = 0;
// Start inserting pre-fence from second launch inorder to for NvMedia2Blit to
// wait
// for cuda signal on fence.
if (launch) {
status = NvMedia2DInsertPreNvSciSyncFence(ctx->i2d, preSyncFence);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DSetNvSciSyncObjforEOF failed: %d\n", __func__, status);
return status;
}
NvSciSyncFenceClear(preSyncFence);
}
launch++;
status =
NvMedia2DGetEOFNvSciSyncFence(ctx->i2d, nvMediaSignalerSyncObj, fence);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DGetEOFNvSciSyncFence failed: %d\n", __func__, status);
return status;
}
status = NvMedia2DSetNvSciSyncObjforEOF(ctx->i2d, nvMediaSignalerSyncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DSetNvSciSyncObjforEOF failed: %d\n", __func__, status);
return status;
}
return NVMEDIA_STATUS_OK;
/* 2DBlit processing on input image */
status = NvMedia2DBlitEx(ctx->i2d, /* i2d */
ctx->dstImage, /* dstSurface */
ctx->dstRect, /* dstRect */
ctx->srcImage, /* srcSurface */
ctx->srcRect, /* srcRect */
&args->blitParams, /* params */
NULL); /* paramsOut */
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DBlitEx failed: %d\n", __func__, status);
return status;
}
status = NvMedia2DGetEOFNvSciSyncFence(ctx->i2d, nvMediaSignalerSyncObj, fence);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DGetEOFNvSciSyncFence failed: %d\n", __func__, status);
return status;
}
return NVMEDIA_STATUS_OK;
}
static NvMediaStatus blit2DImageNonNvSCI(Blit2DTest *ctx, TestArgs *args) {
NvMediaStatus status;
NvMediaImageSurfaceMap surfaceMap;
static NvMediaStatus blit2DImageNonNvSCI(Blit2DTest *ctx, TestArgs *args)
{
NvMediaStatus status;
NvMediaImageSurfaceMap surfaceMap;
status = ReadImage(args->inputFileName, /* fileName */
0, /* frameNum */
args->srcSurfAllocAttrs[0].value, /* source image width */
args->srcSurfAllocAttrs[1].value, /* source image height */
ctx->srcImage, /* srcImage */
NVMEDIA_TRUE, /* uvOrderFlag */
1, /* bytesPerPixel */
MSB_ALIGNED); /* pixelAlignment */
status = ReadImage(args->inputFileName, /* fileName */
0, /* frameNum */
args->srcSurfAllocAttrs[0].value, /* source image width */
args->srcSurfAllocAttrs[1].value, /* source image height */
ctx->srcImage, /* srcImage */
NVMEDIA_TRUE, /* uvOrderFlag */
1, /* bytesPerPixel */
MSB_ALIGNED); /* pixelAlignment */
if (status != NVMEDIA_STATUS_OK) {
printf("%s: ReadImage failed for input buffer: %d\n", __func__, status);
return status;
}
if (status != NVMEDIA_STATUS_OK) {
printf("%s: ReadImage failed for input buffer: %d\n", __func__, status);
return status;
}
if ((args->srcRect.x1 <= args->srcRect.x0) ||
(args->srcRect.y1 <= args->srcRect.y0)) {
ctx->srcRect = NULL;
} else {
ctx->srcRect = &(args->srcRect);
}
if ((args->srcRect.x1 <= args->srcRect.x0) || (args->srcRect.y1 <= args->srcRect.y0)) {
ctx->srcRect = NULL;
}
else {
ctx->srcRect = &(args->srcRect);
}
if ((args->dstRect.x1 <= args->dstRect.x0) ||
(args->dstRect.y1 <= args->dstRect.y0)) {
ctx->dstRect = NULL;
} else {
ctx->dstRect = &(args->dstRect);
}
if ((args->dstRect.x1 <= args->dstRect.x0) || (args->dstRect.y1 <= args->dstRect.y0)) {
ctx->dstRect = NULL;
}
else {
ctx->dstRect = &(args->dstRect);
}
/* 2DBlit processing on input image */
status = NvMedia2DBlitEx(ctx->i2d, /* i2d */
ctx->dstImage, /* dstSurface */
ctx->dstRect, /* dstRect */
ctx->srcImage, /* srcSurface */
ctx->srcRect, /* srcRect */
&args->blitParams, /* params */
NULL); /* paramsOut */
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DBlitEx failed: %d\n", __func__, status);
return status;
}
/* 2DBlit processing on input image */
status = NvMedia2DBlitEx(ctx->i2d, /* i2d */
ctx->dstImage, /* dstSurface */
ctx->dstRect, /* dstRect */
ctx->srcImage, /* srcSurface */
ctx->srcRect, /* srcRect */
&args->blitParams, /* params */
NULL); /* paramsOut */
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DBlitEx failed: %d\n", __func__, status);
return status;
}
/* Write output image into buffer */
ctx->bytesPerPixel = 1;
WriteImageToAllocatedBuffer(ctx, ctx->dstImage, NVMEDIA_TRUE, NVMEDIA_FALSE,
ctx->bytesPerPixel);
/* Write output image into buffer */
ctx->bytesPerPixel = 1;
WriteImageToAllocatedBuffer(ctx, ctx->dstImage, NVMEDIA_TRUE, NVMEDIA_FALSE, ctx->bytesPerPixel);
return NVMEDIA_STATUS_OK;
return NVMEDIA_STATUS_OK;
}
static void cleanup(Blit2DTest *ctx, NvMediaStatus status = NVMEDIA_STATUS_OK) {
if (ctx->srcImage != NULL) {
NvMedia2DImageUnRegister(ctx->i2d, ctx->srcImage);
destroySurface(ctx->srcImage);
}
if (ctx->dstImage != NULL) {
NvMedia2DImageUnRegister(ctx->i2d, ctx->dstImage);
destroySurface(ctx->dstImage);
}
if (status != NVMEDIA_STATUS_OK) {
exit(EXIT_FAILURE);
}
static void cleanup(Blit2DTest *ctx, NvMediaStatus status = NVMEDIA_STATUS_OK)
{
if (ctx->srcImage != NULL) {
NvMedia2DImageUnRegister(ctx->i2d, ctx->srcImage);
destroySurface(ctx->srcImage);
}
if (ctx->dstImage != NULL) {
NvMedia2DImageUnRegister(ctx->i2d, ctx->dstImage);
destroySurface(ctx->dstImage);
}
if (status != NVMEDIA_STATUS_OK) {
exit(EXIT_FAILURE);
}
}
void cleanupNvMedia(Blit2DTest *ctx, NvSciSyncObj &syncObj,
NvSciSyncObj &preSyncObj) {
NvMediaStatus status;
cleanup(ctx);
status = NvMedia2DUnregisterNvSciSyncObj(ctx->i2d, syncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
exit(EXIT_FAILURE);
}
status = NvMedia2DUnregisterNvSciSyncObj(ctx->i2d, preSyncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
exit(EXIT_FAILURE);
}
NvMediaImageNvSciBufDeinit();
void cleanupNvMedia(Blit2DTest *ctx, NvSciSyncObj &syncObj, NvSciSyncObj &preSyncObj)
{
NvMediaStatus status;
cleanup(ctx);
status = NvMedia2DUnregisterNvSciSyncObj(ctx->i2d, syncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
exit(EXIT_FAILURE);
}
status = NvMedia2DUnregisterNvSciSyncObj(ctx->i2d, preSyncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
exit(EXIT_FAILURE);
}
NvMediaImageNvSciBufDeinit();
}
void cleanupNvMedia(Blit2DTest *ctx) {
cleanup(ctx);
free(ctx->dstBuffPitches);
free(ctx->dstBuffer);
free(ctx->dstBuff);
void cleanupNvMedia(Blit2DTest *ctx)
{
cleanup(ctx);
free(ctx->dstBuffPitches);
free(ctx->dstBuffer);
free(ctx->dstBuff);
}
void setupNvMedia(TestArgs *args, Blit2DTest *ctx, NvSciBufObj &srcNvSciBufobj,
NvSciBufObj &dstNvSciBufobj, NvSciSyncObj &syncObj,
NvSciSyncObj &preSyncObj, int cudaDeviceId) {
NvMediaStatus status;
status = NvMediaImageNvSciBufInit();
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
cleanup(ctx, status);
}
void setupNvMedia(TestArgs *args,
Blit2DTest *ctx,
NvSciBufObj &srcNvSciBufobj,
NvSciBufObj &dstNvSciBufobj,
NvSciSyncObj &syncObj,
NvSciSyncObj &preSyncObj,
int cudaDeviceId)
{
NvMediaStatus status;
status = NvMediaImageNvSciBufInit();
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMediaImageSciBufInit failed\n", __func__);
cleanup(ctx, status);
}
// Create source surface
status = createSurface(ctx, args->srcSurfFormatAttrs, args->srcSurfAllocAttrs,
args->numSurfAllocAttrs, &ctx->srcImage,
srcNvSciBufobj, cudaDeviceId);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Create source surface
status = createSurface(ctx,
args->srcSurfFormatAttrs,
args->srcSurfAllocAttrs,
args->numSurfAllocAttrs,
&ctx->srcImage,
srcNvSciBufobj,
cudaDeviceId);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Create destination surface
status = createSurface(ctx, args->dstSurfFormatAttrs, args->dstSurfAllocAttrs,
args->numSurfAllocAttrs, &ctx->dstImage,
dstNvSciBufobj, cudaDeviceId);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Create destination surface
status = createSurface(ctx,
args->dstSurfFormatAttrs,
args->dstSurfAllocAttrs,
args->numSurfAllocAttrs,
&ctx->dstImage,
dstNvSciBufobj,
cudaDeviceId);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Register source Surface
status =
NvMedia2DImageRegister(ctx->i2d, ctx->srcImage, NVMEDIA_ACCESS_MODE_READ);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register source surface\n", __func__);
cleanup(ctx, status);
}
// Register destination Surface
status = NvMedia2DImageRegister(ctx->i2d, ctx->dstImage,
NVMEDIA_ACCESS_MODE_READ_WRITE);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register destination surface\n", __func__);
cleanup(ctx, status);
}
// Register source Surface
status = NvMedia2DImageRegister(ctx->i2d, ctx->srcImage, NVMEDIA_ACCESS_MODE_READ);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register source surface\n", __func__);
cleanup(ctx, status);
}
// Register destination Surface
status = NvMedia2DImageRegister(ctx->i2d, ctx->dstImage, NVMEDIA_ACCESS_MODE_READ_WRITE);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register destination surface\n", __func__);
cleanup(ctx, status);
}
status = NvMedia2DRegisterNvSciSyncObj(ctx->i2d, NVMEDIA_EOFSYNCOBJ, syncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to NvMedia2DRegisterNvSciSyncObj\n", __func__);
}
status = NvMedia2DRegisterNvSciSyncObj(ctx->i2d, NVMEDIA_EOFSYNCOBJ, syncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to NvMedia2DRegisterNvSciSyncObj\n", __func__);
}
status =
NvMedia2DRegisterNvSciSyncObj(ctx->i2d, NVMEDIA_PRESYNCOBJ, preSyncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to NvMedia2DRegisterNvSciSyncObj\n", __func__);
}
status = NvMedia2DRegisterNvSciSyncObj(ctx->i2d, NVMEDIA_PRESYNCOBJ, preSyncObj);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to NvMedia2DRegisterNvSciSyncObj\n", __func__);
}
}
// Create NvMedia src & dst image without NvSciBuf
void setupNvMedia(TestArgs *args, Blit2DTest *ctx) {
NvMediaStatus status;
void setupNvMedia(TestArgs *args, Blit2DTest *ctx)
{
NvMediaStatus status;
// Create source surface
status = createSurfaceNonNvSCI(ctx, args->srcSurfFormatAttrs,
args->srcSurfAllocAttrs,
args->numSurfAllocAttrs, &ctx->srcImage);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Create source surface
status = createSurfaceNonNvSCI(
ctx, args->srcSurfFormatAttrs, args->srcSurfAllocAttrs, args->numSurfAllocAttrs, &ctx->srcImage);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Create destination surface
status = createSurfaceNonNvSCI(ctx, args->dstSurfFormatAttrs,
args->dstSurfAllocAttrs,
args->numSurfAllocAttrs, &ctx->dstImage);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Create destination surface
status = createSurfaceNonNvSCI(
ctx, args->dstSurfFormatAttrs, args->dstSurfAllocAttrs, args->numSurfAllocAttrs, &ctx->dstImage);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to create buffer pools\n", __func__);
cleanup(ctx, status);
}
// Register source Surface
status =
NvMedia2DImageRegister(ctx->i2d, ctx->srcImage, NVMEDIA_ACCESS_MODE_READ);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register source surface\n", __func__);
cleanup(ctx, status);
}
// Register source Surface
status = NvMedia2DImageRegister(ctx->i2d, ctx->srcImage, NVMEDIA_ACCESS_MODE_READ);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register source surface\n", __func__);
cleanup(ctx, status);
}
// Register destination Surface
status = NvMedia2DImageRegister(ctx->i2d, ctx->dstImage,
NVMEDIA_ACCESS_MODE_READ_WRITE);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register destination surface\n", __func__);
cleanup(ctx, status);
}
// Register destination Surface
status = NvMedia2DImageRegister(ctx->i2d, ctx->dstImage, NVMEDIA_ACCESS_MODE_READ_WRITE);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Unable to register destination surface\n", __func__);
cleanup(ctx, status);
}
// Allocate buffer for writing image & set image parameters in Blit2DTest.
ctx->bytesPerPixel = 1;
AllocateBufferToWriteImage(ctx, ctx->dstImage, NVMEDIA_TRUE, /* uvOrderFlag */
NVMEDIA_FALSE); /* appendFlag */
// Allocate buffer for writing image & set image parameters in Blit2DTest.
ctx->bytesPerPixel = 1;
AllocateBufferToWriteImage(ctx,
ctx->dstImage,
NVMEDIA_TRUE, /* uvOrderFlag */
NVMEDIA_FALSE); /* appendFlag */
}
void runNvMediaBlit2D(TestArgs *args, Blit2DTest *ctx) {
// Blit2D function
NvMediaStatus status = blit2DImageNonNvSCI(ctx, args);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Blit2D failed\n", __func__);
cleanup(ctx, status);
}
void runNvMediaBlit2D(TestArgs *args, Blit2DTest *ctx)
{
// Blit2D function
NvMediaStatus status = blit2DImageNonNvSCI(ctx, args);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Blit2D failed\n", __func__);
cleanup(ctx, status);
}
}
void runNvMediaBlit2D(TestArgs *args, Blit2DTest *ctx,
NvSciSyncObj &nvMediaSignalerSyncObj,
NvSciSyncFence *preSyncFence, NvSciSyncFence *fence) {
// Blit2D function
NvMediaStatus status =
blit2DImage(ctx, args, nvMediaSignalerSyncObj, preSyncFence, fence);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Blit2D failed\n", __func__);
cleanup(ctx, status);
}
void runNvMediaBlit2D(TestArgs *args,
Blit2DTest *ctx,
NvSciSyncObj &nvMediaSignalerSyncObj,
NvSciSyncFence *preSyncFence,
NvSciSyncFence *fence)
{
// Blit2D function
NvMediaStatus status = blit2DImage(ctx, args, nvMediaSignalerSyncObj, preSyncFence, fence);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: Blit2D failed\n", __func__);
cleanup(ctx, status);
}
}

View File

@@ -27,22 +27,28 @@
#ifndef __NVMEDIA_PRODUCER_H__
#define __NVMEDIA_PRODUCER_H__
#include "nvmedia_utils/cmdline.h"
#include "nvmedia_image.h"
#include "nvmedia_2d.h"
#include "nvmedia_surface.h"
#include "nvmedia_utils/image_utils.h"
#include "nvmedia_image.h"
#include "nvmedia_image_nvscibuf.h"
#include "nvmedia_surface.h"
#include "nvmedia_utils/cmdline.h"
#include "nvmedia_utils/image_utils.h"
#include "nvscisync.h"
void runNvMediaBlit2D(TestArgs* args, Blit2DTest* ctx, NvSciSyncObj& syncObj,
NvSciSyncFence* preSyncFence, NvSciSyncFence* fence);
void runNvMediaBlit2D(TestArgs* args, Blit2DTest* ctx);
void setupNvMedia(TestArgs* args, Blit2DTest* ctx, NvSciBufObj& srcNvSciBufobj,
NvSciBufObj& dstNvSciBufobj, NvSciSyncObj& syncObj,
NvSciSyncObj& preSyncObj, int cudaDeviceId);
void setupNvMedia(TestArgs* args, Blit2DTest* ctx);
void cleanupNvMedia(Blit2DTest* ctx, NvSciSyncObj& syncObj,
NvSciSyncObj& preSyncObj);
void cleanupNvMedia(Blit2DTest* ctx);
void runNvMediaBlit2D(TestArgs *args,
Blit2DTest *ctx,
NvSciSyncObj &syncObj,
NvSciSyncFence *preSyncFence,
NvSciSyncFence *fence);
void runNvMediaBlit2D(TestArgs *args, Blit2DTest *ctx);
void setupNvMedia(TestArgs *args,
Blit2DTest *ctx,
NvSciBufObj &srcNvSciBufobj,
NvSciBufObj &dstNvSciBufobj,
NvSciSyncObj &syncObj,
NvSciSyncObj &preSyncObj,
int cudaDeviceId);
void setupNvMedia(TestArgs *args, Blit2DTest *ctx);
void cleanupNvMedia(Blit2DTest *ctx, NvSciSyncObj &syncObj, NvSciSyncObj &preSyncObj);
void cleanupNvMedia(Blit2DTest *ctx);
#endif

View File

@@ -35,10 +35,10 @@
/* Nvidia headers */
#include "cmdline.h"
#include "log_utils.h"
#include "misc_utils.h"
#include "config_parser.h"
#include "helper_cuda.h"
#include "log_utils.h"
#include "misc_utils.h"
/* see cmdline.h for details */
void PrintUsage()
@@ -59,11 +59,11 @@ SectionMap sectionsMap[] = {
/* see cmdline.h for details */
int ParseArgs(int argc, char *argv[], TestArgs *args)
{
NvMediaBool bLastArg = NVMEDIA_FALSE;
NvMediaBool bDataAvailable = NVMEDIA_FALSE;
NvMediaStatus status = NVMEDIA_STATUS_OK;
const char* filename = NULL;
int i;
NvMediaBool bLastArg = NVMEDIA_FALSE;
NvMediaBool bDataAvailable = NVMEDIA_FALSE;
NvMediaStatus status = NVMEDIA_STATUS_OK;
const char *filename = NULL;
int i;
args->srcSurfAllocAttrs[0].type = args->dstSurfAllocAttrs[0].type = NVM_SURF_ATTR_WIDTH;
args->srcSurfAllocAttrs[1].type = args->dstSurfAllocAttrs[1].type = NVM_SURF_ATTR_HEIGHT;
@@ -73,7 +73,7 @@ int ParseArgs(int argc, char *argv[], TestArgs *args)
args->srcSurfAllocAttrs[5].type = args->dstSurfAllocAttrs[5].type = NVM_SURF_ATTR_ALLOC_TYPE;
args->srcSurfAllocAttrs[6].type = args->dstSurfAllocAttrs[6].type = NVM_SURF_ATTR_SCAN_TYPE;
args->srcSurfAllocAttrs[7].type = args->dstSurfAllocAttrs[7].type = NVM_SURF_ATTR_COLOR_STD_TYPE;
args->numSurfAllocAttrs = 8;
args->numSurfAllocAttrs = 8;
args->srcSurfFormatAttrs[0].type = args->dstSurfFormatAttrs[0].type = NVM_SURF_ATTR_SURF_TYPE;
args->srcSurfFormatAttrs[1].type = args->dstSurfFormatAttrs[1].type = NVM_SURF_ATTR_LAYOUT;
@@ -87,56 +87,74 @@ int ParseArgs(int argc, char *argv[], TestArgs *args)
* See nvmedia_2d.h and sample config file(s) for details.
*/
ConfigParamsMap paramsMap[] = {
/*ParamName, &args->variableName, paramType, D, LimitType, Mn, Mx, CharSize, p2C, section */
{"transformMode", &args->blitParams.dstTransform, TYPE_UINT, 0, LIMITS_BOTH, 0, 7, 0, 0, SECTION_NONE},
{"filterMode", &args->blitParams.filter, TYPE_UINT, 1, LIMITS_BOTH, 1, 4, 0, 0, SECTION_NONE},
{"colorStd", &args->blitParams.colorStandard, TYPE_UINT, 0, LIMITS_MIN, 0, 3, 0, 0, SECTION_NONE},
{"validOperations", &args->blitParams.validFields, TYPE_UINT, 0, LIMITS_BOTH, 0, 15, 0, 0, SECTION_NONE},
{"inputfile", &args->inputFileName, TYPE_CHAR_ARR, 0, LIMITS_NONE, 0, 0, FILE_NAME_SIZE, 0, SECTION_NONE},
/*ParamName, &args->variableName, paramType, D, LimitType, Mn,
Mx, CharSize, p2C, section */
{"transformMode", &args->blitParams.dstTransform, TYPE_UINT, 0, LIMITS_BOTH, 0, 7, 0, 0, SECTION_NONE},
{"filterMode", &args->blitParams.filter, TYPE_UINT, 1, LIMITS_BOTH, 1, 4, 0, 0, SECTION_NONE},
{"colorStd", &args->blitParams.colorStandard, TYPE_UINT, 0, LIMITS_MIN, 0, 3, 0, 0, SECTION_NONE},
{"validOperations", &args->blitParams.validFields, TYPE_UINT, 0, LIMITS_BOTH, 0, 15, 0, 0, SECTION_NONE},
{"inputfile", &args->inputFileName, TYPE_CHAR_ARR, 0, LIMITS_NONE, 0, 0, FILE_NAME_SIZE, 0, SECTION_NONE},
/*src surface alloc attributes*/
{"srcWidth", &args->srcSurfAllocAttrs[0].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcHeight", &args->srcSurfAllocAttrs[1].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcCPUAccess", &args->srcSurfAllocAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"srcAllocType", &args->srcSurfAllocAttrs[5].value, TYPE_UINT, 0, LIMITS_BOTH, 0, 1, 0, 0, SECTION_NONE},
{"srcScanType", &args->srcSurfAllocAttrs[6].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 1, 0, 0, SECTION_NONE},
{"srcColorStd", &args->srcSurfAllocAttrs[7].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 12, 0, 0, SECTION_NONE},
{"srcWidth", &args->srcSurfAllocAttrs[0].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcHeight", &args->srcSurfAllocAttrs[1].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcCPUAccess", &args->srcSurfAllocAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"srcAllocType", &args->srcSurfAllocAttrs[5].value, TYPE_UINT, 0, LIMITS_BOTH, 0, 1, 0, 0, SECTION_NONE},
{"srcScanType", &args->srcSurfAllocAttrs[6].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 1, 0, 0, SECTION_NONE},
{"srcColorStd", &args->srcSurfAllocAttrs[7].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 12, 0, 0, SECTION_NONE},
/*src surface format attributes*/
{"srcSurfType", &args->srcSurfFormatAttrs[0].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"srcLayout", &args->srcSurfFormatAttrs[1].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 2, 0, 0, SECTION_NONE},
{"srcDataType", &args->srcSurfFormatAttrs[2].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 4, 0, 0, SECTION_NONE},
{"srcMemory", &args->srcSurfFormatAttrs[3].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"srcSubSamplingType", &args->srcSurfFormatAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 0, 4, 0, 0, SECTION_NONE},
{"srcBitsPerComponent", &args->srcSurfFormatAttrs[5].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 10, 0, 0, SECTION_NONE},
{"srcComponentOrder", &args->srcSurfFormatAttrs[6].value, TYPE_UINT, 2, LIMITS_BOTH, 1, 45, 0, 0, SECTION_NONE},
{"srcSurfType", &args->srcSurfFormatAttrs[0].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"srcLayout", &args->srcSurfFormatAttrs[1].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 2, 0, 0, SECTION_NONE},
{"srcDataType", &args->srcSurfFormatAttrs[2].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 4, 0, 0, SECTION_NONE},
{"srcMemory", &args->srcSurfFormatAttrs[3].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"srcSubSamplingType", &args->srcSurfFormatAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 0, 4, 0, 0, SECTION_NONE},
{"srcBitsPerComponent",
&args->srcSurfFormatAttrs[5].value,
TYPE_UINT,
1,
LIMITS_BOTH,
1,
10,
0,
0,
SECTION_NONE},
{"srcComponentOrder", &args->srcSurfFormatAttrs[6].value, TYPE_UINT, 2, LIMITS_BOTH, 1, 45, 0, 0, SECTION_NONE},
/*srcRect*/
{"srcRectx0", &args->srcRect.x0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcRecty0", &args->srcRect.y0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcRectx1", &args->srcRect.x1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcRecty1", &args->srcRect.y1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcRectx0", &args->srcRect.x0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcRecty0", &args->srcRect.y0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcRectx1", &args->srcRect.x1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"srcRecty1", &args->srcRect.y1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
/*dst surface alloc attributes*/
{"dstWidth", &args->dstSurfAllocAttrs[0].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstHeight", &args->dstSurfAllocAttrs[1].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstCPUAccess", &args->dstSurfAllocAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"dstAllocType", &args->dstSurfAllocAttrs[5].value, TYPE_UINT, 0, LIMITS_BOTH, 0, 1, 0, 0, SECTION_NONE},
{"dstScanType", &args->dstSurfAllocAttrs[6].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 1, 0, 0, SECTION_NONE},
{"dstColorStd", &args->dstSurfAllocAttrs[7].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 12, 0, 0, SECTION_NONE},
{"dstWidth", &args->dstSurfAllocAttrs[0].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstHeight", &args->dstSurfAllocAttrs[1].value, TYPE_UINT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstCPUAccess", &args->dstSurfAllocAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"dstAllocType", &args->dstSurfAllocAttrs[5].value, TYPE_UINT, 0, LIMITS_BOTH, 0, 1, 0, 0, SECTION_NONE},
{"dstScanType", &args->dstSurfAllocAttrs[6].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 1, 0, 0, SECTION_NONE},
{"dstColorStd", &args->dstSurfAllocAttrs[7].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 12, 0, 0, SECTION_NONE},
/*dst surface format attributes*/
{"dstSurfType", &args->dstSurfFormatAttrs[0].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"dstLayout", &args->dstSurfFormatAttrs[1].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 2, 0, 0, SECTION_NONE},
{"dstDataType", &args->dstSurfFormatAttrs[2].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 4, 0, 0, SECTION_NONE},
{"dstMemory", &args->dstSurfFormatAttrs[3].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"dstSubSamplingType", &args->dstSurfFormatAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 0, 4, 0, 0, SECTION_NONE},
{"dstBitsPerComponent", &args->dstSurfFormatAttrs[5].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 10, 0, 0, SECTION_NONE},
{"dstComponentOrder", &args->dstSurfFormatAttrs[6].value, TYPE_UINT, 2, LIMITS_BOTH, 1, 45, 0, 0, SECTION_NONE},
{"dstSurfType", &args->dstSurfFormatAttrs[0].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"dstLayout", &args->dstSurfFormatAttrs[1].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 2, 0, 0, SECTION_NONE},
{"dstDataType", &args->dstSurfFormatAttrs[2].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 4, 0, 0, SECTION_NONE},
{"dstMemory", &args->dstSurfFormatAttrs[3].value, TYPE_UINT, 1, LIMITS_BOTH, 1, 3, 0, 0, SECTION_NONE},
{"dstSubSamplingType", &args->dstSurfFormatAttrs[4].value, TYPE_UINT, 1, LIMITS_BOTH, 0, 4, 0, 0, SECTION_NONE},
{"dstBitsPerComponent",
&args->dstSurfFormatAttrs[5].value,
TYPE_UINT,
1,
LIMITS_BOTH,
1,
10,
0,
0,
SECTION_NONE},
{"dstComponentOrder", &args->dstSurfFormatAttrs[6].value, TYPE_UINT, 2, LIMITS_BOTH, 1, 45, 0, 0, SECTION_NONE},
/*dstRect*/
{"dstRectx0", &args->dstRect.x0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstRecty0", &args->dstRect.y0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstRectx1", &args->dstRect.x1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstRecty1", &args->dstRect.y1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstRectx0", &args->dstRect.x0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstRecty0", &args->dstRect.y0, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstRectx1", &args->dstRect.x1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
{"dstRecty1", &args->dstRect.y1, TYPE_USHORT, 0, LIMITS_MIN, 0, 0, 0, 0, SECTION_NONE},
/*End of the array */
{NULL, NULL, TYPE_UINT, 0, LIMITS_NONE, 0, 0, 0, 0, SECTION_NONE}
};
{NULL, NULL, TYPE_UINT, 0, LIMITS_NONE, 0, 0, 0, 0, SECTION_NONE}};
args->iterations = 100; // Set default iterations value.
@@ -146,7 +164,7 @@ int ParseArgs(int argc, char *argv[], TestArgs *args)
if (checkCmdLineFlag(argc, (const char **)argv, "cf")) {
char *inputFileName = NULL;
getCmdLineArgumentString(argc, (const char **)argv, "cf", (char**)&inputFileName);
getCmdLineArgumentString(argc, (const char **)argv, "cf", (char **)&inputFileName);
if (!inputFileName) {
printf("ERR: Invalid config file name\n");
return -1;
@@ -162,8 +180,7 @@ int ParseArgs(int argc, char *argv[], TestArgs *args)
filename = sdkFindFilePath("sample.cfg", ".");
}
if (filename != NULL)
{
if (filename != NULL) {
printf("Using config file %s\n", filename);
/* Init Parser Map*/
@@ -173,7 +190,7 @@ int ParseArgs(int argc, char *argv[], TestArgs *args)
return -1;
}
status = ConfigParser_ParseFile(paramsMap, 1, sectionsMap, (char*)filename);
status = ConfigParser_ParseFile(paramsMap, 1, sectionsMap, (char *)filename);
if (status != NVMEDIA_STATUS_OK) {
printf("ERR: Failed to parse config file. status:%x\n", status);
return -1;
@@ -189,4 +206,3 @@ int ParseArgs(int argc, char *argv[], TestArgs *args)
return 0;
}

View File

@@ -36,55 +36,57 @@
#define FILE_NAME_SIZE 1024
/* TestArgs contains all arguments required to run the 2D test */
typedef struct _TestArgs {
typedef struct _TestArgs
{
char inputFileName[FILE_NAME_SIZE];
NvMediaSurfAllocAttr srcSurfAllocAttrs[NVM_SURF_ALLOC_ATTR_MAX];
NvMediaSurfAllocAttr dstSurfAllocAttrs[NVM_SURF_ALLOC_ATTR_MAX];
uint32_t numSurfAllocAttrs;
uint32_t numSurfAllocAttrs;
NvMediaSurfFormatAttr srcSurfFormatAttrs[NVM_SURF_FMT_ATTR_MAX];
NvMediaSurfFormatAttr dstSurfFormatAttrs[NVM_SURF_FMT_ATTR_MAX];
NvMediaRect srcRect;
NvMediaRect dstRect;
NvMedia2DBlitParameters blitParams;
size_t iterations;
NvMediaRect srcRect;
NvMediaRect dstRect;
NvMedia2DBlitParameters blitParams;
size_t iterations;
} TestArgs;
typedef struct {
NvMediaDevice *device;
typedef struct
{
NvMediaDevice *device;
/* I2D for 2D blit processing */
NvMedia2D *i2d;
NvMediaImage *srcImage;
NvMediaImage *dstImage;
NvMediaRect *srcRect;
NvMediaRect *dstRect;
uint8_t **dstBuff;
uint32_t *dstBuffPitches;
uint8_t *dstBuffer;
uint32_t numSurfaces;
uint32_t bytesPerPixel;
uint32_t heightSurface;
uint32_t widthSurface;
float *xScalePtr;
float *yScalePtr;
NvMedia2D *i2d;
NvMediaImage *srcImage;
NvMediaImage *dstImage;
NvMediaRect *srcRect;
NvMediaRect *dstRect;
uint8_t **dstBuff;
uint32_t *dstBuffPitches;
uint8_t *dstBuffer;
uint32_t numSurfaces;
uint32_t bytesPerPixel;
uint32_t heightSurface;
uint32_t widthSurface;
float *xScalePtr;
float *yScalePtr;
} Blit2DTest;
/* Prints application usage options */
void PrintUsage (void);
void PrintUsage(void);
/* Parses command line arguments.
* Also parses any configuration files supplied in the command line arguments.
* Arguments:
* argc
* (in) Number of tokens in the command line
* argv
* (in) Command line tokens
* args
* (out) Pointer to test arguments structure
*/
int ParseArgs(int argc, char **argv, TestArgs *args);
* Also parses any configuration files supplied in the command line arguments.
* Arguments:
* argc
* (in) Number of tokens in the command line
* argv
* (in) Command line tokens
* args
* (out) Pointer to test arguments structure
*/
int ParseArgs(int argc, char **argv, TestArgs *args);
#endif /* _NVMEDIA_2D_CMD_LINE_H_ */

View File

@@ -25,9 +25,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config_parser.h"
#include <stdlib.h>
#include "config_parser.h"
#include "log_utils.h"
#if defined(__QNX__)
#include <strings.h>
@@ -37,11 +38,12 @@ static NvMediaStatus GetParamIndex(ConfigParamsMap *paramsMap, char *paramName,
{
int i = 0;
while(paramsMap[i].paramName != NULL) {
while (paramsMap[i].paramName != NULL) {
if (strcasecmp(paramsMap[i].paramName, paramName) == 0) {
*index = i;
return NVMEDIA_STATUS_OK;
} else {
}
else {
i++;
}
}
@@ -53,11 +55,12 @@ NvMediaStatus ConfigParser_GetSectionIndexByName(SectionMap *sectionsMap, char *
{
unsigned int i = 0;
while(sectionsMap[i].secType != SECTION_NONE) {
if(strcmp(sectionsMap[i].name, sectionName) == 0) {
while (sectionsMap[i].secType != SECTION_NONE) {
if (strcmp(sectionsMap[i].name, sectionName) == 0) {
*index = i;
return NVMEDIA_STATUS_OK;
} else {
}
else {
i++;
}
}
@@ -69,11 +72,12 @@ NvMediaStatus ConfigParser_GetSectionIndexByType(SectionMap *sectionsMap, Sectio
{
unsigned int i = 0;
while(sectionsMap[i].secType != SECTION_NONE) {
if(sectionsMap[i].secType == sectionType) {
while (sectionsMap[i].secType != SECTION_NONE) {
if (sectionsMap[i].secType == sectionType) {
*index = i;
return NVMEDIA_STATUS_OK;
} else {
}
else {
i++;
}
}
@@ -86,10 +90,10 @@ static NvMediaStatus GetFileContent(char *filename, char **fileContentOut)
{
FILE *file;
char *fileCotent;
long fileSize;
long fileSize;
file = fopen(filename, "r");
if(file == NULL) {
if (file == NULL) {
printf("Parser_GetFileContent: Cannot open configuration file %s\n", filename);
return NVMEDIA_STATUS_BAD_PARAMETER;
}
@@ -100,152 +104,162 @@ static NvMediaStatus GetFileContent(char *filename, char **fileContentOut)
}
fileSize = ftell(file);
if(fileSize < 0 || fileSize > 150000) {
if (fileSize < 0 || fileSize > 150000) {
printf("Parser_GetFileContent: Unreasonable Filesize %ld encountered for file %s\n", fileSize, filename);
return NVMEDIA_STATUS_ERROR;
}
if(fseek (file, 0, SEEK_SET) != 0) {
if (fseek(file, 0, SEEK_SET) != 0) {
printf("Parser_GetFileContent: Cannot fseek in configuration file %s\n", filename);
return NVMEDIA_STATUS_ERROR;
}
fileCotent = (char*)malloc(fileSize + 1);
if(fileCotent == NULL) {
fileCotent = (char *)malloc(fileSize + 1);
if (fileCotent == NULL) {
printf("Parser_GetFileContent: Failed allocating buffer for file Content\n");
return NVMEDIA_STATUS_OUT_OF_MEMORY;
}
fileSize = (long)fread(fileCotent, 1, fileSize, file);
fileSize = (long)fread(fileCotent, 1, fileSize, file);
fileCotent[fileSize] = '\0';
*fileContentOut = fileCotent;
*fileContentOut = fileCotent;
fclose(file);
return NVMEDIA_STATUS_OK;
}
NvMediaStatus ConfigParser_ParseFile(ConfigParamsMap *paramsMap, unsigned int numParams, SectionMap *sectionsMap, char *fileName)
NvMediaStatus
ConfigParser_ParseFile(ConfigParamsMap *paramsMap, unsigned int numParams, SectionMap *sectionsMap, char *fileName)
{
char *items[MAX_ITEMS_TO_PARSE] = {NULL};
int intValue, itemsCount = 0, i = 0, sectionIndex = 0;
double doubleValue;
float floatValue;
unsigned int currItemIndex, uintValue, sectionId = 0, currSectionId = 0, charValue, paramDefaultLength;
unsigned short ushortValue;
short shortValue;
char *items[MAX_ITEMS_TO_PARSE] = {NULL};
int intValue, itemsCount = 0, i = 0, sectionIndex = 0;
double doubleValue;
float floatValue;
unsigned int currItemIndex, uintValue, sectionId = 0, currSectionId = 0, charValue, paramDefaultLength;
unsigned short ushortValue;
short shortValue;
unsigned long long ullValue;
NvMediaBool isInString = NVMEDIA_FALSE, isInItem = NVMEDIA_FALSE;
char *buffer, *bufferEnd, *param, *pParamLength;
char sectionName[100];
char currDigit;
char *configContentBuf = NULL;
unsigned int numSetsInSection = 0;
NvMediaBool isInString = NVMEDIA_FALSE, isInItem = NVMEDIA_FALSE;
char *buffer, *bufferEnd, *param, *pParamLength;
char sectionName[100];
char currDigit;
char *configContentBuf = NULL;
unsigned int numSetsInSection = 0;
if(GetFileContent(fileName, &configContentBuf) != NVMEDIA_STATUS_OK) {
if (GetFileContent(fileName, &configContentBuf) != NVMEDIA_STATUS_OK) {
printf("ConfigParser_ParseFile: Failed reading file %s", fileName);
return NVMEDIA_STATUS_ERROR;
}
buffer = configContentBuf;
buffer = configContentBuf;
bufferEnd = &configContentBuf[strlen(configContentBuf)];
// Stage one: Create items mapping in the content using "items" pointers array. For each parameter we have 3 items: param name, '=' char and the param value.
while(buffer < bufferEnd) {
if(itemsCount >= MAX_ITEMS_TO_PARSE) {
LOG_WARN("ConfigParser_ParseFile: Number of items in configuration file exceeded the maximum allowed (%d). Only %d items will be parsed.\n",
MAX_ITEMS_TO_PARSE, MAX_ITEMS_TO_PARSE);
// Stage one: Create items mapping in the content using "items" pointers array. For each parameter we have 3 items:
// param name, '=' char and the param value.
while (buffer < bufferEnd) {
if (itemsCount >= MAX_ITEMS_TO_PARSE) {
LOG_WARN("ConfigParser_ParseFile: Number of items in configuration file exceeded the maximum allowed (%d). "
"Only %d items will be parsed.\n",
MAX_ITEMS_TO_PARSE,
MAX_ITEMS_TO_PARSE);
itemsCount = MAX_ITEMS_TO_PARSE;
break;
}
switch(*buffer) {
// Carriage return
case 13:
switch (*buffer) {
// Carriage return
case 13:
++buffer;
break;
case '#':
*buffer = '\0'; // Replace '#' with '\0' in case of comment immediately following integer or string
while (*buffer != '\n' && buffer < bufferEnd) { // Skip till EOL or EOF
++buffer;
break;
case '#':
*buffer = '\0'; // Replace '#' with '\0' in case of comment immediately following integer or string
while(*buffer != '\n' && buffer < bufferEnd) { // Skip till EOL or EOF
++buffer;
}
isInString = NVMEDIA_FALSE;
isInItem = NVMEDIA_FALSE;
break;
case '\n':
isInItem = NVMEDIA_FALSE;
isInString = NVMEDIA_FALSE;
*buffer++='\0';
break;
case ' ':
case '\t': // Skip whitespace, leave state unchanged
if(isInString)
buffer++;
else { // Terminate non-strings once whitespace is found
*buffer++ = '\0';
isInItem = NVMEDIA_FALSE;
}
break;
case '"': // Begin/End of String
*buffer++ = '\0';
if(!isInString) {
items[itemsCount++] = buffer;
isInItem = ~isInItem;
} else {
isInItem = NVMEDIA_FALSE;
}
isInString = ~isInString; // Toggle
break;
case '[':
*(buffer++) = '\0';
items[itemsCount++] = buffer;
while(*buffer != ' ' && *buffer != '\n' && buffer < bufferEnd) { // Skip till whitespace (after which is located the parsed section number) or EOL or EOF
sectionName[i++] = *(buffer++);
}
sectionName[i] = '\0';
i = 0;
while(*buffer == ' ') {
*(buffer++) = '\0';
}
items[itemsCount++] = buffer;
while(*buffer != ']' && *buffer != '\n' && buffer < bufferEnd) { // Read the section number
currDigit = *buffer;
sectionIndex = sectionIndex * 10 + (currDigit - '0');
buffer++;
}
*(buffer++) = '\0';
sectionIndex--;
if(ConfigParser_GetSectionIndexByName(sectionsMap, sectionName, &sectionId) != NVMEDIA_STATUS_OK) {
printf("ConfigParser_ParseFile: SectionName couldn't be found in section map: '%s'.\n", sectionName);
}
numSetsInSection++;
sectionsMap[sectionId].lastSectionIndex = sectionIndex;
sectionIndex = 0;
isInString = NVMEDIA_FALSE;
isInItem = NVMEDIA_FALSE;
break;
default:
if(!isInItem) {
items[itemsCount++] = buffer;
isInItem = ~isInItem;
}
}
isInString = NVMEDIA_FALSE;
isInItem = NVMEDIA_FALSE;
break;
case '\n':
isInItem = NVMEDIA_FALSE;
isInString = NVMEDIA_FALSE;
*buffer++ = '\0';
break;
case ' ':
case '\t': // Skip whitespace, leave state unchanged
if (isInString)
buffer++;
else { // Terminate non-strings once whitespace is found
*buffer++ = '\0';
isInItem = NVMEDIA_FALSE;
}
break;
case '"': // Begin/End of String
*buffer++ = '\0';
if (!isInString) {
items[itemsCount++] = buffer;
isInItem = ~isInItem;
}
else {
isInItem = NVMEDIA_FALSE;
}
isInString = ~isInString; // Toggle
break;
case '[':
*(buffer++) = '\0';
items[itemsCount++] = buffer;
while (*buffer != ' ' && *buffer != '\n'
&& buffer < bufferEnd) { // Skip till whitespace (after which is located the parsed section number)
// or EOL or EOF
sectionName[i++] = *(buffer++);
}
sectionName[i] = '\0';
i = 0;
while (*buffer == ' ') {
*(buffer++) = '\0';
}
items[itemsCount++] = buffer;
while (*buffer != ']' && *buffer != '\n' && buffer < bufferEnd) { // Read the section number
currDigit = *buffer;
sectionIndex = sectionIndex * 10 + (currDigit - '0');
buffer++;
}
*(buffer++) = '\0';
sectionIndex--;
if (ConfigParser_GetSectionIndexByName(sectionsMap, sectionName, &sectionId) != NVMEDIA_STATUS_OK) {
printf("ConfigParser_ParseFile: SectionName couldn't be found in section map: '%s'.\n", sectionName);
}
numSetsInSection++;
sectionsMap[sectionId].lastSectionIndex = sectionIndex;
sectionIndex = 0;
isInString = NVMEDIA_FALSE;
isInItem = NVMEDIA_FALSE;
break;
default:
if (!isInItem) {
items[itemsCount++] = buffer;
isInItem = ~isInItem;
}
buffer++;
}
}
itemsCount--;
if(numSetsInSection > numParams) {
printf("%s: Not enough buffers allocated for parsing. Number of sets allocated: %d. Number of sets in config file: %d \n",
__func__, numParams, numSetsInSection);
if(configContentBuf) {
if (numSetsInSection > numParams) {
printf("%s: Not enough buffers allocated for parsing. Number of sets allocated: %d. Number of sets in config "
"file: %d \n",
__func__,
numParams,
numSetsInSection);
if (configContentBuf) {
free(configContentBuf);
}
return NVMEDIA_STATUS_ERROR;
}
// Stage 2: Go through the list of items and save their values in parameters map
for(i = 0; i < itemsCount; i += 3) {
if(ConfigParser_GetSectionIndexByName(sectionsMap, items[i], &currItemIndex) == NVMEDIA_STATUS_OK) {
for (i = 0; i < itemsCount; i += 3) {
if (ConfigParser_GetSectionIndexByName(sectionsMap, items[i], &currItemIndex) == NVMEDIA_STATUS_OK) {
currSectionId = atoi(items[i + 1]);
currSectionId--;
LOG_DBG("ConfigParser_ParseFile: Parsing section %s index %d\n", items[i], currSectionId);
@@ -253,105 +267,130 @@ NvMediaStatus ConfigParser_ParseFile(ConfigParamsMap *paramsMap, unsigned int nu
continue;
}
if(GetParamIndex(paramsMap, items[i], &currItemIndex) != NVMEDIA_STATUS_OK) {
LOG_WARN("ConfigParser_ParseFile: Parameter Name '%s' is not recognized. Dismissing this parameter.\n", items[i]);
if (GetParamIndex(paramsMap, items[i], &currItemIndex) != NVMEDIA_STATUS_OK) {
LOG_WARN("ConfigParser_ParseFile: Parameter Name '%s' is not recognized. Dismissing this parameter.\n",
items[i]);
continue;
}
if(strcmp("=", items[i + 1])) {
printf("ConfigParser_ParseFile: '=' expected as the second token in each line. Error caught while parsing parameter '%s'.\n", items[i]);
if (strcmp("=", items[i + 1])) {
printf("ConfigParser_ParseFile: '=' expected as the second token in each line. Error caught while parsing "
"parameter '%s'.\n",
items[i]);
i -= 2;
continue;
}
if(ConfigParser_GetSectionIndexByType(sectionsMap, paramsMap[currItemIndex].sectionType, &sectionId) != NVMEDIA_STATUS_OK) {
printf("ConfigParser_ParseFile: Section index couldn't be found in section map by type. Param Name: '%s'.\n", paramsMap[currItemIndex].paramName);
if (ConfigParser_GetSectionIndexByType(sectionsMap, paramsMap[currItemIndex].sectionType, &sectionId)
!= NVMEDIA_STATUS_OK) {
printf(
"ConfigParser_ParseFile: Section index couldn't be found in section map by type. Param Name: '%s'.\n",
paramsMap[currItemIndex].paramName);
}
if(sectionsMap[sectionId].lastSectionIndex == 0) {
if (sectionsMap[sectionId].lastSectionIndex == 0) {
// Param is not part of a collection or collection includes only one item
currSectionId = 0;
}
param = (char *)paramsMap[currItemIndex].mappedLocation + currSectionId * sectionsMap[sectionId].sizeOfStruct;
pParamLength = (char *)paramsMap[currItemIndex].stringLengthAddr + currSectionId * sectionsMap[sectionId].sizeOfStruct;
pParamLength =
(char *)paramsMap[currItemIndex].stringLengthAddr + currSectionId * sectionsMap[sectionId].sizeOfStruct;
paramDefaultLength = paramsMap[currItemIndex].stringLength;
// Interpret the Value
LOG_DBG("ConfigParser_ParseFile: Interpreting parameter %s\n", items[i]);
switch(paramsMap[currItemIndex].type) {
case TYPE_INT:
if(sscanf(items[i + 2], "%d", &intValue) != 1) {
printf("ConfigParser_ParseFile: Expected numerical value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(int *)(void *)param = intValue;
break;
case TYPE_UINT:
if(sscanf(items[i + 2], "%u", &uintValue) != 1) {
printf("ConfigParser_ParseFile: Expected numerical value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(unsigned int *)(void *)param = uintValue;
break;
case TYPE_UINT_HEX:
if(sscanf(items[i + 2], "%x", &uintValue) != 1) {
printf("ConfigParser_ParseFile: Expected unsigned char value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(unsigned int *)(void *)param = uintValue;
break;
case TYPE_CHAR_ARR:
if(items[i + 2] == NULL)
memset(param, 0, (pParamLength != NULL && *pParamLength != 0) ? *pParamLength : paramDefaultLength);
else {
strncpy(param, items[i + 2], paramsMap[currItemIndex].stringLength);
param[strlen(items[i + 2])] = '\0';
}
break;
case TYPE_DOUBLE:
if(sscanf(items[i + 2], "%lf", &doubleValue) != 1) {
printf("ConfigParser_ParseFile: Expected double value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(double *)(void *)param = doubleValue;
break;
case TYPE_FLOAT:
if(sscanf(items[i + 2], "%f", &floatValue) != 1) {
printf("ConfigParser_ParseFile: Expected double value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(float *)(void *)param = floatValue;
break;
case TYPE_UCHAR:
if(sscanf(items[i + 2], "%u", &charValue) != 1) {
printf("ConfigParser_ParseFile: Expected unsigned char value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(unsigned char *)(void *)param = charValue;
break;
case TYPE_USHORT:
if(sscanf(items[i + 2], "%hu", &ushortValue) != 1) {
printf("ConfigParser_ParseFile: Expected unsigned short value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(unsigned short *)(void *)param = ushortValue;
break;
case TYPE_SHORT:
if(sscanf(items[i + 2], "%hd", &shortValue) != 1) {
printf("ConfigParser_ParseFile: Expected short value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(short *)(void *)param = shortValue;
break;
case TYPE_UCHAR_ARR:
if(items[i + 2] == NULL)
memset(param, 0, (pParamLength != NULL && *pParamLength != 0) ? *pParamLength : paramDefaultLength);
else {
strncpy(param, items[i + 2], paramsMap[currItemIndex].stringLength);
param[strlen(items[i + 2])] = '\0';
}
break;
case TYPE_ULLONG:
if(sscanf(items[i + 2], "%llu", &ullValue) != 1) {
printf("ConfigParser_ParseFile: Expected numerical value for Parameter %s, found value '%s'\n", items[i], items[i + 2]);
}
*(unsigned long long *)(void *)param = ullValue;
break;
default:
printf("ConfigParser_ParseFile: Encountered unknown value type in the map\n");
switch (paramsMap[currItemIndex].type) {
case TYPE_INT:
if (sscanf(items[i + 2], "%d", &intValue) != 1) {
printf("ConfigParser_ParseFile: Expected numerical value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(int *)(void *)param = intValue;
break;
case TYPE_UINT:
if (sscanf(items[i + 2], "%u", &uintValue) != 1) {
printf("ConfigParser_ParseFile: Expected numerical value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(unsigned int *)(void *)param = uintValue;
break;
case TYPE_UINT_HEX:
if (sscanf(items[i + 2], "%x", &uintValue) != 1) {
printf("ConfigParser_ParseFile: Expected unsigned char value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(unsigned int *)(void *)param = uintValue;
break;
case TYPE_CHAR_ARR:
if (items[i + 2] == NULL)
memset(param, 0, (pParamLength != NULL && *pParamLength != 0) ? *pParamLength : paramDefaultLength);
else {
strncpy(param, items[i + 2], paramsMap[currItemIndex].stringLength);
param[strlen(items[i + 2])] = '\0';
}
break;
case TYPE_DOUBLE:
if (sscanf(items[i + 2], "%lf", &doubleValue) != 1) {
printf("ConfigParser_ParseFile: Expected double value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(double *)(void *)param = doubleValue;
break;
case TYPE_FLOAT:
if (sscanf(items[i + 2], "%f", &floatValue) != 1) {
printf("ConfigParser_ParseFile: Expected double value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(float *)(void *)param = floatValue;
break;
case TYPE_UCHAR:
if (sscanf(items[i + 2], "%u", &charValue) != 1) {
printf("ConfigParser_ParseFile: Expected unsigned char value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(unsigned char *)(void *)param = charValue;
break;
case TYPE_USHORT:
if (sscanf(items[i + 2], "%hu", &ushortValue) != 1) {
printf("ConfigParser_ParseFile: Expected unsigned short value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(unsigned short *)(void *)param = ushortValue;
break;
case TYPE_SHORT:
if (sscanf(items[i + 2], "%hd", &shortValue) != 1) {
printf("ConfigParser_ParseFile: Expected short value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(short *)(void *)param = shortValue;
break;
case TYPE_UCHAR_ARR:
if (items[i + 2] == NULL)
memset(param, 0, (pParamLength != NULL && *pParamLength != 0) ? *pParamLength : paramDefaultLength);
else {
strncpy(param, items[i + 2], paramsMap[currItemIndex].stringLength);
param[strlen(items[i + 2])] = '\0';
}
break;
case TYPE_ULLONG:
if (sscanf(items[i + 2], "%llu", &ullValue) != 1) {
printf("ConfigParser_ParseFile: Expected numerical value for Parameter %s, found value '%s'\n",
items[i],
items[i + 2]);
}
*(unsigned long long *)(void *)param = ullValue;
break;
default:
printf("ConfigParser_ParseFile: Encountered unknown value type in the map\n");
}
}
@@ -365,42 +404,42 @@ NvMediaStatus ConfigParser_InitParamsMap(ConfigParamsMap *paramsMap)
{
int i = 0;
while(paramsMap[i].paramName != NULL) {
while (paramsMap[i].paramName != NULL) {
if (paramsMap[i].mappedLocation == NULL) {
i++;
continue;
i++;
continue;
}
switch(paramsMap[i].type) {
case TYPE_UINT:
case TYPE_UINT_HEX:
*(unsigned int *)(paramsMap[i].mappedLocation) = (unsigned int)paramsMap[i].defaultValue;
break;
case TYPE_INT:
*(int *)(paramsMap[i].mappedLocation) = (int)paramsMap[i].defaultValue;
break;
case TYPE_DOUBLE:
*(double *)(paramsMap[i].mappedLocation) = (double)paramsMap[i].defaultValue;
break;
case TYPE_FLOAT:
*(float *)(paramsMap[i].mappedLocation) = (float)paramsMap[i].defaultValue;
break;
case TYPE_UCHAR:
*(unsigned char *)(paramsMap[i].mappedLocation) = (NvMediaBool)paramsMap[i].defaultValue;
break;
case TYPE_USHORT:
*(unsigned short *)(paramsMap[i].mappedLocation) = (unsigned short)paramsMap[i].defaultValue;
break;
case TYPE_SHORT:
*(short *)(paramsMap[i].mappedLocation) = (short)paramsMap[i].defaultValue;
break;
case TYPE_ULLONG:
*(unsigned long long *)(paramsMap[i].mappedLocation) = (unsigned long long)paramsMap[i].defaultValue;
break;
case TYPE_CHAR_ARR:
case TYPE_UCHAR_ARR:
default:
break;
switch (paramsMap[i].type) {
case TYPE_UINT:
case TYPE_UINT_HEX:
*(unsigned int *)(paramsMap[i].mappedLocation) = (unsigned int)paramsMap[i].defaultValue;
break;
case TYPE_INT:
*(int *)(paramsMap[i].mappedLocation) = (int)paramsMap[i].defaultValue;
break;
case TYPE_DOUBLE:
*(double *)(paramsMap[i].mappedLocation) = (double)paramsMap[i].defaultValue;
break;
case TYPE_FLOAT:
*(float *)(paramsMap[i].mappedLocation) = (float)paramsMap[i].defaultValue;
break;
case TYPE_UCHAR:
*(unsigned char *)(paramsMap[i].mappedLocation) = (NvMediaBool)paramsMap[i].defaultValue;
break;
case TYPE_USHORT:
*(unsigned short *)(paramsMap[i].mappedLocation) = (unsigned short)paramsMap[i].defaultValue;
break;
case TYPE_SHORT:
*(short *)(paramsMap[i].mappedLocation) = (short)paramsMap[i].defaultValue;
break;
case TYPE_ULLONG:
*(unsigned long long *)(paramsMap[i].mappedLocation) = (unsigned long long)paramsMap[i].defaultValue;
break;
case TYPE_CHAR_ARR:
case TYPE_UCHAR_ARR:
default:
break;
}
i++;
}
@@ -410,82 +449,88 @@ NvMediaStatus ConfigParser_InitParamsMap(ConfigParamsMap *paramsMap)
NvMediaStatus ConfigParser_ValidateParams(ConfigParamsMap *paramsMap, SectionMap *sectionsMap)
{
NvMediaStatus status = NVMEDIA_STATUS_OK;
unsigned int sectionId = 0, i = 0, j;
char *param;
NvMediaStatus status = NVMEDIA_STATUS_OK;
unsigned int sectionId = 0, i = 0, j;
char *param;
while(paramsMap[i].paramName != NULL) {
if(ConfigParser_GetSectionIndexByType(sectionsMap, paramsMap[i].sectionType, &sectionId) != NVMEDIA_STATUS_OK) {
printf("ConfigParser_ValidateParams: Section index couldn't be found in section map. Param Name: '%s'.\n", paramsMap[i].paramName);
while (paramsMap[i].paramName != NULL) {
if (ConfigParser_GetSectionIndexByType(sectionsMap, paramsMap[i].sectionType, &sectionId)
!= NVMEDIA_STATUS_OK) {
printf("ConfigParser_ValidateParams: Section index couldn't be found in section map. Param Name: '%s'.\n",
paramsMap[i].paramName);
}
for(j = 0; j <= sectionsMap[sectionId].lastSectionIndex; j++) {
if(paramsMap[i].paramLimits == 1 || paramsMap[i].paramLimits == 2) {
for (j = 0; j <= sectionsMap[sectionId].lastSectionIndex; j++) {
if (paramsMap[i].paramLimits == 1 || paramsMap[i].paramLimits == 2) {
param = (char *)paramsMap[i].mappedLocation + j * sectionsMap[sectionId].sizeOfStruct;
if (param == NULL) {
i++;
continue;
}
switch (paramsMap[i].type) {
case TYPE_UINT:
case TYPE_UINT_HEX:
if(*(unsigned int *)(void *)param < (unsigned int)paramsMap[i].minLimit ||
(paramsMap[i].paramLimits == 2 && *(unsigned int *)(void *)param > (unsigned int)paramsMap[i].maxLimit )) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_DOUBLE:
if(*(double *)(void *)param < (double)paramsMap[i].minLimit ||
(paramsMap[i].paramLimits == 2 && *(double *)(void *)param > (double)paramsMap[i].maxLimit )) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_FLOAT:
if(*(float *)(void *)param < (float)paramsMap[i].minLimit ||
(paramsMap[i].paramLimits == 2 && *(float *)(void *)param > (float)paramsMap[i].maxLimit )) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_INT:
if(*(int *)(void *)param < (int)paramsMap[i].minLimit ||
(paramsMap[i].paramLimits == 2 && *(int *)(void *)param > (int)paramsMap[i].maxLimit )) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_USHORT:
if(*(unsigned short *)(void *)param < (unsigned short)paramsMap[i].minLimit ||
(paramsMap[i].paramLimits == 2 && *(unsigned short *)(void *)param > (unsigned short)paramsMap[i].maxLimit )) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_SHORT:
if(*(short *)(void *)param < (short)paramsMap[i].minLimit ||
(paramsMap[i].paramLimits == 2 && *(short *)(void *)param > (short)paramsMap[i].maxLimit )) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_ULLONG:
if(*(unsigned long long *)(void *)param < (unsigned long long)paramsMap[i].minLimit ||
(paramsMap[i].paramLimits == 2 && *(unsigned long long *)(void *)param > (unsigned long long)paramsMap[i].maxLimit )) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
default:
break;
case TYPE_UINT:
case TYPE_UINT_HEX:
if (*(unsigned int *)(void *)param < (unsigned int)paramsMap[i].minLimit
|| (paramsMap[i].paramLimits == 2
&& *(unsigned int *)(void *)param > (unsigned int)paramsMap[i].maxLimit)) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_DOUBLE:
if (*(double *)(void *)param < (double)paramsMap[i].minLimit
|| (paramsMap[i].paramLimits == 2
&& *(double *)(void *)param > (double)paramsMap[i].maxLimit)) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_FLOAT:
if (*(float *)(void *)param < (float)paramsMap[i].minLimit
|| (paramsMap[i].paramLimits == 2 && *(float *)(void *)param > (float)paramsMap[i].maxLimit)) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_INT:
if (*(int *)(void *)param < (int)paramsMap[i].minLimit
|| (paramsMap[i].paramLimits == 2 && *(int *)(void *)param > (int)paramsMap[i].maxLimit)) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_USHORT:
if (*(unsigned short *)(void *)param < (unsigned short)paramsMap[i].minLimit
|| (paramsMap[i].paramLimits == 2
&& *(unsigned short *)(void *)param > (unsigned short)paramsMap[i].maxLimit)) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_SHORT:
if (*(short *)(void *)param < (short)paramsMap[i].minLimit
|| (paramsMap[i].paramLimits == 2 && *(short *)(void *)param > (short)paramsMap[i].maxLimit)) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
case TYPE_ULLONG:
if (*(unsigned long long *)(void *)param < (unsigned long long)paramsMap[i].minLimit
|| (paramsMap[i].paramLimits == 2
&& *(unsigned long long *)(void *)param > (unsigned long long)paramsMap[i].maxLimit)) {
printf("ConfigParser_ValidateParams: Error in input parameter %s\n", paramsMap[i].paramName);
printf("Check configuration file for parameter limits\n");
status = NVMEDIA_STATUS_BAD_PARAMETER;
}
break;
default:
break;
}
}
}
@@ -498,57 +543,70 @@ NvMediaStatus ConfigParser_ValidateParams(ConfigParamsMap *paramsMap, SectionMap
NvMediaStatus ConfigParser_DisplayParams(ConfigParamsMap *pParamsMap, SectionMap *pSectionsMap)
{
unsigned int i = 0, j, sectionId = 0;
char *param;
char *param;
while(pParamsMap[i].paramName != NULL) {
if(ConfigParser_GetSectionIndexByType(pSectionsMap, pParamsMap[i].sectionType, &sectionId) != NVMEDIA_STATUS_OK) {
printf("ConfigParser_DisplayParams: Section index couldn't be found in section map by type. Param Name: '%s'.\n", pParamsMap[i].paramName);
while (pParamsMap[i].paramName != NULL) {
if (ConfigParser_GetSectionIndexByType(pSectionsMap, pParamsMap[i].sectionType, &sectionId)
!= NVMEDIA_STATUS_OK) {
printf("ConfigParser_DisplayParams: Section index couldn't be found in section map by type. Param Name: "
"'%s'.\n",
pParamsMap[i].paramName);
}
for(j = 0; j <= pSectionsMap[sectionId].lastSectionIndex; j++) {
for (j = 0; j <= pSectionsMap[sectionId].lastSectionIndex; j++) {
param = (char *)pParamsMap[i].mappedLocation + j * pSectionsMap[sectionId].sizeOfStruct;
if (param == NULL) {
i++;
continue;
}
switch(pParamsMap[i].type) {
case TYPE_UINT:
printf("(%d) %s = %u\n", j, pParamsMap[i].paramName, *(unsigned int *)(void *)param);
break;
case TYPE_DOUBLE:
printf("(%d) %s = %.2lf\n", j, pParamsMap[i].paramName, *(double *)(void *)param);
break;
case TYPE_FLOAT:
printf("(%d) %s = %.2f\n", j, pParamsMap[i].paramName, *(float *)(void *)param);
break;
case TYPE_UCHAR:
printf("(%d) %s = %d\n", j, pParamsMap[i].paramName, *(unsigned char *)(void *)param);
break;
case TYPE_USHORT:
printf("(%d) %s = %hu\n", j, pParamsMap[i].paramName, *(unsigned short *)(void *)param);
break;
case TYPE_SHORT:
printf("(%d) %s = %hd\n", j, pParamsMap[i].paramName, *(short *)(void *)param);
break;
case TYPE_ULLONG:
printf("(%d) %s = %llu\n", j, pParamsMap[i].paramName, *(unsigned long long *)(void *)param);
break;
case TYPE_CHAR_ARR:
printf("(%d) %s = ""%s""\n", j, pParamsMap[i].paramName, param);
break;
case TYPE_UCHAR_ARR:
printf("(%d) %s = ""%s""\n", j, pParamsMap[i].paramName, (unsigned char *)(void *)param);
break;
case TYPE_INT:
printf("(%d) %s = %d\n", j, pParamsMap[i].paramName, *(int *)(void *)param);
break;
case TYPE_UINT_HEX:
printf("(%d) %s = %x\n", j, pParamsMap[i].paramName, *(unsigned int *)(void *)param);
break;
default:
// Do nothing
break;
switch (pParamsMap[i].type) {
case TYPE_UINT:
printf("(%d) %s = %u\n", j, pParamsMap[i].paramName, *(unsigned int *)(void *)param);
break;
case TYPE_DOUBLE:
printf("(%d) %s = %.2lf\n", j, pParamsMap[i].paramName, *(double *)(void *)param);
break;
case TYPE_FLOAT:
printf("(%d) %s = %.2f\n", j, pParamsMap[i].paramName, *(float *)(void *)param);
break;
case TYPE_UCHAR:
printf("(%d) %s = %d\n", j, pParamsMap[i].paramName, *(unsigned char *)(void *)param);
break;
case TYPE_USHORT:
printf("(%d) %s = %hu\n", j, pParamsMap[i].paramName, *(unsigned short *)(void *)param);
break;
case TYPE_SHORT:
printf("(%d) %s = %hd\n", j, pParamsMap[i].paramName, *(short *)(void *)param);
break;
case TYPE_ULLONG:
printf("(%d) %s = %llu\n", j, pParamsMap[i].paramName, *(unsigned long long *)(void *)param);
break;
case TYPE_CHAR_ARR:
printf("(%d) %s = "
"%s"
"\n",
j,
pParamsMap[i].paramName,
param);
break;
case TYPE_UCHAR_ARR:
printf("(%d) %s = "
"%s"
"\n",
j,
pParamsMap[i].paramName,
(unsigned char *)(void *)param);
break;
case TYPE_INT:
printf("(%d) %s = %d\n", j, pParamsMap[i].paramName, *(int *)(void *)param);
break;
case TYPE_UINT_HEX:
printf("(%d) %s = %x\n", j, pParamsMap[i].paramName, *(unsigned int *)(void *)param);
break;
default:
// Do nothing
break;
}
}
i++;

View File

@@ -29,7 +29,8 @@
#define _NVMEDIA_TEST_CONFIG_PARSER_H_
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include <ctype.h>
@@ -42,65 +43,65 @@ extern "C" {
#define MAX_ITEMS_TO_PARSE 10000
typedef enum _ParamType {
TYPE_UINT = 0,
TYPE_UINT_HEX,
TYPE_INT,
TYPE_DOUBLE,
TYPE_FLOAT,
TYPE_UCHAR,
TYPE_ULLONG,
TYPE_USHORT,
TYPE_CHAR_ARR,
TYPE_UCHAR_ARR,
TYPE_SHORT
} ParamType;
typedef enum _ParamType {
TYPE_UINT = 0,
TYPE_UINT_HEX,
TYPE_INT,
TYPE_DOUBLE,
TYPE_FLOAT,
TYPE_UCHAR,
TYPE_ULLONG,
TYPE_USHORT,
TYPE_CHAR_ARR,
TYPE_UCHAR_ARR,
TYPE_SHORT
} ParamType;
typedef enum {
LIMITS_NONE = 0,
LIMITS_MIN = 1,
LIMITS_BOTH = 2
} LimitsType;
typedef enum { LIMITS_NONE = 0, LIMITS_MIN = 1, LIMITS_BOTH = 2 } LimitsType;
typedef enum {
SECTION_NONE,
SECTION_CAPTURE,
SECTION_QP,
SECTION_RC,
SECTION_ENCODE_PIC,
SECTION_ENCODE_PIC_H264,
SECTION_ENCODE_PIC_H265,
SECTION_MVC,
SECTION_PAYLOAD,
SECTION_2DPROCESSOR
} SectionType;
typedef enum {
SECTION_NONE,
SECTION_CAPTURE,
SECTION_QP,
SECTION_RC,
SECTION_ENCODE_PIC,
SECTION_ENCODE_PIC_H264,
SECTION_ENCODE_PIC_H265,
SECTION_MVC,
SECTION_PAYLOAD,
SECTION_2DPROCESSOR
} SectionType;
typedef struct {
SectionType secType;
const char *name;
unsigned int lastSectionIndex;
size_t sizeOfStruct;
} SectionMap;
typedef struct
{
SectionType secType;
const char *name;
unsigned int lastSectionIndex;
size_t sizeOfStruct;
} SectionMap;
typedef struct {
const char *paramName;
void *mappedLocation;
ParamType type;
double defaultValue;
LimitsType paramLimits;
double minLimit;
double maxLimit;
unsigned int stringLength; // string param size
unsigned int *stringLengthAddr; // address of string param size
SectionType sectionType;
} ConfigParamsMap;
typedef struct
{
const char *paramName;
void *mappedLocation;
ParamType type;
double defaultValue;
LimitsType paramLimits;
double minLimit;
double maxLimit;
unsigned int stringLength; // string param size
unsigned int *stringLengthAddr; // address of string param size
SectionType sectionType;
} ConfigParamsMap;
NvMediaStatus ConfigParser_InitParamsMap(ConfigParamsMap *paramsMap);
NvMediaStatus ConfigParser_ParseFile(ConfigParamsMap *paramsMap, unsigned int numParams, SectionMap *sectionsMap, char *file);
NvMediaStatus ConfigParser_ValidateParams(ConfigParamsMap *paramsMap, SectionMap *sectionsMap);
NvMediaStatus ConfigParser_DisplayParams(ConfigParamsMap *paramsMap, SectionMap *sectionsMap);
NvMediaStatus ConfigParser_GetSectionIndexByName(SectionMap *sectionsMap, char *sectionName, unsigned int *index);
NvMediaStatus ConfigParser_GetSectionIndexByType(SectionMap *sectionsMap, SectionType sectionType, unsigned int *index);
NvMediaStatus ConfigParser_InitParamsMap(ConfigParamsMap *paramsMap);
NvMediaStatus
ConfigParser_ParseFile(ConfigParamsMap *paramsMap, unsigned int numParams, SectionMap *sectionsMap, char *file);
NvMediaStatus ConfigParser_ValidateParams(ConfigParamsMap *paramsMap, SectionMap *sectionsMap);
NvMediaStatus ConfigParser_DisplayParams(ConfigParamsMap *paramsMap, SectionMap *sectionsMap);
NvMediaStatus ConfigParser_GetSectionIndexByName(SectionMap *sectionsMap, char *sectionName, unsigned int *index);
NvMediaStatus
ConfigParser_GetSectionIndexByType(SectionMap *sectionsMap, SectionType sectionType, unsigned int *index);
#ifdef __cplusplus
}

View File

@@ -29,110 +29,96 @@
#define _NVMEDIA_TEST_IMAGE_UTILS_H_
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include "cmdline.h"
#include "misc_utils.h"
#include "nvmedia_core.h"
#include "nvmedia_surface.h"
#include "nvmedia_image.h"
#include "cmdline.h"
#include "nvmedia_surface.h"
#if (NV_IS_SAFETY == 1)
#include "nvmedia_image_internal.h"
#endif
#define PACK_RGBA(R, G, B, A) (((uint32_t)(A) << 24) | ((uint32_t)(B) << 16) | \
((uint32_t)(G) << 8) | (uint32_t)(R))
#define DEFAULT_ALPHA 0x80
#define PACK_RGBA(R, G, B, A) (((uint32_t)(A) << 24) | ((uint32_t)(B) << 16) | ((uint32_t)(G) << 8) | (uint32_t)(R))
#define DEFAULT_ALPHA 0x80
// ReadImage
//
// ReadImage() Read image from file
//
// Arguments:
//
// filename
// (in) Input file name
//
// frameNum
// (in) Frame number to read. Use for stream input files.
//
// width
// (in) Surface width
//
// height
// (in) Surface height
//
// image
// (out) Pointer to pre-allocated output surface
//
// uvOrderFlag
// (in) Flag for UV order. If true - UV; If false - VU;
//
// bytesPerPixel
// (in) Bytes per pixel. Nedded for RAW image types handling.
// RAW8 - 1 byte per pixel
// RAW10, RAW12, RAW14 - 2 bytes per pixel
//
// pixelAlignment
// (in) Alignment of bits in pixel.
// 0 - LSB Aligned
// 1 - MSB Aligned
NvMediaStatus ReadImage(char *fileName,
uint32_t frameNum,
uint32_t width,
uint32_t height,
NvMediaImage *image,
NvMediaBool uvOrderFlag,
uint32_t bytesPerPixel,
uint32_t pixelAlignment);
// ReadImage
//
// ReadImage() Read image from file
//
// Arguments:
//
// filename
// (in) Input file name
//
// frameNum
// (in) Frame number to read. Use for stream input files.
//
// width
// (in) Surface width
//
// height
// (in) Surface height
//
// image
// (out) Pointer to pre-allocated output surface
//
// uvOrderFlag
// (in) Flag for UV order. If true - UV; If false - VU;
//
// bytesPerPixel
// (in) Bytes per pixel. Nedded for RAW image types handling.
// RAW8 - 1 byte per pixel
// RAW10, RAW12, RAW14 - 2 bytes per pixel
//
// pixelAlignment
// (in) Alignment of bits in pixel.
// 0 - LSB Aligned
// 1 - MSB Aligned
// InitImage
//
// InitImage() Init image data to zeros
//
// Arguments:
//
// image
// (in) image to initialize
//
// width
// (in) Surface width
//
// height
// (in) Surface height
NvMediaStatus
ReadImage(
char *fileName,
uint32_t frameNum,
uint32_t width,
uint32_t height,
NvMediaImage *image,
NvMediaBool uvOrderFlag,
uint32_t bytesPerPixel,
uint32_t pixelAlignment);
NvMediaStatus InitImage(NvMediaImage *image, uint32_t width, uint32_t height);
// InitImage
//
// InitImage() Init image data to zeros
//
// Arguments:
//
// image
// (in) image to initialize
//
// width
// (in) Surface width
//
// height
// (in) Surface height
NvMediaStatus
AllocateBufferToWriteImage(Blit2DTest *ctx, NvMediaImage *image, NvMediaBool uvOrderFlag, NvMediaBool appendFlag);
NvMediaStatus
InitImage(
NvMediaImage *image,
uint32_t width,
uint32_t height);
NvMediaStatus
AllocateBufferToWriteImage(
Blit2DTest *ctx,
NvMediaImage *image,
NvMediaBool uvOrderFlag,
NvMediaBool appendFlag);
// WriteImageToBuffer
//
// WriteImageToBuffer() Save RGB or YUV image
//
NvMediaStatus
WriteImageToAllocatedBuffer(
Blit2DTest *ctx,
NvMediaImage *image,
NvMediaBool uvOrderFlag,
NvMediaBool appendFlag,
uint32_t bytesPerPixel);
// WriteImageToBuffer
//
// WriteImageToBuffer() Save RGB or YUV image
//
NvMediaStatus WriteImageToAllocatedBuffer(Blit2DTest *ctx,
NvMediaImage *image,
NvMediaBool uvOrderFlag,
NvMediaBool appendFlag,
uint32_t bytesPerPixel);
#ifdef __cplusplus
}

View File

@@ -29,7 +29,7 @@
#include <stdio.h>
#include <string.h>
#ifdef NVMEDIA_ANDROID
#define LOG_TAG "nvmedia_common"
#define LOG_TAG "nvmedia_common"
#define LOG_NDEBUG 1
#include <utils/Log.h>
#endif
@@ -48,99 +48,100 @@
static enum LogLevel msg_level = LEVEL_ERR;
static enum LogStyle msg_style = LOG_STYLE_NORMAL;
static FILE *msg_file = NULL;
static FILE *msg_file = NULL;
void SetLogLevel(enum LogLevel level)
{
if (level > LEVEL_DBG)
return;
if (level > LEVEL_DBG)
return;
msg_level = level;
msg_level = level;
}
void SetLogStyle(enum LogStyle style)
{
if (style > LOG_STYLE_FUNCTION_LINE)
return;
if (style > LOG_STYLE_FUNCTION_LINE)
return;
msg_style = style;
msg_style = style;
}
void SetLogFile(FILE *logFileHandle)
{
if(!logFileHandle)
if (!logFileHandle)
return;
msg_file = logFileHandle;
}
void LogLevelMessage(enum LogLevel level, const char *functionName,
int lineNumber, const char *format, ...)
void LogLevelMessage(enum LogLevel level, const char *functionName, int lineNumber, const char *format, ...)
{
va_list ap;
char str[LOG_BUFFER_BYTES] = {'\0',};
char str[LOG_BUFFER_BYTES] = {
'\0',
};
FILE *logFile = msg_file ? msg_file : stdout;
if (level > msg_level)
return;
#ifndef NVMEDIA_ANDROID
/** In the case of Android ADB log, if LOG_TAG is defined,
* before 'Log.h' is included in source file,
* LOG_TAG is automatically concatenated at the beginning of log message,
* so, we don't copy 'nvmedia: ' into 'str'.
*/
/** In the case of Android ADB log, if LOG_TAG is defined,
* before 'Log.h' is included in source file,
* LOG_TAG is automatically concatenated at the beginning of log message,
* so, we don't copy 'nvmedia: ' into 'str'.
*/
strcpy(str, "nvmedia: ");
/** As LOG_TAG is concatednated, log level is also automatically concatenated,
* by calling different ADB log function such as ALOGE(for eror log message),
* ALOGW(for warning log message).
*/
/** As LOG_TAG is concatednated, log level is also automatically concatenated,
* by calling different ADB log function such as ALOGE(for eror log message),
* ALOGW(for warning log message).
*/
switch (level) {
case LEVEL_ERR:
strcat(str, "ERROR: ");
break;
case LEVEL_WARN:
strcat(str, "WARNING: ");
break;
case LEVEL_INFO:
case LEVEL_DBG:
// Empty
break;
case LEVEL_ERR:
strcat(str, "ERROR: ");
break;
case LEVEL_WARN:
strcat(str, "WARNING: ");
break;
case LEVEL_INFO:
case LEVEL_DBG:
// Empty
break;
}
#endif
va_start(ap, format);
vsnprintf(str + strlen(str), sizeof(str) - strlen(str), format, ap);
if(msg_style == LOG_STYLE_NORMAL) {
if (msg_style == LOG_STYLE_NORMAL) {
// Add trailing new line char
if(strlen(str) && str[strlen(str) - 1] != '\n')
if (strlen(str) && str[strlen(str) - 1] != '\n')
strcat(str, "\n");
} else if(msg_style == LOG_STYLE_FUNCTION_LINE) {
}
else if (msg_style == LOG_STYLE_FUNCTION_LINE) {
// Remove trailing new line char
if(strlen(str) && str[strlen(str) - 1] == '\n')
if (strlen(str) && str[strlen(str) - 1] == '\n')
str[strlen(str) - 1] = 0;
// Add function and line info
snprintf(str + + strlen(str), sizeof(str) - strlen(str), " at %s():%d\n", functionName, lineNumber);
snprintf(str + +strlen(str), sizeof(str) - strlen(str), " at %s():%d\n", functionName, lineNumber);
}
#ifdef NVMEDIA_ANDROID
switch (msg_level) {
case LEVEL_ERR:
ALOGE("%s", str);
break;
case LEVEL_WARN:
ALOGW("%s", str);
break;
case LEVEL_INFO:
ALOGI("%s", str);
break;
case LEVEL_DBG:
ALOGD("%s", str);
break;
case LEVEL_ERR:
ALOGE("%s", str);
break;
case LEVEL_WARN:
ALOGW("%s", str);
break;
case LEVEL_INFO:
ALOGI("%s", str);
break;
case LEVEL_DBG:
ALOGD("%s", str);
break;
}
#else
fprintf(logFile, "%s", str);
@@ -151,4 +152,3 @@ void LogLevelMessage(enum LogLevel level, const char *functionName,
#endif
va_end(ap);
}

View File

@@ -29,90 +29,76 @@
#define _NVMEDIA_TEST_LOG_UTILS_H_
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include <stdarg.h>
#include <stdio.h>
enum LogLevel {
LEVEL_ERR = 0,
LEVEL_WARN = 1,
LEVEL_INFO = 2,
LEVEL_DBG = 3,
};
enum LogLevel {
LEVEL_ERR = 0,
LEVEL_WARN = 1,
LEVEL_INFO = 2,
LEVEL_DBG = 3,
};
enum LogStyle {
LOG_STYLE_NORMAL = 0,
LOG_STYLE_FUNCTION_LINE
};
enum LogStyle { LOG_STYLE_NORMAL = 0, LOG_STYLE_FUNCTION_LINE };
#define LINE_INFO __FUNCTION__, __LINE__
#define LOG_DBG(...) LogLevelMessage(LEVEL_DBG, LINE_INFO, __VA_ARGS__)
#define LOG_INFO(...) LogLevelMessage(LEVEL_INFO, LINE_INFO, __VA_ARGS__)
#define LOG_WARN(...) LogLevelMessage(LEVEL_WARN, LINE_INFO, __VA_ARGS__)
#define LINE_INFO __FUNCTION__, __LINE__
#define LOG_DBG(...) LogLevelMessage(LEVEL_DBG, LINE_INFO, __VA_ARGS__)
#define LOG_INFO(...) LogLevelMessage(LEVEL_INFO, LINE_INFO, __VA_ARGS__)
#define LOG_WARN(...) LogLevelMessage(LEVEL_WARN, LINE_INFO, __VA_ARGS__)
// SetLogLevel
//
// SetLogLevel() Set logging level
//
// Arguments:
//
// level
// (in) Logging level
// SetLogLevel
//
// SetLogLevel() Set logging level
//
// Arguments:
//
// level
// (in) Logging level
void
SetLogLevel(
enum LogLevel level);
void SetLogLevel(enum LogLevel level);
// SetLogStyle
//
// SetLogStyle() Set logging print slyle
//
// Arguments:
//
// level
// (in) Logging style
// SetLogStyle
//
// SetLogStyle() Set logging print slyle
//
// Arguments:
//
// level
// (in) Logging style
void
SetLogStyle(
enum LogStyle style);
void SetLogStyle(enum LogStyle style);
// SetLogFile
//
// SetLogFile() Set logging file handle
//
// Arguments:
//
// level
// (in) Logging file handle
// SetLogFile
//
// SetLogFile() Set logging file handle
//
// Arguments:
//
// level
// (in) Logging file handle
void
SetLogFile(
FILE *logFileHandle);
void SetLogFile(FILE *logFileHandle);
// LogLevelMessage
//
// LogLevelMessage() Print message if logging level is higher than message level
//
// Arguments:
//
// LogLevel
// (in) Message level
//
// format
// (in) Message format
//
// ...
// (in) Parameters list
// LogLevelMessage
//
// LogLevelMessage() Print message if logging level is higher than message level
//
// Arguments:
//
// LogLevel
// (in) Message level
//
// format
// (in) Message format
//
// ...
// (in) Parameters list
void
LogLevelMessage(
enum LogLevel level,
const char *functionName,
int lineNumber,
const char *format,
...);
void LogLevelMessage(enum LogLevel level, const char *functionName, int lineNumber, const char *format, ...);
#ifdef __cplusplus
}

View File

@@ -28,35 +28,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#if defined (__QNX__)
#include <unistd.h>
#if defined(__QNX__)
#include <sys/time.h>
#endif
#include "misc_utils.h"
uint32_t
u32(const uint8_t* ptr)
{
return ptr[0] | (ptr[1]<<8) | (ptr[2]<<16) | (ptr[3]<<24);
}
uint32_t u32(const uint8_t *ptr) { return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); }
NvMediaStatus
GetTimeMicroSec(
uint64_t *uTime)
NvMediaStatus GetTimeMicroSec(uint64_t *uTime)
{
struct timespec t;
#if !(defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 && _POSIX_TIMERS > 0)
struct timeval tv;
#endif
if(!uTime)
if (!uTime)
return NVMEDIA_STATUS_BAD_PARAMETER;
#if !(defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 && _POSIX_TIMERS > 0)
gettimeofday(&tv, NULL);
t.tv_sec = tv.tv_sec;
t.tv_nsec = tv.tv_usec*1000L;
t.tv_sec = tv.tv_sec;
t.tv_nsec = tv.tv_usec * 1000L;
#else
clock_gettime(CLOCK_MONOTONIC, &t);
#endif
@@ -64,4 +58,3 @@ GetTimeMicroSec(
*uTime = (uint64_t)t.tv_sec * 1000000LL + (uint64_t)t.tv_nsec / 1000LL;
return NVMEDIA_STATUS_OK;
}

View File

@@ -29,46 +29,42 @@
#define _NVMEDIA_TEST_MISC_UTILS_H_
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include "nvmedia_core.h"
#include "nvmedia_common.h"
#include "nvmedia_core.h"
#ifndef __INTEGRITY
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
typedef enum {
LSB_ALIGNED,
MSB_ALIGNED
} PixelAlignment;
typedef enum { LSB_ALIGNED, MSB_ALIGNED } PixelAlignment;
// u32
//
// u32() Reads 4 bytes from buffer and returns the read value
//
// Arguments:
//
// ptr
// (in) Input buffer
// u32
//
// u32() Reads 4 bytes from buffer and returns the read value
//
// Arguments:
//
// ptr
// (in) Input buffer
uint32_t u32(const uint8_t* ptr);
uint32_t u32(const uint8_t *ptr);
// GetTimeMicroSec
//
// GetTimeMicroSec() Returns current time in microseconds
//
// Arguments:
//
// uTime
// (out) Pointer to current time in microseconds
// GetTimeMicroSec
//
// GetTimeMicroSec() Returns current time in microseconds
//
// Arguments:
//
// uTime
// (out) Pointer to current time in microseconds
NvMediaStatus
GetTimeMicroSec(
uint64_t *uTime);
NvMediaStatus GetTimeMicroSec(uint64_t *uTime);
#ifdef __cplusplus
}

View File

@@ -25,133 +25,130 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "nvmedia_utils/cmdline.h"
#include "nvsci_setup.h"
#include <cuda.h>
#include <cuda_runtime.h>
#include "helper_cuda.h"
#include "nvsci_setup.h"
#include "nvmedia_2d_nvscisync.h"
#include "nvmedia_utils/cmdline.h"
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf( \
"NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, __LINE__, _status, NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define checkNvSciErrors(call) \
do { \
NvSciError _status = call; \
if (NvSciError_Success != _status) { \
printf("NVSCI call in file '%s' in line %i returned" \
" %d, expected %d\n", \
__FILE__, \
__LINE__, \
_status, \
NvSciError_Success); \
fflush(stdout); \
exit(EXIT_FAILURE); \
} \
} while (0)
void setupNvMediaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj,
int cudaDeviceId) {
NvSciSyncModule sciSyncModule;
checkNvSciErrors(NvSciSyncModuleOpen(&sciSyncModule));
NvSciSyncAttrList signalerAttrList, waiterAttrList;
NvSciSyncAttrList syncUnreconciledList[2];
NvSciSyncAttrList syncReconciledList, syncConflictList;
void setupNvMediaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj, int cudaDeviceId)
{
NvSciSyncModule sciSyncModule;
checkNvSciErrors(NvSciSyncModuleOpen(&sciSyncModule));
NvSciSyncAttrList signalerAttrList, waiterAttrList;
NvSciSyncAttrList syncUnreconciledList[2];
NvSciSyncAttrList syncReconciledList, syncConflictList;
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &signalerAttrList));
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &waiterAttrList));
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &signalerAttrList));
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &waiterAttrList));
NvMediaStatus status = NvMedia2DFillNvSciSyncAttrList(
ctx->i2d, signalerAttrList, NVMEDIA_SIGNALER);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DFillNvSciSyncAttrList failed\n", __func__);
exit(EXIT_FAILURE);
}
NvMediaStatus status = NvMedia2DFillNvSciSyncAttrList(ctx->i2d, signalerAttrList, NVMEDIA_SIGNALER);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DFillNvSciSyncAttrList failed\n", __func__);
exit(EXIT_FAILURE);
}
checkCudaErrors(cudaSetDevice(cudaDeviceId));
checkCudaErrors(cudaDeviceGetNvSciSyncAttributes(waiterAttrList, cudaDeviceId,
cudaNvSciSyncAttrWait));
checkCudaErrors(cudaSetDevice(cudaDeviceId));
checkCudaErrors(cudaDeviceGetNvSciSyncAttributes(waiterAttrList, cudaDeviceId, cudaNvSciSyncAttrWait));
syncUnreconciledList[0] = signalerAttrList;
syncUnreconciledList[1] = waiterAttrList;
checkNvSciErrors(NvSciSyncAttrListReconcile(
syncUnreconciledList, 2, &syncReconciledList, &syncConflictList));
checkNvSciErrors(NvSciSyncObjAlloc(syncReconciledList, &syncObj));
syncUnreconciledList[0] = signalerAttrList;
syncUnreconciledList[1] = waiterAttrList;
checkNvSciErrors(NvSciSyncAttrListReconcile(syncUnreconciledList, 2, &syncReconciledList, &syncConflictList));
checkNvSciErrors(NvSciSyncObjAlloc(syncReconciledList, &syncObj));
NvSciSyncAttrListFree(signalerAttrList);
NvSciSyncAttrListFree(waiterAttrList);
if (syncConflictList != nullptr) {
NvSciSyncAttrListFree(syncConflictList);
}
NvSciSyncAttrListFree(signalerAttrList);
NvSciSyncAttrListFree(waiterAttrList);
if (syncConflictList != nullptr) {
NvSciSyncAttrListFree(syncConflictList);
}
}
void setupCudaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj,
int cudaDeviceId) {
NvSciSyncModule sciSyncModule;
checkNvSciErrors(NvSciSyncModuleOpen(&sciSyncModule));
NvSciSyncAttrList signalerAttrList, waiterAttrList;
NvSciSyncAttrList syncUnreconciledList[2];
NvSciSyncAttrList syncReconciledList, syncConflictList;
void setupCudaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj, int cudaDeviceId)
{
NvSciSyncModule sciSyncModule;
checkNvSciErrors(NvSciSyncModuleOpen(&sciSyncModule));
NvSciSyncAttrList signalerAttrList, waiterAttrList;
NvSciSyncAttrList syncUnreconciledList[2];
NvSciSyncAttrList syncReconciledList, syncConflictList;
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &signalerAttrList));
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &waiterAttrList));
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &signalerAttrList));
checkNvSciErrors(NvSciSyncAttrListCreate(sciSyncModule, &waiterAttrList));
NvMediaStatus status =
NvMedia2DFillNvSciSyncAttrList(ctx->i2d, waiterAttrList, NVMEDIA_WAITER);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DFillNvSciSyncAttrList failed\n", __func__);
exit(EXIT_FAILURE);
}
NvMediaStatus status = NvMedia2DFillNvSciSyncAttrList(ctx->i2d, waiterAttrList, NVMEDIA_WAITER);
if (status != NVMEDIA_STATUS_OK) {
printf("%s: NvMedia2DFillNvSciSyncAttrList failed\n", __func__);
exit(EXIT_FAILURE);
}
checkCudaErrors(cudaSetDevice(cudaDeviceId));
checkCudaErrors(cudaDeviceGetNvSciSyncAttributes(
signalerAttrList, cudaDeviceId, cudaNvSciSyncAttrSignal));
checkCudaErrors(cudaSetDevice(cudaDeviceId));
checkCudaErrors(cudaDeviceGetNvSciSyncAttributes(signalerAttrList, cudaDeviceId, cudaNvSciSyncAttrSignal));
syncUnreconciledList[0] = signalerAttrList;
syncUnreconciledList[1] = waiterAttrList;
checkNvSciErrors(NvSciSyncAttrListReconcile(
syncUnreconciledList, 2, &syncReconciledList, &syncConflictList));
checkNvSciErrors(NvSciSyncObjAlloc(syncReconciledList, &syncObj));
syncUnreconciledList[0] = signalerAttrList;
syncUnreconciledList[1] = waiterAttrList;
checkNvSciErrors(NvSciSyncAttrListReconcile(syncUnreconciledList, 2, &syncReconciledList, &syncConflictList));
checkNvSciErrors(NvSciSyncObjAlloc(syncReconciledList, &syncObj));
NvSciSyncAttrListFree(signalerAttrList);
NvSciSyncAttrListFree(waiterAttrList);
if (syncConflictList != nullptr) {
NvSciSyncAttrListFree(syncConflictList);
}
NvSciSyncAttrListFree(signalerAttrList);
NvSciSyncAttrListFree(waiterAttrList);
if (syncConflictList != nullptr) {
NvSciSyncAttrListFree(syncConflictList);
}
}
void setupNvSciBuf(NvSciBufObj &bufobj, NvSciBufAttrList &nvmediaAttrlist,
int cudaDeviceId) {
CUuuid devUUID;
NvSciBufAttrList conflictlist;
NvSciBufAttrList bufUnreconciledAttrlist[1];
void setupNvSciBuf(NvSciBufObj &bufobj, NvSciBufAttrList &nvmediaAttrlist, int cudaDeviceId)
{
CUuuid devUUID;
NvSciBufAttrList conflictlist;
NvSciBufAttrList bufUnreconciledAttrlist[1];
CUresult res = cuDeviceGetUuid(&devUUID, cudaDeviceId);
if (res != CUDA_SUCCESS) {
fprintf(stderr, "Driver API error = %04d \n", res);
exit(EXIT_FAILURE);
}
CUresult res = cuDeviceGetUuid(&devUUID, cudaDeviceId);
if (res != CUDA_SUCCESS) {
fprintf(stderr, "Driver API error = %04d \n", res);
exit(EXIT_FAILURE);
}
NvSciBufAttrKeyValuePair attr_gpuid[] = {NvSciBufGeneralAttrKey_GpuId,
&devUUID, sizeof(devUUID)};
NvSciBufAttrKeyValuePair attr_gpuid[] = {NvSciBufGeneralAttrKey_GpuId, &devUUID, sizeof(devUUID)};
// set CUDA GPU ID to attribute list
checkNvSciErrors(NvSciBufAttrListSetAttrs(
nvmediaAttrlist, attr_gpuid,
sizeof(attr_gpuid) / sizeof(NvSciBufAttrKeyValuePair)));
// set CUDA GPU ID to attribute list
checkNvSciErrors(
NvSciBufAttrListSetAttrs(nvmediaAttrlist, attr_gpuid, sizeof(attr_gpuid) / sizeof(NvSciBufAttrKeyValuePair)));
bufUnreconciledAttrlist[0] = nvmediaAttrlist;
bufUnreconciledAttrlist[0] = nvmediaAttrlist;
checkNvSciErrors(NvSciBufAttrListReconcileAndObjAlloc(
bufUnreconciledAttrlist, 1, &bufobj, &conflictlist));
if (conflictlist != NULL) {
NvSciBufAttrListFree(conflictlist);
}
checkNvSciErrors(NvSciBufAttrListReconcileAndObjAlloc(bufUnreconciledAttrlist, 1, &bufobj, &conflictlist));
if (conflictlist != NULL) {
NvSciBufAttrListFree(conflictlist);
}
}
void cleanupNvSciBuf(NvSciBufObj &Bufobj) {
if (Bufobj != NULL) {
NvSciBufObjFree(Bufobj);
}
void cleanupNvSciBuf(NvSciBufObj &Bufobj)
{
if (Bufobj != NULL) {
NvSciBufObjFree(Bufobj);
}
}
void cleanupNvSciSync(NvSciSyncObj &syncObj) {
if (NvSciSyncObjFree != NULL) {
NvSciSyncObjFree(syncObj);
}
void cleanupNvSciSync(NvSciSyncObj &syncObj)
{
if (NvSciSyncObjFree != NULL) {
NvSciSyncObjFree(syncObj);
}
}

View File

@@ -27,16 +27,14 @@
#ifndef __NVSCI_SETUP_H__
#define __NVSCI_SETUP_H__
#include "nvmedia_utils/cmdline.h"
#include <nvscibuf.h>
#include <nvscisync.h>
void setupNvMediaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj,
int cudaDeviceId);
void setupCudaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj,
int cudaDeviceId);
void setupNvSciBuf(NvSciBufObj &bufobj, NvSciBufAttrList &nvmediaAttrlist,
int cudaDeviceId);
#include "nvmedia_utils/cmdline.h"
void setupNvMediaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj, int cudaDeviceId);
void setupCudaSignalerNvSciSync(Blit2DTest *ctx, NvSciSyncObj &syncObj, int cudaDeviceId);
void setupNvSciBuf(NvSciBufObj &bufobj, NvSciBufAttrList &nvmediaAttrlist, int cudaDeviceId);
void cleanupNvSciBuf(NvSciBufObj &Bufobj);
void cleanupNvSciSync(NvSciSyncObj &syncObj);
#endif
#endif

View File

@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -28,21 +28,20 @@
#ifndef DEFINES_H
#define DEFINES_H
#define DIM 512 // Square size of solver domain
#define DS (DIM * DIM) // Total domain size
#define CPADW (DIM / 2 + 1) // Padded width for real->complex in-place FFT
#define RPADW \
(2 * (DIM / 2 + 1)) // Padded width for real->complex in-place FFT
#define PDS (DIM * CPADW) // Padded total domain size
#define DIM 512 // Square size of solver domain
#define DS (DIM * DIM) // Total domain size
#define CPADW (DIM / 2 + 1) // Padded width for real->complex in-place FFT
#define RPADW (2 * (DIM / 2 + 1)) // Padded width for real->complex in-place FFT
#define PDS (DIM * CPADW) // Padded total domain size
#define DT 0.09f // Delta T for interative solver
#define VIS 0.0025f // Viscosity constant
#define FORCE (5.8f * DIM) // Force scale factor
#define FR 4 // Force update radius
#define DT 0.09f // Delta T for interative solver
#define VIS 0.0025f // Viscosity constant
#define FORCE (5.8f * DIM) // Force scale factor
#define FR 4 // Force update radius
#define TILEX 64 // Tile width
#define TILEY 64 // Tile height
#define TIDSX 64 // Tids in X
#define TIDSY 4 // Tids in Y
#define TILEX 64 // Tile width
#define TILEY 64 // Tile height
#define TIDSX 64 // Tids in X
#define TIDSY 4 // Tids in Y
#endif

View File

@@ -10,22 +10,20 @@
*/
// Includes
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void error_exit(const char* format, ... )
void error_exit(const char *format, ...)
{
va_list args;
va_start( args, format );
vfprintf( stderr, format, args );
va_end( args );
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
@@ -33,19 +31,19 @@ void error_exit(const char* format, ... )
#include "graphics_interface.h"
// CUDA standard includes
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>
#include <cuda_runtime.h>
// CUDA FFT Libraries
#include <cufft.h>
// CUDA helper functions
#include "helper_functions.h"
#include <rendercheck_gles.h>
#include <helper_cuda.h>
#include <rendercheck_gles.h>
#include "defines.h"
#include "fluidsGLES_kernels.h"
#include "helper_functions.h"
typedef float matrix4[4][4];
typedef float vector3[3];
@@ -65,20 +63,20 @@ void cleanup(void);
void reshape(int x, int y);
// CUFFT plan handle
cufftHandle planr2c;
cufftHandle planc2r;
cufftHandle planr2c;
cufftHandle planc2r;
static cData *vxfield = NULL;
static cData *vyfield = NULL;
cData *hvfield = NULL;
cData *dvfield = NULL;
cData *hvfield = NULL;
cData *dvfield = NULL;
static int wWidth = MAX(512, DIM);
static int wHeight = MAX(512, DIM);
static int clicked = 0;
static int fpsCount = 0;
static int fpsLimit = 1;
StopWatchInterface *timer = NULL;
static int clicked = 0;
static int fpsCount = 0;
static int fpsLimit = 1;
StopWatchInterface *timer = NULL;
int gui_mode; // For X window
// Rotate & translate variable temp., will remove and use shaders.
@@ -87,19 +85,19 @@ float translate_z = -3.0;
// Particle data
GLuint vbo = 0,vao = 0; // OpenGLES vertex buffer object
GLuint m_texture = 0;
GLuint vbo = 0, vao = 0; // OpenGLES vertex buffer object
GLuint m_texture = 0;
struct cudaGraphicsResource *cuda_vbo_resource; // handles OpenGLES-CUDA exchange
static cData *particles = NULL; // particle positions in host memory
static int lastx = 0, lasty = 0;
static cData *particles = NULL; // particle positions in host memory
static int lastx = 0, lasty = 0;
// Texture pitch
size_t tPitch = 0; // Now this is compatible with gcc in 64-bit
char *ref_file = NULL;
bool g_bQAAddTestForce = true;
int g_iFrameToCompare = 100;
int g_TotalErrors = 0;
char *ref_file = NULL;
bool g_bQAAddTestForce = true;
int g_iFrameToCompare = 100;
int g_TotalErrors = 0;
bool g_bExitESC = false;
@@ -107,7 +105,7 @@ const unsigned int window_width = 512;
const unsigned int window_height = 512;
// CheckFBO/BackBuffer class objects
CheckRender *g_CheckRender = NULL;
CheckRender *g_CheckRender = NULL;
void autoTest(char **);
void displayFrame();
@@ -132,8 +130,8 @@ GLuint mesh_shader = 0;
void mat_identity(matrix4 m)
{
m[0][1] = m[0][2] = m[0][3] = m[1][0] = m[1][2] = m[1][3] = m[2][0] =
m[2][1] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
m[0][1] = m[0][2] = m[0][3] = m[1][0] = m[1][2] = m[1][3] = m[2][0] = m[2][1] = m[2][3] = m[3][0] = m[3][1] =
m[3][2] = 0.0f;
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
}
@@ -141,18 +139,14 @@ void mat_identity(matrix4 m)
void mat_multiply(matrix4 m0, matrix4 m1)
{
float m[4];
for(int r = 0; r < 4; r++)
{
for (int r = 0; r < 4; r++) {
m[0] = m[1] = m[2] = m[3] = 0.0f;
for(int c = 0; c < 4; c++)
{
for(int i = 0; i < 4; i++)
{
for (int c = 0; c < 4; c++) {
for (int i = 0; i < 4; i++) {
m[c] += m0[i][r] * m1[c][i];
}
}
for(int c = 0; c < 4; c++)
{
for (int c = 0; c < 4; c++) {
m0[c][r] = m[c];
}
}
@@ -163,52 +157,52 @@ void mat4f_Ortho(float left, float right, float bottom, float top, float near, f
float r_l = right - left;
float t_b = top - bottom;
float f_n = far - near;
float tx = - (right + left) / (right - left);
float ty = - (top + bottom) / (top - bottom);
float tz = - (far + near) / (far - near);
float tx = -(right + left) / (right - left);
float ty = -(top + bottom) / (top - bottom);
float tz = -(far + near) / (far - near);
matrix4 m2;
m2[0][0] = 2.0f/ r_l;
m2[0][0] = 2.0f / r_l;
m2[0][1] = 0.0f;
m2[0][2] = 0.0f;
m2[0][3] = 0.0f;
m2[1][0] = 0.0f;
m2[1][0] = 0.0f;
m2[1][1] = 2.0f / t_b;
m2[1][2] = 0.0f;
m2[1][3] = 0.0f;
m2[2][0] = 0.0f;
m2[2][1] = 0.0f;
m2[2][1] = 0.0f;
m2[2][2] = -2.0f / f_n;
m2[2][3] = 0.0f;
m2[3][0] = tx;
m2[3][1] = ty;
m2[3][1] = ty;
m2[3][2] = tz;
m2[3][3] = 1.0f;
mat_multiply(m, m2);
mat_multiply(m, m2);
}
void readAndCompileShaderFromGLSLFile(GLuint new_shaderprogram, const char *filename, GLenum shaderType)
{
FILE *file = fopen(filename,"rb"); // open shader text file
if (!file)
FILE *file = fopen(filename, "rb"); // open shader text file
if (!file)
error_exit("Filename %s does not exist\n", filename);
/* get the size of the file and read it */
fseek(file,0,SEEK_END);
fseek(file, 0, SEEK_END);
GLint size = ftell(file);
char *data = (char*)malloc(sizeof(char)*(size + 1));
memset(data, 0, sizeof(char)*(size + 1));
fseek(file,0,SEEK_SET);
size_t res = fread(data,1,size,file);
char *data = (char *)malloc(sizeof(char) * (size + 1));
memset(data, 0, sizeof(char) * (size + 1));
fseek(file, 0, SEEK_SET);
size_t res = fread(data, 1, size, file);
fclose(file);
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const GLchar**)&data, &size);
glShaderSource(shader, 1, (const GLchar **)&data, &size);
glCompileShader(shader);
GET_GLERROR(0);
@@ -216,19 +210,18 @@ void readAndCompileShaderFromGLSLFile(GLuint new_shaderprogram, const char *file
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_success);
GET_GLERROR(0);
if (compile_success == GL_FALSE)
{
if (compile_success == GL_FALSE) {
printf("Compilation of %s failed!\n Reason:\n", filename);
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
char errorLog[maxLength];
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
printf("%s", errorLog);
glDeleteShader(shader);
glDeleteShader(shader);
exit(1);
}
@@ -259,8 +252,7 @@ GLuint ShaderCreate(const char *vshader_filename, const char *fshader_filename)
GLint link_success;
glGetProgramiv(new_shaderprogram, GL_LINK_STATUS, &link_success);
if (link_success == GL_FALSE)
{
if (link_success == GL_FALSE) {
printf("Linking of %s with %s failed!\n Reason:\n", vshader_filename, fshader_filename);
GLint maxLength = 0;
@@ -282,17 +274,16 @@ void motion(int x, int y)
// Convert motion coordinates to domain
float fx = (lastx / (float)wWidth);
float fy = (lasty / (float)wHeight);
int nx = (int)(fx * DIM);
int ny = (int)(fy * DIM);
int nx = (int)(fx * DIM);
int ny = (int)(fy * DIM);
if (clicked && nx < DIM-FR && nx > FR-1 && ny < DIM-FR && ny > FR-1)
{
if (clicked && nx < DIM - FR && nx > FR - 1 && ny < DIM - FR && ny > FR - 1) {
int ddx = x - lastx;
int ddy = y - lasty;
fx = ddx / (float)wWidth;
fy = ddy / (float)wHeight;
int spy = ny-FR;
int spx = nx-FR;
fx = ddx / (float)wWidth;
fy = ddy / (float)wHeight;
int spy = ny - FR;
int spx = nx - FR;
addForces(dvfield, DIM, DIM, spx, spy, FORCE * DT * fx, FORCE * DT * fy, FR);
lastx = x;
lasty = y;
@@ -302,12 +293,12 @@ void motion(int x, int y)
//===========================================================================
// InitGraphicsState() - initialize OpenGLES
//===========================================================================
static void InitGraphicsState(int argc, char** argv)
static void InitGraphicsState(int argc, char **argv)
{
char *GL_version = (char *)glGetString(GL_VERSION);
char *GL_vendor = (char *)glGetString(GL_VENDOR);
char *GL_renderer = (char *)glGetString(GL_RENDERER);
printf("Version: %s\n", GL_version);
printf("Vendor: %s\n", GL_vendor);
printf("Renderer: %s\n", GL_renderer);
@@ -316,26 +307,24 @@ static void InitGraphicsState(int argc, char** argv)
GLint bsize;
// initialize buffer object
glGenBuffers(1, &vbo);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(cData) * DS, particles, GL_DYNAMIC_DRAW);
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bsize);
if (bsize != (sizeof(cData) * DS))
{
if (bsize != (sizeof(cData) * DS)) {
printf("Failed to initialize GL extensions.\n");
exit(EXIT_FAILURE);
}
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, vbo, cudaGraphicsMapFlagsNone));
// GLSL stuff
char *vertex_shader_path = sdkFindFilePath("mesh.vert.glsl", argv[0]);
char *vertex_shader_path = sdkFindFilePath("mesh.vert.glsl", argv[0]);
char *fragment_shader_path = sdkFindFilePath("mesh.frag.glsl", argv[0]);
if (vertex_shader_path == NULL || fragment_shader_path == NULL)
{
if (vertex_shader_path == NULL || fragment_shader_path == NULL) {
printf("Error finding shader file\n");
exit(EXIT_FAILURE);
}
@@ -345,19 +334,18 @@ static void InitGraphicsState(int argc, char** argv)
free(vertex_shader_path);
free(fragment_shader_path);
glUseProgram(mesh_shader);
}
void displayFrame(void)
{
if (!ref_file)
{
if (!ref_file) {
sdkStartTimer(&timer);
simulateFluids();
}
GLint view_arr[4];
GLint view_arr[4];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -366,20 +354,20 @@ void displayFrame(void)
glDepthMask(GL_FALSE);
glUseProgram(mesh_shader);
// Set modelview and projection matricies
GLint h_ModelViewMatrix = glGetUniformLocation(mesh_shader, "modelview");
GLint h_ProjectionMatrix = glGetUniformLocation(mesh_shader, "projection");
GLint h_ModelViewMatrix = glGetUniformLocation(mesh_shader, "modelview");
GLint h_ProjectionMatrix = glGetUniformLocation(mesh_shader, "projection");
matrix4 modelview;
matrix4 projection;
mat_identity(modelview);
mat_identity(projection);
// (float left, float right, float bottom, float top, float near, float far, matrix4 m)
// (float left, float right, float bottom, float top, float near, float far, matrix4 m)
mat4f_Ortho(0.0, 1.0, 1.0, 0.0, 0.0, 1.0, projection);
glUniformMatrix4fv(h_ModelViewMatrix, 1, GL_FALSE, (GLfloat*)modelview);
glUniformMatrix4fv(h_ProjectionMatrix, 1, GL_FALSE, (GLfloat*)projection);
glUniformMatrix4fv(h_ModelViewMatrix, 1, GL_FALSE, (GLfloat *)modelview);
glUniformMatrix4fv(h_ProjectionMatrix, 1, GL_FALSE, (GLfloat *)projection);
// Set position coords
GLint h_position = glGetAttribLocation(mesh_shader, "a_position");
@@ -388,7 +376,7 @@ void displayFrame(void)
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glDrawArrays(GL_POINTS, 0, DS*sizeof(cData));
glDrawArrays(GL_POINTS, 0, DS * sizeof(cData));
glDisableVertexAttribArray(h_position);
glDisable(GL_DEPTH_TEST);
@@ -396,8 +384,7 @@ void displayFrame(void)
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
if (ref_file)
{
if (ref_file) {
return;
}
@@ -408,9 +395,8 @@ void displayFrame(void)
fpsCount++;
if (fpsCount == fpsLimit)
{
char fps[256];
if (fpsCount == fpsLimit) {
char fps[256];
float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
sprintf(fps, "Cuda/GL Stable Fluids (%d x %d): %3.1f fps", DIM, DIM, ifps);
graphics_set_windowtitle(fps);
@@ -423,7 +409,7 @@ void displayFrame(void)
void autoTest(char **argv)
{
CFrameBufferObject *fbo = new CFrameBufferObject(wWidth, wHeight, 4, false, GL_TEXTURE_2D);
g_CheckRender = new CheckFBO(wWidth, wHeight, 4, fbo);
g_CheckRender = new CheckFBO(wWidth, wHeight, 4, fbo);
g_CheckRender->setPixelFormat(GL_RGBA);
g_CheckRender->setExecPath(argv[0]);
@@ -431,26 +417,24 @@ void autoTest(char **argv)
fbo->bindRenderPath();
for (int count=0; count<g_iFrameToCompare; count++)
{
for (int count = 0; count < g_iFrameToCompare; count++) {
simulateFluids();
// add in a little force so the automated testing is interesing.
if (ref_file)
{
int x = wWidth/(count+1);
int y = wHeight/(count+1);
if (ref_file) {
int x = wWidth / (count + 1);
int y = wHeight / (count + 1);
float fx = (x / (float)wWidth);
float fy = (y / (float)wHeight);
int nx = (int)(fx * DIM);
int ny = (int)(fy * DIM);
int nx = (int)(fx * DIM);
int ny = (int)(fy * DIM);
int ddx = 35;
int ddy = 35;
fx = ddx / (float)wWidth;
fy = ddy / (float)wHeight;
int spy = ny-FR;
int spx = nx-FR;
fx = ddx / (float)wWidth;
fy = ddy / (float)wHeight;
int spy = ny - FR;
int spx = nx - FR;
addForces(dvfield, DIM, DIM, spx, spy, FORCE * DT * fx, FORCE * DT * fy, FR);
@@ -469,8 +453,7 @@ void autoTest(char **argv)
g_CheckRender->readback(wWidth, wHeight);
g_CheckRender->savePPM("fluidsGLES.ppm", true, NULL);
if (!g_CheckRender->PPMvsPPM("fluidsGLES.ppm", ref_file, MAX_EPSILON_ERROR, 0.25f))
{
if (!g_CheckRender->PPMvsPPM("fluidsGLES.ppm", ref_file, MAX_EPSILON_ERROR, 0.25f)) {
g_TotalErrors++;
}
}
@@ -482,18 +465,16 @@ bool runFluidsSimulation(int argc, char **argv, char *ref_file)
sdkCreateTimer(&timer);
if (ref_file != NULL)
{
// command line mode only - auto test
graphics_setup_window(0,0, wWidth, wHeight, sSDKname);
if (ref_file != NULL) {
// command line mode only - auto test
graphics_setup_window(0, 0, wWidth, wHeight, sSDKname);
InitGraphicsState(argc, argv); // set up GLES stuff
autoTest(argv);
cleanup();
}
else
{
else {
// create X11 window and set up associated OpenGL ES context
graphics_setup_window(0,0, wWidth, wHeight, sSDKname);
graphics_setup_window(0, 0, wWidth, wHeight, sSDKname);
InitGraphicsState(argc, argv); // set up GLES stuff
@@ -501,60 +482,50 @@ bool runFluidsSimulation(int argc, char **argv, char *ref_file)
graphics_swap_buffers();
XEvent event;
KeySym key;
char text[255];
char text[255];
while (1)
{
while (XPending(display) > 0)
{
while (1) {
while (XPending(display) > 0) {
XNextEvent(display, &event);
if (event.type==Expose && event.xexpose.count==0)
{
if (event.type == Expose && event.xexpose.count == 0) {
printf("Redraw requested!\n");
}
if (event.type==KeyPress && XLookupString(&event.xkey,text,255,&key,0)==1)
{
if (text[0] == 27 || text[0] == 'q' || text[0] == 'Q')
{
keyboard(text[0], 0, 0, argc, argv);
return true;
}
if (text[0] == 114)
{
keyboard(text[0], 0, 0, argc, argv);
}
printf("You pressed the %c key!\n",text[0]);
}
if (event.type==ButtonPress)
{
lastx = event.xbutton.x;
lasty = event.xbutton.y;
if (event.type == KeyPress && XLookupString(&event.xkey, text, 255, &key, 0) == 1) {
if (text[0] == 27 || text[0] == 'q' || text[0] == 'Q') {
keyboard(text[0], 0, 0, argc, argv);
return true;
}
if (text[0] == 114) {
keyboard(text[0], 0, 0, argc, argv);
}
printf("You pressed the %c key!\n", text[0]);
}
if (event.type == ButtonPress) {
lastx = event.xbutton.x;
lasty = event.xbutton.y;
clicked = !clicked;
}
if (event.type==ButtonRelease)
{
lastx = event.xbutton.x;
lasty = event.xbutton.y;
if (event.type == ButtonRelease) {
lastx = event.xbutton.x;
lasty = event.xbutton.y;
clicked = !clicked;
}
if (event.type == MotionNotify)
{
motion(event.xmotion.x, event.xmotion.y);
if (event.type == MotionNotify) {
motion(event.xmotion.x, event.xmotion.y);
}
else
{
else {
XFlush(display);
}
}
displayFrame();
usleep(1000); // need not take full CPU and GPU
usleep(1000); // need not take full CPU and GPU
}
}
@@ -567,70 +538,65 @@ bool runFluidsSimulation(int argc, char **argv, char *ref_file)
float myrand(void)
{
static int seed = 72191;
char sq[22];
char sq[22];
if (ref_file)
{
if (ref_file) {
seed *= seed;
sprintf(sq, "%010d", seed);
// pull the middle 5 digits out of sq
sq[8] = 0;
seed = atoi(&sq[3]);
seed = atoi(&sq[3]);
return seed/99999.f;
return seed / 99999.f;
}
else
{
return rand()/(float)RAND_MAX;
else {
return rand() / (float)RAND_MAX;
}
}
void initParticles(cData *p, int dx, int dy)
{
int i, j;
for (i = 0; i < dy; i++)
{
for (j = 0; j < dx; j++)
{
p[i*dx+j].x = (j+0.5f+(myrand() - 0.5f))/dx;
p[i*dx+j].y = (i+0.5f+(myrand() - 0.5f))/dy;
for (i = 0; i < dy; i++) {
for (j = 0; j < dx; j++) {
p[i * dx + j].x = (j + 0.5f + (myrand() - 0.5f)) / dx;
p[i * dx + j].y = (i + 0.5f + (myrand() - 0.5f)) / dy;
}
}
}
void keyboard(unsigned char key, int x, int y, int argc, char **argv)
{
switch (key)
{
case 'q':
case 'Q':
case 27:
g_bExitESC = true;
cleanup();
graphics_close_window(); // close window and destroy OpenGL ES context
return;
break;
case 'r':
printf("\nResetting\n");
memset(hvfield, 0, sizeof(cData) * DS);
cudaMemcpy(dvfield, hvfield, sizeof(cData) * DS, cudaMemcpyHostToDevice);
switch (key) {
case 'q':
case 'Q':
case 27:
g_bExitESC = true;
cleanup();
graphics_close_window(); // close window and destroy OpenGL ES context
return;
break;
case 'r':
printf("\nResetting\n");
memset(hvfield, 0, sizeof(cData) * DS);
cudaMemcpy(dvfield, hvfield, sizeof(cData) * DS, cudaMemcpyHostToDevice);
initParticles(particles, DIM, DIM);
initParticles(particles, DIM, DIM);
checkCudaErrors(cudaGraphicsUnregisterResource(cuda_vbo_resource));
checkCudaErrors(cudaGraphicsUnregisterResource(cuda_vbo_resource));
getLastCudaError("cudaGraphicsUnregisterBuffer failed");
getLastCudaError("cudaGraphicsUnregisterBuffer failed");
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
InitGraphicsState(argc, argv); // set up GLES stuff
graphics_swap_buffers();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &vbo);
InitGraphicsState(argc, argv); // set up GLES stuff
graphics_swap_buffers();
getLastCudaError("cudaGraphicsGLRegisterBuffer failed");
break;
getLastCudaError("cudaGraphicsGLRegisterBuffer failed");
break;
default:
break;
default:
break;
}
}
@@ -657,18 +623,19 @@ void cleanup(void)
int main(int argc, char **argv)
{
int devID;
int devID;
cudaDeviceProp deviceProps;
#if defined(__linux__)
setenv ("DISPLAY", ":0", 0);
setenv("DISPLAY", ":0", 0);
#endif
printf("%s Starting...\n\n", sSDKname);
printf("NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.\n\n");
printf("NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is "
"enabled.\n\n");
#if defined (__aarch64__) || defined(__arm__)
#if defined(__aarch64__) || defined(__arm__)
// find iGPU on the system which is compute capable which will perform GLES-CUDA interop
devID = findIntegratedGPU();
#else
@@ -678,12 +645,10 @@ int main(int argc, char **argv)
// get number of SMs on this GPU
checkCudaErrors(cudaGetDeviceProperties(&deviceProps, devID));
printf("CUDA device [%s] has %d Multi-Processors\n",
deviceProps.name, deviceProps.multiProcessorCount);
printf("CUDA device [%s] has %d Multi-Processors\n", deviceProps.name, deviceProps.multiProcessorCount);
// automated build testing harness
if (checkCmdLineFlag(argc, (const char **)argv, "file"))
{
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);
}
@@ -694,7 +659,7 @@ int main(int argc, char **argv)
memset(hvfield, 0, sizeof(cData) * DS);
// Allocate and initialize device data
checkCudaErrors(cudaMallocPitch((void **)&dvfield, &tPitch, sizeof(cData)*DIM, DIM));
checkCudaErrors(cudaMallocPitch((void **)&dvfield, &tPitch, sizeof(cData) * DIM, DIM));
checkCudaErrors(cudaMemcpy(dvfield, hvfield, sizeof(cData) * DS, cudaMemcpyHostToDevice));
// Temporary complex velocity field data
@@ -715,16 +680,14 @@ int main(int argc, char **argv)
runFluidsSimulation(argc, argv, ref_file);
if (ref_file)
{
if (ref_file) {
printf("[fluidsGLES] - Test Results: %d Failures\n", g_TotalErrors);
exit(g_TotalErrors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
sdkDeleteTimer(&timer);
if (!ref_file)
{
if (!ref_file) {
exit(EXIT_SUCCESS);
}

View File

@@ -25,13 +25,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cuda_runtime.h>
#include <cufft.h> // CUDA FFT Libraries
#include <helper_cuda.h> // Helper functions for CUDA Error handling
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
#include <cufft.h> // CUDA FFT Libraries
#include <helper_cuda.h> // Helper functions for CUDA Error handling
// OpenGL Graphics includes
#include <GLES3/gl31.h>
@@ -40,51 +39,52 @@
// Texture object for reading velocity field
cudaTextureObject_t texObj;
static cudaArray *array = NULL;
static cudaArray *array = NULL;
// Particle data
extern GLuint vbo; // OpenGL vertex buffer object
extern struct cudaGraphicsResource
*cuda_vbo_resource; // handles OpenGL-CUDA exchange
extern GLuint vbo; // OpenGL vertex buffer object
extern struct cudaGraphicsResource *cuda_vbo_resource; // handles OpenGL-CUDA exchange
// Texture pitch
extern size_t tPitch;
extern size_t tPitch;
extern cufftHandle planr2c;
extern cufftHandle planc2r;
cData *vxfield = NULL;
cData *vyfield = NULL;
cData *vxfield = NULL;
cData *vyfield = NULL;
void setupTexture(int x, int y) {
cudaChannelFormatDesc desc = cudaCreateChannelDesc<float2>();
void setupTexture(int x, int y)
{
cudaChannelFormatDesc desc = cudaCreateChannelDesc<float2>();
cudaMallocArray(&array, &desc, y, x);
getLastCudaError("cudaMalloc failed");
cudaMallocArray(&array, &desc, y, x);
getLastCudaError("cudaMalloc failed");
cudaResourceDesc texRes;
memset(&texRes, 0, sizeof(cudaResourceDesc));
cudaResourceDesc texRes;
memset(&texRes, 0, sizeof(cudaResourceDesc));
texRes.resType = cudaResourceTypeArray;
texRes.res.array.array = array;
texRes.resType = cudaResourceTypeArray;
texRes.res.array.array = array;
cudaTextureDesc texDescr;
memset(&texDescr, 0, sizeof(cudaTextureDesc));
cudaTextureDesc texDescr;
memset(&texDescr, 0, sizeof(cudaTextureDesc));
texDescr.normalizedCoords = false;
texDescr.filterMode = cudaFilterModeLinear;
texDescr.addressMode[0] = cudaAddressModeWrap;
texDescr.readMode = cudaReadModeElementType;
texDescr.normalizedCoords = false;
texDescr.filterMode = cudaFilterModeLinear;
texDescr.addressMode[0] = cudaAddressModeWrap;
texDescr.readMode = cudaReadModeElementType;
checkCudaErrors(cudaCreateTextureObject(&texObj, &texRes, &texDescr, NULL));
checkCudaErrors(cudaCreateTextureObject(&texObj, &texRes, &texDescr, NULL));
}
void updateTexture(cData *data, size_t wib, size_t h, size_t pitch) {
checkCudaErrors(cudaMemcpy2DToArray(array, 0, 0, data, pitch, wib, h,
cudaMemcpyDeviceToDevice));
void updateTexture(cData *data, size_t wib, size_t h, size_t pitch)
{
checkCudaErrors(cudaMemcpy2DToArray(array, 0, 0, data, pitch, wib, h, cudaMemcpyDeviceToDevice));
}
void deleteTexture(void) {
checkCudaErrors(cudaDestroyTextureObject(texObj));
checkCudaErrors(cudaFreeArray(array));
void deleteTexture(void)
{
checkCudaErrors(cudaDestroyTextureObject(texObj));
checkCudaErrors(cudaFreeArray(array));
}
// Note that these kernels are designed to work with arbitrary
@@ -98,54 +98,61 @@ void deleteTexture(void) {
// This method adds constant force vectors to the velocity field
// stored in 'v' according to v(x,t+1) = v(x,t) + dt * f.
__global__ void addForces_k(cData *v, int dx, int dy, int spx, int spy,
float fx, float fy, int r, size_t pitch) {
int tx = threadIdx.x;
int ty = threadIdx.y;
cData *fj = (cData *)((char *)v + (ty + spy) * pitch) + tx + spx;
__global__ void addForces_k(cData *v, int dx, int dy, int spx, int spy, float fx, float fy, int r, size_t pitch)
{
int tx = threadIdx.x;
int ty = threadIdx.y;
cData *fj = (cData *)((char *)v + (ty + spy) * pitch) + tx + spx;
cData vterm = *fj;
tx -= r;
ty -= r;
float s = 1.f / (1.f + tx * tx * tx * tx + ty * ty * ty * ty);
vterm.x += s * fx;
vterm.y += s * fy;
*fj = vterm;
cData vterm = *fj;
tx -= r;
ty -= r;
float s = 1.f / (1.f + tx * tx * tx * tx + ty * ty * ty * ty);
vterm.x += s * fx;
vterm.y += s * fy;
*fj = vterm;
}
// This method performs the velocity advection step, where we
// trace velocity vectors back in time to update each grid cell.
// That is, v(x,t+1) = v(p(x,-dt),t). Here we perform bilinear
// interpolation in the velocity space.
__global__ void advectVelocity_k(cData *v, float *vx, float *vy, int dx,
int pdx, int dy, float dt, int lb,
cudaTextureObject_t texObject) {
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
__global__ void advectVelocity_k(cData *v,
float *vx,
float *vy,
int dx,
int pdx,
int dy,
float dt,
int lb,
cudaTextureObject_t texObject)
{
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
cData vterm, ploc;
float vxterm, vyterm;
cData vterm, ploc;
float vxterm, vyterm;
// gtidx is the domain location in x for this thread
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
// gtidx is the domain location in x for this thread
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
if (fi < dy) {
int fj = fi * pdx + gtidx;
vterm = tex2D<cData>(texObject, (float)gtidx, (float)fi);
ploc.x = (gtidx + 0.5f) - (dt * vterm.x * dx);
ploc.y = (fi + 0.5f) - (dt * vterm.y * dy);
vterm = tex2D<cData>(texObject, ploc.x, ploc.y);
vxterm = vterm.x;
vyterm = vterm.y;
vx[fj] = vxterm;
vy[fj] = vyterm;
}
if (fi < dy) {
int fj = fi * pdx + gtidx;
vterm = tex2D<cData>(texObject, (float)gtidx, (float)fi);
ploc.x = (gtidx + 0.5f) - (dt * vterm.x * dx);
ploc.y = (fi + 0.5f) - (dt * vterm.y * dy);
vterm = tex2D<cData>(texObject, ploc.x, ploc.y);
vxterm = vterm.x;
vyterm = vterm.y;
vx[fj] = vxterm;
vy[fj] = vyterm;
}
}
}
}
}
// This method performs velocity diffusion and forces mass conservation
@@ -156,201 +163,194 @@ __global__ void advectVelocity_k(cData *v, float *vx, float *vy, int dx,
// and k is the wavenumber. The projection step forces the Fourier
// velocity vectors to be orthogonal to the vectors for each
// wavenumber: v(k,t) = v(k,t) - ((k dot v(k,t) * k) / k^2.
__global__ void diffuseProject_k(cData *vx, cData *vy, int dx, int dy, float dt,
float visc, int lb) {
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
__global__ void diffuseProject_k(cData *vx, cData *vy, int dx, int dy, float dt, float visc, int lb)
{
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
cData xterm, yterm;
cData xterm, yterm;
// gtidx is the domain location in x for this thread
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
// gtidx is the domain location in x for this thread
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
if (fi < dy) {
int fj = fi * dx + gtidx;
xterm = vx[fj];
yterm = vy[fj];
if (fi < dy) {
int fj = fi * dx + gtidx;
xterm = vx[fj];
yterm = vy[fj];
// Compute the index of the wavenumber based on the
// data order produced by a standard NN FFT.
int iix = gtidx;
int iiy = (fi > dy / 2) ? (fi - (dy)) : fi;
// Compute the index of the wavenumber based on the
// data order produced by a standard NN FFT.
int iix = gtidx;
int iiy = (fi > dy / 2) ? (fi - (dy)) : fi;
// Velocity diffusion
float kk = (float)(iix * iix + iiy * iiy); // k^2
float diff = 1.f / (1.f + visc * dt * kk);
xterm.x *= diff;
xterm.y *= diff;
yterm.x *= diff;
yterm.y *= diff;
// Velocity diffusion
float kk = (float)(iix * iix + iiy * iiy); // k^2
float diff = 1.f / (1.f + visc * dt * kk);
xterm.x *= diff;
xterm.y *= diff;
yterm.x *= diff;
yterm.y *= diff;
// Velocity projection
if (kk > 0.f) {
float rkk = 1.f / kk;
// Real portion of velocity projection
float rkp = (iix * xterm.x + iiy * yterm.x);
// Imaginary portion of velocity projection
float ikp = (iix * xterm.y + iiy * yterm.y);
xterm.x -= rkk * rkp * iix;
xterm.y -= rkk * ikp * iix;
yterm.x -= rkk * rkp * iiy;
yterm.y -= rkk * ikp * iiy;
// Velocity projection
if (kk > 0.f) {
float rkk = 1.f / kk;
// Real portion of velocity projection
float rkp = (iix * xterm.x + iiy * yterm.x);
// Imaginary portion of velocity projection
float ikp = (iix * xterm.y + iiy * yterm.y);
xterm.x -= rkk * rkp * iix;
xterm.y -= rkk * ikp * iix;
yterm.x -= rkk * rkp * iiy;
yterm.y -= rkk * ikp * iiy;
}
vx[fj] = xterm;
vy[fj] = yterm;
}
}
vx[fj] = xterm;
vy[fj] = yterm;
}
}
}
}
// This method updates the velocity field 'v' using the two complex
// arrays from the previous step: 'vx' and 'vy'. Here we scale the
// real components by 1/(dx*dy) to account for an unnormalized FFT.
__global__ void updateVelocity_k(cData *v, float *vx, float *vy, int dx,
int pdx, int dy, int lb, size_t pitch) {
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
__global__ void updateVelocity_k(cData *v, float *vx, float *vy, int dx, int pdx, int dy, int lb, size_t pitch)
{
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
float vxterm, vyterm;
cData nvterm;
float vxterm, vyterm;
cData nvterm;
// gtidx is the domain location in x for this thread
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
// gtidx is the domain location in x for this thread
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
if (fi < dy) {
int fjr = fi * pdx + gtidx;
vxterm = vx[fjr];
vyterm = vy[fjr];
if (fi < dy) {
int fjr = fi * pdx + gtidx;
vxterm = vx[fjr];
vyterm = vy[fjr];
// Normalize the result of the inverse FFT
float scale = 1.f / (dx * dy);
nvterm.x = vxterm * scale;
nvterm.y = vyterm * scale;
// Normalize the result of the inverse FFT
float scale = 1.f / (dx * dy);
nvterm.x = vxterm * scale;
nvterm.y = vyterm * scale;
cData *fj = (cData *)((char *)v + fi * pitch) + gtidx;
*fj = nvterm;
}
} // If this thread is inside the domain in Y
} // If this thread is inside the domain in X
cData *fj = (cData *)((char *)v + fi * pitch) + gtidx;
*fj = nvterm;
}
} // If this thread is inside the domain in Y
} // If this thread is inside the domain in X
}
// This method updates the particles by moving particle positions
// according to the velocity field and time step. That is, for each
// particle: p(t+1) = p(t) + dt * v(p(t)).
__global__ void advectParticles_k(cData *part, cData *v, int dx, int dy,
float dt, int lb, size_t pitch) {
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
__global__ void advectParticles_k(cData *part, cData *v, int dx, int dy, float dt, int lb, size_t pitch)
{
int gtidx = blockIdx.x * blockDim.x + threadIdx.x;
int gtidy = blockIdx.y * (lb * blockDim.y) + threadIdx.y * lb;
int p;
// gtidx is the domain location in x for this thread
cData pterm, vterm;
// gtidx is the domain location in x for this thread
cData pterm, vterm;
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
if (gtidx < dx) {
for (p = 0; p < lb; p++) {
// fi is the domain location in y for this thread
int fi = gtidy + p;
if (fi < dy) {
int fj = fi * dx + gtidx;
pterm = part[fj];
if (fi < dy) {
int fj = fi * dx + gtidx;
pterm = part[fj];
int xvi = ((int)(pterm.x * dx));
int yvi = ((int)(pterm.y * dy));
vterm = *((cData *)((char *)v + yvi * pitch) + xvi);
int xvi = ((int)(pterm.x * dx));
int yvi = ((int)(pterm.y * dy));
vterm = *((cData *)((char *)v + yvi * pitch) + xvi);
pterm.x += dt * vterm.x;
pterm.x = pterm.x - (int)pterm.x;
pterm.x += 1.f;
pterm.x = pterm.x - (int)pterm.x;
pterm.y += dt * vterm.y;
pterm.y = pterm.y - (int)pterm.y;
pterm.y += 1.f;
pterm.y = pterm.y - (int)pterm.y;
pterm.x += dt * vterm.x;
pterm.x = pterm.x - (int)pterm.x;
pterm.x += 1.f;
pterm.x = pterm.x - (int)pterm.x;
pterm.y += dt * vterm.y;
pterm.y = pterm.y - (int)pterm.y;
pterm.y += 1.f;
pterm.y = pterm.y - (int)pterm.y;
part[fj] = pterm;
}
} // If this thread is inside the domain in Y
} // If this thread is inside the domain in X
part[fj] = pterm;
}
} // If this thread is inside the domain in Y
} // If this thread is inside the domain in X
}
// These are the external function calls necessary for launching fluid simuation
extern "C" void addForces(cData *v, int dx, int dy, int spx, int spy, float fx,
float fy, int r) {
dim3 tids(2 * r + 1, 2 * r + 1);
extern "C" void addForces(cData *v, int dx, int dy, int spx, int spy, float fx, float fy, int r)
{
dim3 tids(2 * r + 1, 2 * r + 1);
addForces_k<<<1, tids>>>(v, dx, dy, spx, spy, fx, fy, r, tPitch);
getLastCudaError("addForces_k failed.");
addForces_k<<<1, tids>>>(v, dx, dy, spx, spy, fx, fy, r, tPitch);
getLastCudaError("addForces_k failed.");
}
extern "C" void advectVelocity(cData *v, float *vx, float *vy, int dx, int pdx,
int dy, float dt) {
dim3 grid((dx / TILEX) + (!(dx % TILEX) ? 0 : 1),
(dy / TILEY) + (!(dy % TILEY) ? 0 : 1));
extern "C" void advectVelocity(cData *v, float *vx, float *vy, int dx, int pdx, int dy, float dt)
{
dim3 grid((dx / TILEX) + (!(dx % TILEX) ? 0 : 1), (dy / TILEY) + (!(dy % TILEY) ? 0 : 1));
dim3 tids(TIDSX, TIDSY);
dim3 tids(TIDSX, TIDSY);
updateTexture(v, DIM * sizeof(cData), DIM, tPitch);
advectVelocity_k<<<grid, tids>>>(v, vx, vy, dx, pdx, dy, dt, TILEY / TIDSY,
texObj);
getLastCudaError("advectVelocity_k failed.");
updateTexture(v, DIM * sizeof(cData), DIM, tPitch);
advectVelocity_k<<<grid, tids>>>(v, vx, vy, dx, pdx, dy, dt, TILEY / TIDSY, texObj);
getLastCudaError("advectVelocity_k failed.");
}
extern "C" void diffuseProject(cData *vx, cData *vy, int dx, int dy, float dt,
float visc) {
// Forward FFT
checkCudaErrors(cufftExecR2C(planr2c, (cufftReal *)vx, (cufftComplex *)vx));
checkCudaErrors(cufftExecR2C(planr2c, (cufftReal *)vy, (cufftComplex *)vy));
extern "C" void diffuseProject(cData *vx, cData *vy, int dx, int dy, float dt, float visc)
{
// Forward FFT
checkCudaErrors(cufftExecR2C(planr2c, (cufftReal *)vx, (cufftComplex *)vx));
checkCudaErrors(cufftExecR2C(planr2c, (cufftReal *)vy, (cufftComplex *)vy));
uint3 grid = make_uint3((dx / TILEX) + (!(dx % TILEX) ? 0 : 1),
(dy / TILEY) + (!(dy % TILEY) ? 0 : 1), 1);
uint3 tids = make_uint3(TIDSX, TIDSY, 1);
uint3 grid = make_uint3((dx / TILEX) + (!(dx % TILEX) ? 0 : 1), (dy / TILEY) + (!(dy % TILEY) ? 0 : 1), 1);
uint3 tids = make_uint3(TIDSX, TIDSY, 1);
diffuseProject_k<<<grid, tids>>>(vx, vy, dx, dy, dt, visc, TILEY / TIDSY);
getLastCudaError("diffuseProject_k failed.");
diffuseProject_k<<<grid, tids>>>(vx, vy, dx, dy, dt, visc, TILEY / TIDSY);
getLastCudaError("diffuseProject_k failed.");
// Inverse FFT
checkCudaErrors(cufftExecC2R(planc2r, (cufftComplex *)vx, (cufftReal *)vx));
checkCudaErrors(cufftExecC2R(planc2r, (cufftComplex *)vy, (cufftReal *)vy));
// Inverse FFT
checkCudaErrors(cufftExecC2R(planc2r, (cufftComplex *)vx, (cufftReal *)vx));
checkCudaErrors(cufftExecC2R(planc2r, (cufftComplex *)vy, (cufftReal *)vy));
}
extern "C" void updateVelocity(cData *v, float *vx, float *vy, int dx, int pdx,
int dy) {
dim3 grid((dx / TILEX) + (!(dx % TILEX) ? 0 : 1),
(dy / TILEY) + (!(dy % TILEY) ? 0 : 1));
dim3 tids(TIDSX, TIDSY);
extern "C" void updateVelocity(cData *v, float *vx, float *vy, int dx, int pdx, int dy)
{
dim3 grid((dx / TILEX) + (!(dx % TILEX) ? 0 : 1), (dy / TILEY) + (!(dy % TILEY) ? 0 : 1));
dim3 tids(TIDSX, TIDSY);
updateVelocity_k<<<grid, tids>>>(v, vx, vy, dx, pdx, dy, TILEY / TIDSY,
tPitch);
getLastCudaError("updateVelocity_k failed.");
updateVelocity_k<<<grid, tids>>>(v, vx, vy, dx, pdx, dy, TILEY / TIDSY, tPitch);
getLastCudaError("updateVelocity_k failed.");
}
extern "C" void advectParticles(GLuint vbo, cData *v, int dx, int dy,
float dt) {
dim3 grid((dx / TILEX) + (!(dx % TILEX) ? 0 : 1),
(dy / TILEY) + (!(dy % TILEY) ? 0 : 1));
dim3 tids(TIDSX, TIDSY);
extern "C" void advectParticles(GLuint vbo, cData *v, int dx, int dy, float dt)
{
dim3 grid((dx / TILEX) + (!(dx % TILEX) ? 0 : 1), (dy / TILEY) + (!(dy % TILEY) ? 0 : 1));
dim3 tids(TIDSX, TIDSY);
cData *p;
checkCudaErrors(cudaGraphicsMapResources(1, &cuda_vbo_resource, 0));
getLastCudaError("cudaGraphicsMapResources failed");
cData *p;
checkCudaErrors(cudaGraphicsMapResources(1, &cuda_vbo_resource, 0));
getLastCudaError("cudaGraphicsMapResources failed");
size_t num_bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&p, &num_bytes,
cuda_vbo_resource));
getLastCudaError("cudaGraphicsResourceGetMappedPointer failed");
size_t num_bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&p, &num_bytes, cuda_vbo_resource));
getLastCudaError("cudaGraphicsResourceGetMappedPointer failed");
advectParticles_k<<<grid, tids>>>(p, v, dx, dy, dt, TILEY / TIDSY, tPitch);
getLastCudaError("advectParticles_k failed.");
advectParticles_k<<<grid, tids>>>(p, v, dx, dy, dt, TILEY / TIDSY, tPitch);
getLastCudaError("advectParticles_k failed.");
checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_vbo_resource, 0));
checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_vbo_resource, 0));
}

View File

@@ -39,16 +39,14 @@ void deleteTexture(void);
// This method adds constant force vectors to the velocity field
// stored in 'v' according to v(x,t+1) = v(x,t) + dt * f.
__global__ void addForces_k(cData *v, int dx, int dy, int spx, int spy,
float fx, float fy, int r, size_t pitch);
__global__ void addForces_k(cData *v, int dx, int dy, int spx, int spy, float fx, float fy, int r, size_t pitch);
// This method performs the velocity advection step, where we
// trace velocity vectors back in time to update each grid cell.
// That is, v(x,t+1) = v(p(x,-dt),t). Here we perform bilinear
// interpolation in the velocity space.
__global__ void advectVelocity_k(cData *v, float *vx, float *vy, int dx,
int pdx, int dy, float dt, int lb,
cudaTextureObject_t tex);
__global__ void
advectVelocity_k(cData *v, float *vx, float *vy, int dx, int pdx, int dy, float dt, int lb, cudaTextureObject_t tex);
// This method performs velocity diffusion and forces mass conservation
// in the frequency domain. The inputs 'vx' and 'vy' are complex-valued
@@ -58,19 +56,16 @@ __global__ void advectVelocity_k(cData *v, float *vx, float *vy, int dx,
// and k is the wavenumber. The projection step forces the Fourier
// velocity vectors to be orthogonal to the wave wave vectors for each
// wavenumber: v(k,t) = v(k,t) - ((k dot v(k,t) * k) / k^2.
__global__ void diffuseProject_k(cData *vx, cData *vy, int dx, int dy, float dt,
float visc, int lb);
__global__ void diffuseProject_k(cData *vx, cData *vy, int dx, int dy, float dt, float visc, int lb);
// This method updates the velocity field 'v' using the two complex
// arrays from the previous step: 'vx' and 'vy'. Here we scale the
// real components by 1/(dx*dy) to account for an unnormalized FFT.
__global__ void updateVelocity_k(cData *v, float *vx, float *vy, int dx,
int pdx, int dy, int lb, size_t pitch);
__global__ void updateVelocity_k(cData *v, float *vx, float *vy, int dx, int pdx, int dy, int lb, size_t pitch);
// This method updates the particles by moving particle positions
// according to the velocity field and time step. That is, for each
// particle: p(t+1) = p(t) + dt * v(p(t)).
__global__ void advectParticles_k(cData *part, cData *v, int dx, int dy,
float dt, int lb, size_t pitch);
__global__ void advectParticles_k(cData *part, cData *v, int dx, int dy, float dt, int lb, size_t pitch);
#endif

View File

@@ -20,16 +20,14 @@ void deleteTexture(void);
// This method adds constant force vectors to the velocity field
// stored in 'v' according to v(x,t+1) = v(x,t) + dt * f.
__global__ void
addForces_k(cData *v, int dx, int dy, int spx, int spy, float fx, float fy, int r, size_t pitch);
__global__ void addForces_k(cData *v, int dx, int dy, int spx, int spy, float fx, float fy, int r, size_t pitch);
// This method performs the velocity advection step, where we
// trace velocity vectors back in time to update each grid cell.
// That is, v(x,t+1) = v(p(x,-dt),t). Here we perform bilinear
// interpolation in the velocity space.
__global__ void
advectVelocity_k(cData *v, float *vx, float *vy,
int dx, int pdx, int dy, float dt, int lb, cudaTextureObject_t tex);
advectVelocity_k(cData *v, float *vx, float *vy, int dx, int pdx, int dy, float dt, int lb, cudaTextureObject_t tex);
// This method performs velocity diffusion and forces mass conservation
// in the frequency domain. The inputs 'vx' and 'vy' are complex-valued
@@ -39,23 +37,16 @@ advectVelocity_k(cData *v, float *vx, float *vy,
// and k is the wavenumber. The projection step forces the Fourier
// velocity vectors to be orthogonal to the wave wave vectors for each
// wavenumber: v(k,t) = v(k,t) - ((k dot v(k,t) * k) / k^2.
__global__ void
diffuseProject_k(cData *vx, cData *vy, int dx, int dy, float dt,
float visc, int lb);
__global__ void diffuseProject_k(cData *vx, cData *vy, int dx, int dy, float dt, float visc, int lb);
// This method updates the velocity field 'v' using the two complex
// arrays from the previous step: 'vx' and 'vy'. Here we scale the
// real components by 1/(dx*dy) to account for an unnormalized FFT.
__global__ void
updateVelocity_k(cData *v, float *vx, float *vy,
int dx, int pdx, int dy, int lb, size_t pitch);
__global__ void updateVelocity_k(cData *v, float *vx, float *vy, int dx, int pdx, int dy, int lb, size_t pitch);
// This method updates the particles by moving particle positions
// according to the velocity field and time step. That is, for each
// particle: p(t+1) = p(t) + dt * v(p(t)).
__global__ void
advectParticles_k(cData *part, cData *v, int dx, int dy,
float dt, int lb, size_t pitch);
__global__ void advectParticles_k(cData *part, cData *v, int dx, int dy, float dt, int lb, size_t pitch);
#endif

View File

@@ -31,165 +31,183 @@
#include <stdlib.h>
Display *display;
int screen;
Window win = 0;
int screen;
Window win = 0;
#include <GLES3/gl31.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl31.h>
#define GET_GLERROR(ret) \
\
{ \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, \
err); \
fflush(stderr); \
\
switch (err) { \
case GL_INVALID_ENUM: \
printf("GL_INVALID_ENUM\n"); \
break; \
case GL_INVALID_VALUE: \
printf("GL_INVALID_VALUE\n"); \
break; \
case GL_INVALID_OPERATION: \
printf("GL_INVALID_OPERATION\n"); \
break; \
case GL_OUT_OF_MEMORY: \
printf("GL_OUT_OF_MEMORY\n"); \
break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \
break; \
default: \
printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \
}; \
} \
\
}
#define GET_GLERROR(ret) \
\
{ \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, err); \
fflush(stderr); \
\
switch (err) { \
case GL_INVALID_ENUM: \
printf("GL_INVALID_ENUM\n"); \
break; \
case GL_INVALID_VALUE: \
printf("GL_INVALID_VALUE\n"); \
break; \
case GL_INVALID_OPERATION: \
printf("GL_INVALID_OPERATION\n"); \
break; \
case GL_OUT_OF_MEMORY: \
printf("GL_OUT_OF_MEMORY\n"); \
break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \
break; \
default: \
printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \
}; \
} \
}
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLSurface eglSurface = EGL_NO_SURFACE;
EGLContext eglContext = EGL_NO_CONTEXT;
int graphics_setup_window(int xpos, int ypos, int width, int height,
const char *windowname) {
// OpenGL ES 3.1
EGLint configAttrs[] = {
EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_DEPTH_SIZE, 16,
EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0,
// EGL_CONFORMANT, EGL_OPENGL_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // 3_BIT_KHR,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
int graphics_setup_window(int xpos, int ypos, int width, int height, const char *windowname)
{
// OpenGL ES 3.1
EGLint configAttrs[] = {EGL_RED_SIZE,
1,
EGL_GREEN_SIZE,
1,
EGL_BLUE_SIZE,
1,
EGL_DEPTH_SIZE,
16,
EGL_SAMPLE_BUFFERS,
0,
EGL_SAMPLES,
0,
// EGL_CONFORMANT, EGL_OPENGL_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT, // 3_BIT_KHR,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLConfig *configList = NULL;
EGLint configCount;
EGLConfig *configList = NULL;
EGLint configCount;
display = XOpenDisplay(NULL);
if (!display) error_exit("Error opening X display.\n");
display = XOpenDisplay(NULL);
if (!display)
error_exit("Error opening X display.\n");
screen = DefaultScreen(display);
screen = DefaultScreen(display);
eglDisplay = eglGetDisplay(0);
eglDisplay = eglGetDisplay(0);
if (eglDisplay == EGL_NO_DISPLAY)
error_exit("EGL failed to obtain display\n");
if (eglDisplay == EGL_NO_DISPLAY)
error_exit("EGL failed to obtain display\n");
if (!eglInitialize(eglDisplay, 0, 0))
error_exit("EGL failed to initialize\n");
if (!eglInitialize(eglDisplay, 0, 0))
error_exit("EGL failed to initialize\n");
if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) ||
!configCount)
error_exit("EGL failed to return any matching configurations\n");
if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) || !configCount)
error_exit("EGL failed to return any matching configurations\n");
configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig));
configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig));
if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount,
&configCount) ||
!configCount)
error_exit("EGL failed to populate configuration list\n");
if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount, &configCount) || !configCount)
error_exit("EGL failed to populate configuration list\n");
Window xRootWindow = DefaultRootWindow(display);
XSetWindowAttributes xCreateWindowAttributes;
xCreateWindowAttributes.event_mask = ExposureMask;
win = XCreateWindow(display, xRootWindow, 0, 0, width, height, 0,
CopyFromParent, InputOutput, CopyFromParent, CWEventMask,
&xCreateWindowAttributes);
XMapWindow(display, win);
Atom netWmStateAtom = XInternAtom(display, "_NET_WM_STATE", false);
XEvent xEvent;
memset(&xEvent, 0, sizeof(xEvent));
xEvent.type = ClientMessage;
xEvent.xclient.window = win;
xEvent.xclient.message_type = netWmStateAtom;
xEvent.xclient.format = 32;
xEvent.xclient.data.l[0] = 1;
xEvent.xclient.data.l[1] = false;
XSendEvent(display, xRootWindow, false, SubstructureNotifyMask, &xEvent);
Window xRootWindow = DefaultRootWindow(display);
XSetWindowAttributes xCreateWindowAttributes;
xCreateWindowAttributes.event_mask = ExposureMask;
win = XCreateWindow(display,
xRootWindow,
0,
0,
width,
height,
0,
CopyFromParent,
InputOutput,
CopyFromParent,
CWEventMask,
&xCreateWindowAttributes);
XMapWindow(display, win);
Atom netWmStateAtom = XInternAtom(display, "_NET_WM_STATE", false);
XEvent xEvent;
memset(&xEvent, 0, sizeof(xEvent));
xEvent.type = ClientMessage;
xEvent.xclient.window = win;
xEvent.xclient.message_type = netWmStateAtom;
xEvent.xclient.format = 32;
xEvent.xclient.data.l[0] = 1;
xEvent.xclient.data.l[1] = false;
XSendEvent(display, xRootWindow, false, SubstructureNotifyMask, &xEvent);
XStoreName(display, win, windowname);
XStoreName(display, win, windowname);
XSelectInput(display, win, ExposureMask | KeyPressMask | ButtonPressMask |
ButtonReleaseMask | KeyReleaseMask |
VisibilityChangeMask | PointerMotionMask);
XSelectInput(display,
win,
ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask
| VisibilityChangeMask | PointerMotionMask);
EGLint windowAttrs[] = {EGL_NONE};
EGLint windowAttrs[] = {EGL_NONE};
eglSurface = eglCreateWindowSurface(eglDisplay, configList[0],
(EGLNativeWindowType)win, windowAttrs);
eglSurface = eglCreateWindowSurface(eglDisplay, configList[0], (EGLNativeWindowType)win, windowAttrs);
if (!eglSurface) error_exit("EGL couldn't create window\n");
if (!eglSurface)
error_exit("EGL couldn't create window\n");
eglBindAPI(EGL_OPENGL_ES_API);
eglBindAPI(EGL_OPENGL_ES_API);
eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs);
if (!eglContext) error_exit("EGL couldn't create context\n");
eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs);
if (!eglContext)
error_exit("EGL couldn't create context\n");
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
error_exit("EGL couldn't make context/surface current\n");
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
error_exit("EGL couldn't make context/surface current\n");
EGLint Context_RendererType;
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE,
&Context_RendererType);
EGLint Context_RendererType;
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE, &Context_RendererType);
switch (Context_RendererType) {
switch (Context_RendererType) {
case EGL_OPENGL_API:
printf("Using OpenGL API is not supported\n");
exit(EXIT_FAILURE);
break;
printf("Using OpenGL API is not supported\n");
exit(EXIT_FAILURE);
break;
case EGL_OPENGL_ES_API:
printf("Using OpenGL ES API");
break;
printf("Using OpenGL ES API");
break;
case EGL_OPENVG_API:
error_exit("Context Query Returned OpenVG. This is Unsupported\n");
error_exit("Context Query Returned OpenVG. This is Unsupported\n");
default:
error_exit("Unknown Context Type. %04X\n", Context_RendererType);
}
error_exit("Unknown Context Type. %04X\n", Context_RendererType);
}
return 1;
return 1;
}
void graphics_set_windowtitle(const char *windowname) {
XStoreName(display, win, windowname);
}
void graphics_set_windowtitle(const char *windowname) { XStoreName(display, win, windowname); }
void graphics_swap_buffers() { eglSwapBuffers(eglDisplay, eglSurface); }
void graphics_close_window() {
if (eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
void graphics_close_window()
{
if (eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (eglContext != EGL_NO_CONTEXT) eglDestroyContext(eglDisplay, eglContext);
if (eglContext != EGL_NO_CONTEXT)
eglDestroyContext(eglDisplay, eglContext);
if (eglSurface != EGL_NO_SURFACE) eglDestroySurface(eglDisplay, eglSurface);
if (eglSurface != EGL_NO_SURFACE)
eglDestroySurface(eglDisplay, eglSurface);
eglTerminate(eglDisplay);
}
eglTerminate(eglDisplay);
}
if (win) XDestroyWindow(display, win);
if (win)
XDestroyWindow(display, win);
XCloseDisplay(display);
XCloseDisplay(display);
}

View File

@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -30,257 +30,262 @@
#include <algorithm>
enum NBodyConfig {
NBODY_CONFIG_RANDOM,
NBODY_CONFIG_SHELL,
NBODY_CONFIG_EXPAND,
NBODY_NUM_CONFIGS
};
enum NBodyConfig { NBODY_CONFIG_RANDOM, NBODY_CONFIG_SHELL, NBODY_CONFIG_EXPAND, NBODY_NUM_CONFIGS };
enum BodyArray {
BODYSYSTEM_POSITION,
BODYSYSTEM_VELOCITY,
BODYSYSTEM_POSITION,
BODYSYSTEM_VELOCITY,
};
template <typename T>
struct vec3 {
typedef float Type;
}; // dummy
template <>
struct vec3<float> {
typedef float3 Type;
template <typename T> struct vec3
{
typedef float Type;
}; // dummy
template <> struct vec3<float>
{
typedef float3 Type;
};
template <>
struct vec3<double> {
typedef double3 Type;
template <> struct vec3<double>
{
typedef double3 Type;
};
template <typename T>
struct vec4 {
typedef float Type;
}; // dummy
template <>
struct vec4<float> {
typedef float4 Type;
template <typename T> struct vec4
{
typedef float Type;
}; // dummy
template <> struct vec4<float>
{
typedef float4 Type;
};
template <>
struct vec4<double> {
typedef double4 Type;
template <> struct vec4<double>
{
typedef double4 Type;
};
class string;
// BodySystem abstract base class
template <typename T>
class BodySystem {
public: // methods
BodySystem(int numBodies) {}
virtual ~BodySystem() {}
template <typename T> class BodySystem
{
public: // methods
BodySystem(int numBodies) {}
virtual ~BodySystem() {}
virtual void loadTipsyFile(const std::string &filename) = 0;
virtual void loadTipsyFile(const std::string &filename) = 0;
virtual void update(T deltaTime) = 0;
virtual void update(T deltaTime) = 0;
virtual void setSoftening(T softening) = 0;
virtual void setDamping(T damping) = 0;
virtual void setSoftening(T softening) = 0;
virtual void setDamping(T damping) = 0;
virtual T *getArray(BodyArray array) = 0;
virtual void setArray(BodyArray array, const T *data) = 0;
virtual T *getArray(BodyArray array) = 0;
virtual void setArray(BodyArray array, const T *data) = 0;
virtual unsigned int getCurrentReadBuffer() const = 0;
virtual unsigned int getCurrentReadBuffer() const = 0;
virtual unsigned int getNumBodies() const = 0;
virtual unsigned int getNumBodies() const = 0;
virtual void synchronizeThreads() const {};
virtual void synchronizeThreads() const {};
protected: // methods
BodySystem() {} // default constructor
protected: // methods
BodySystem() {} // default constructor
virtual void _initialize(int numBodies) = 0;
virtual void _finalize() = 0;
virtual void _initialize(int numBodies) = 0;
virtual void _finalize() = 0;
};
inline float3 scalevec(float3 &vector, float scalar) {
float3 rt = vector;
rt.x *= scalar;
rt.y *= scalar;
rt.z *= scalar;
return rt;
inline float3 scalevec(float3 &vector, float scalar)
{
float3 rt = vector;
rt.x *= scalar;
rt.y *= scalar;
rt.z *= scalar;
return rt;
}
inline float normalize(float3 &vector) {
float dist =
sqrtf(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
inline float normalize(float3 &vector)
{
float dist = sqrtf(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
if (dist > 1e-6) {
vector.x /= dist;
vector.y /= dist;
vector.z /= dist;
}
if (dist > 1e-6) {
vector.x /= dist;
vector.y /= dist;
vector.z /= dist;
}
return dist;
return dist;
}
inline float dot(float3 v0, float3 v1) {
return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
}
inline float dot(float3 v0, float3 v1) { return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z; }
inline float3 cross(float3 v0, float3 v1) {
float3 rt;
rt.x = v0.y * v1.z - v0.z * v1.y;
rt.y = v0.z * v1.x - v0.x * v1.z;
rt.z = v0.x * v1.y - v0.y * v1.x;
return rt;
inline float3 cross(float3 v0, float3 v1)
{
float3 rt;
rt.x = v0.y * v1.z - v0.z * v1.y;
rt.y = v0.z * v1.x - v0.x * v1.z;
rt.z = v0.x * v1.y - v0.y * v1.x;
return rt;
}
// utility function
template <typename T>
void randomizeBodies(NBodyConfig config, T *pos, T *vel, float *color,
float clusterScale, float velocityScale, int numBodies,
bool vec4vel) {
switch (config) {
void randomizeBodies(NBodyConfig config,
T *pos,
T *vel,
float *color,
float clusterScale,
float velocityScale,
int numBodies,
bool vec4vel)
{
switch (config) {
default:
case NBODY_CONFIG_RANDOM: {
float scale = clusterScale * std::max<float>(1.0f, numBodies / (1024.0f));
float vscale = velocityScale * scale;
float scale = clusterScale * std::max<float>(1.0f, numBodies / (1024.0f));
float vscale = velocityScale * scale;
int p = 0, v = 0;
int i = 0;
int p = 0, v = 0;
int i = 0;
while (i < numBodies) {
float3 point;
// const int scale = 16;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
float lenSqr = dot(point, point);
while (i < numBodies) {
float3 point;
// const int scale = 16;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
float lenSqr = dot(point, point);
if (lenSqr > 1) continue;
if (lenSqr > 1)
continue;
float3 velocity;
velocity.x = rand() / (float)RAND_MAX * 2 - 1;
velocity.y = rand() / (float)RAND_MAX * 2 - 1;
velocity.z = rand() / (float)RAND_MAX * 2 - 1;
lenSqr = dot(velocity, velocity);
float3 velocity;
velocity.x = rand() / (float)RAND_MAX * 2 - 1;
velocity.y = rand() / (float)RAND_MAX * 2 - 1;
velocity.z = rand() / (float)RAND_MAX * 2 - 1;
lenSqr = dot(velocity, velocity);
if (lenSqr > 1) continue;
if (lenSqr > 1)
continue;
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
vel[v++] = velocity.x * vscale; // pos.x
vel[v++] = velocity.y * vscale; // pos.x
vel[v++] = velocity.z * vscale; // pos.x
vel[v++] = velocity.x * vscale; // pos.x
vel[v++] = velocity.y * vscale; // pos.x
vel[v++] = velocity.z * vscale; // pos.x
if (vec4vel) vel[v++] = 1.0f; // inverse mass
if (vec4vel)
vel[v++] = 1.0f; // inverse mass
i++;
}
i++;
}
} break;
case NBODY_CONFIG_SHELL: {
float scale = clusterScale;
float vscale = scale * velocityScale;
float inner = 2.5f * scale;
float outer = 4.0f * scale;
float scale = clusterScale;
float vscale = scale * velocityScale;
float inner = 2.5f * scale;
float outer = 4.0f * scale;
int p = 0, v = 0;
int i = 0;
int p = 0, v = 0;
int i = 0;
while (i < numBodies) // for(int i=0; i < numBodies; i++)
{
float x, y, z;
x = rand() / (float)RAND_MAX * 2 - 1;
y = rand() / (float)RAND_MAX * 2 - 1;
z = rand() / (float)RAND_MAX * 2 - 1;
while (i < numBodies) // for(int i=0; i < numBodies; i++)
{
float x, y, z;
x = rand() / (float)RAND_MAX * 2 - 1;
y = rand() / (float)RAND_MAX * 2 - 1;
z = rand() / (float)RAND_MAX * 2 - 1;
float3 point = {x, y, z};
float len = normalize(point);
float3 point = {x, y, z};
float len = normalize(point);
if (len > 1) continue;
if (len > 1)
continue;
pos[p++] =
point.x * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] =
point.y * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] =
point.z * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = 1.0f;
pos[p++] = point.x * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = point.y * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = point.z * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = 1.0f;
x = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
y = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
z = 1.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
float3 axis = {x, y, z};
normalize(axis);
x = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
y = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
z = 1.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
float3 axis = {x, y, z};
normalize(axis);
if (1 - dot(point, axis) < 1e-6) {
axis.x = point.y;
axis.y = point.x;
normalize(axis);
if (1 - dot(point, axis) < 1e-6) {
axis.x = point.y;
axis.y = point.x;
normalize(axis);
}
// if (point.y < 0) axis = scalevec(axis, -1);
float3 vv = {(float)pos[4 * i], (float)pos[4 * i + 1], (float)pos[4 * i + 2]};
vv = cross(vv, axis);
vel[v++] = vv.x * vscale;
vel[v++] = vv.y * vscale;
vel[v++] = vv.z * vscale;
if (vec4vel)
vel[v++] = 1.0f;
i++;
}
// if (point.y < 0) axis = scalevec(axis, -1);
float3 vv = {(float)pos[4 * i], (float)pos[4 * i + 1],
(float)pos[4 * i + 2]};
vv = cross(vv, axis);
vel[v++] = vv.x * vscale;
vel[v++] = vv.y * vscale;
vel[v++] = vv.z * vscale;
if (vec4vel) vel[v++] = 1.0f;
i++;
}
} break;
case NBODY_CONFIG_EXPAND: {
float scale = clusterScale * numBodies / (1024.f);
float scale = clusterScale * numBodies / (1024.f);
if (scale < 1.0f) scale = clusterScale;
if (scale < 1.0f)
scale = clusterScale;
float vscale = scale * velocityScale;
float vscale = scale * velocityScale;
int p = 0, v = 0;
int p = 0, v = 0;
for (int i = 0; i < numBodies;) {
float3 point;
for (int i = 0; i < numBodies;) {
float3 point;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
float lenSqr = dot(point, point);
float lenSqr = dot(point, point);
if (lenSqr > 1) continue;
if (lenSqr > 1)
continue;
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
vel[v++] = point.x * vscale; // pos.x
vel[v++] = point.y * vscale; // pos.x
vel[v++] = point.z * vscale; // pos.x
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
vel[v++] = point.x * vscale; // pos.x
vel[v++] = point.y * vscale; // pos.x
vel[v++] = point.z * vscale; // pos.x
if (vec4vel) vel[v++] = 1.0f; // inverse mass
if (vec4vel)
vel[v++] = 1.0f; // inverse mass
i++;
}
i++;
}
} break;
}
if (color) {
int v = 0;
for (int i = 0; i < numBodies; i++) {
// const int scale = 16;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = 1.0f;
}
}
if (color) {
int v = 0;
for (int i = 0; i < numBodies; i++) {
// const int scale = 16;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = 1.0f;
}
}
}
#endif // __BODYSYSTEM_H__
#endif // __BODYSYSTEM_H__

View File

@@ -31,49 +31,47 @@
#include "bodysystem.h"
// CPU Body System
template <typename T>
class BodySystemCPU : public BodySystem<T> {
public:
BodySystemCPU(int numBodies);
virtual ~BodySystemCPU();
template <typename T> class BodySystemCPU : public BodySystem<T>
{
public:
BodySystemCPU(int numBodies);
virtual ~BodySystemCPU();
virtual void loadTipsyFile(const std::string &filename);
virtual void loadTipsyFile(const std::string &filename);
virtual void update(T deltaTime);
virtual void update(T deltaTime);
virtual void setSoftening(T softening) {
m_softeningSquared = softening * softening;
}
virtual void setDamping(T damping) { m_damping = damping; }
virtual void setSoftening(T softening) { m_softeningSquared = softening * softening; }
virtual void setDamping(T damping) { m_damping = damping; }
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual unsigned int getCurrentReadBuffer() const { return 0; }
virtual unsigned int getCurrentReadBuffer() const { return 0; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
protected: // methods
BodySystemCPU() {} // default constructor
protected: // methods
BodySystemCPU() {} // default constructor
virtual void _initialize(int numBodies);
virtual void _finalize();
virtual void _initialize(int numBodies);
virtual void _finalize();
void _computeNBodyGravitation();
void _integrateNBodySystem(T deltaTime);
void _computeNBodyGravitation();
void _integrateNBodySystem(T deltaTime);
protected: // data
int m_numBodies;
bool m_bInitialized;
protected: // data
int m_numBodies;
bool m_bInitialized;
T *m_pos;
T *m_vel;
T *m_force;
T *m_pos;
T *m_vel;
T *m_force;
T m_softeningSquared;
T m_damping;
T m_softeningSquared;
T m_damping;
};
#include "bodysystemcpu_impl.h"
#endif // __BODYSYSTEMCPU_H__
#endif // __BODYSYSTEMCPU_H__

View File

@@ -25,15 +25,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bodysystemcpu.h"
#include <assert.h>
#include <memory.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <helper_cuda.h>
#include <algorithm>
#include <assert.h>
#include <helper_cuda.h>
#include <math.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include "bodysystemcpu.h"
#include "tipsy.h"
#ifdef OPENMP
@@ -42,239 +42,229 @@
template <typename T>
BodySystemCPU<T>::BodySystemCPU(int numBodies)
: m_numBodies(numBodies),
m_bInitialized(false),
m_force(0),
m_softeningSquared(.00125f),
m_damping(0.995f) {
m_pos = 0;
m_vel = 0;
: m_numBodies(numBodies)
, m_bInitialized(false)
, m_force(0)
, m_softeningSquared(.00125f)
, m_damping(0.995f)
{
m_pos = 0;
m_vel = 0;
_initialize(numBodies);
_initialize(numBodies);
}
template <typename T>
BodySystemCPU<T>::~BodySystemCPU() {
_finalize();
m_numBodies = 0;
template <typename T> BodySystemCPU<T>::~BodySystemCPU()
{
_finalize();
m_numBodies = 0;
}
template <typename T>
void BodySystemCPU<T>::_initialize(int numBodies) {
assert(!m_bInitialized);
template <typename T> void BodySystemCPU<T>::_initialize(int numBodies)
{
assert(!m_bInitialized);
m_numBodies = numBodies;
m_numBodies = numBodies;
m_pos = new T[m_numBodies * 4];
m_vel = new T[m_numBodies * 4];
m_force = new T[m_numBodies * 3];
m_pos = new T[m_numBodies * 4];
m_vel = new T[m_numBodies * 4];
m_force = new T[m_numBodies * 3];
memset(m_pos, 0, m_numBodies * 4 * sizeof(T));
memset(m_vel, 0, m_numBodies * 4 * sizeof(T));
memset(m_force, 0, m_numBodies * 3 * sizeof(T));
memset(m_pos, 0, m_numBodies * 4 * sizeof(T));
memset(m_vel, 0, m_numBodies * 4 * sizeof(T));
memset(m_force, 0, m_numBodies * 3 * sizeof(T));
m_bInitialized = true;
m_bInitialized = true;
}
template <typename T>
void BodySystemCPU<T>::_finalize() {
assert(m_bInitialized);
template <typename T> void BodySystemCPU<T>::_finalize()
{
assert(m_bInitialized);
delete[] m_pos;
delete[] m_vel;
delete[] m_force;
delete[] m_pos;
delete[] m_vel;
delete[] m_force;
m_bInitialized = false;
m_bInitialized = false;
}
template <typename T>
void BodySystemCPU<T>::loadTipsyFile(const std::string &filename) {
if (m_bInitialized) _finalize();
template <typename T> void BodySystemCPU<T>::loadTipsyFile(const std::string &filename)
{
if (m_bInitialized)
_finalize();
vector<typename vec4<T>::Type> positions;
vector<typename vec4<T>::Type> velocities;
vector<int> ids;
vector<typename vec4<T>::Type> positions;
vector<typename vec4<T>::Type> velocities;
vector<int> ids;
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst,
nSecond, nThird);
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst, nSecond, nThird);
_initialize(nBodies);
_initialize(nBodies);
memcpy(m_pos, &positions[0], sizeof(vec4<T>) * nBodies);
memcpy(m_vel, &velocities[0], sizeof(vec4<T>) * nBodies);
memcpy(m_pos, &positions[0], sizeof(vec4<T>) * nBodies);
memcpy(m_vel, &velocities[0], sizeof(vec4<T>) * nBodies);
}
template <typename T>
void BodySystemCPU<T>::update(T deltaTime) {
assert(m_bInitialized);
template <typename T> void BodySystemCPU<T>::update(T deltaTime)
{
assert(m_bInitialized);
_integrateNBodySystem(deltaTime);
_integrateNBodySystem(deltaTime);
// std::swap(m_currentRead, m_currentWrite);
// std::swap(m_currentRead, m_currentWrite);
}
template <typename T>
T *BodySystemCPU<T>::getArray(BodyArray array) {
assert(m_bInitialized);
template <typename T> T *BodySystemCPU<T>::getArray(BodyArray array)
{
assert(m_bInitialized);
T *data = 0;
T *data = 0;
switch (array) {
switch (array) {
default:
case BODYSYSTEM_POSITION:
data = m_pos;
break;
data = m_pos;
break;
case BODYSYSTEM_VELOCITY:
data = m_vel;
break;
}
return data;
}
template <typename T>
void BodySystemCPU<T>::setArray(BodyArray array, const T *data) {
assert(m_bInitialized);
T *target = 0;
switch (array) {
default:
case BODYSYSTEM_POSITION:
target = m_pos;
break;
case BODYSYSTEM_VELOCITY:
target = m_vel;
break;
}
memcpy(target, data, m_numBodies * 4 * sizeof(T));
}
template <typename T>
T sqrt_T(T x) {
return sqrt(x);
}
template <>
float sqrt_T<float>(float x) {
return sqrtf(x);
}
template <typename T>
void bodyBodyInteraction(T accel[3], T posMass0[4], T posMass1[4],
T softeningSquared) {
T r[3];
// r_01 [3 FLOPS]
r[0] = posMass1[0] - posMass0[0];
r[1] = posMass1[1] - posMass0[1];
r[2] = posMass1[2] - posMass0[2];
// d^2 + e^2 [6 FLOPS]
T distSqr = r[0] * r[0] + r[1] * r[1] + r[2] * r[2];
distSqr += softeningSquared;
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = (T)1.0 / (T)sqrt((double)distSqr);
T invDistCube = invDist * invDist * invDist;
// s = m_j * invDistCube [1 FLOP]
T s = posMass1[3] * invDistCube;
// (m_1 * r_01) / (d^2 + e^2)^(3/2) [6 FLOPS]
accel[0] += r[0] * s;
accel[1] += r[1] * s;
accel[2] += r[2] * s;
}
template <typename T>
void BodySystemCPU<T>::_computeNBodyGravitation() {
#ifdef OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < m_numBodies; i++) {
int indexForce = 3 * i;
T acc[3] = {0, 0, 0};
// We unroll this loop 4X for a small performance boost.
int j = 0;
while (j < m_numBodies) {
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
data = m_vel;
break;
}
m_force[indexForce] = acc[0];
m_force[indexForce + 1] = acc[1];
m_force[indexForce + 2] = acc[2];
}
return data;
}
template <typename T>
void BodySystemCPU<T>::_integrateNBodySystem(T deltaTime) {
_computeNBodyGravitation();
template <typename T> void BodySystemCPU<T>::setArray(BodyArray array, const T *data)
{
assert(m_bInitialized);
T *target = 0;
switch (array) {
default:
case BODYSYSTEM_POSITION:
target = m_pos;
break;
case BODYSYSTEM_VELOCITY:
target = m_vel;
break;
}
memcpy(target, data, m_numBodies * 4 * sizeof(T));
}
template <typename T> T sqrt_T(T x) { return sqrt(x); }
template <> float sqrt_T<float>(float x) { return sqrtf(x); }
template <typename T> void bodyBodyInteraction(T accel[3], T posMass0[4], T posMass1[4], T softeningSquared)
{
T r[3];
// r_01 [3 FLOPS]
r[0] = posMass1[0] - posMass0[0];
r[1] = posMass1[1] - posMass0[1];
r[2] = posMass1[2] - posMass0[2];
// d^2 + e^2 [6 FLOPS]
T distSqr = r[0] * r[0] + r[1] * r[1] + r[2] * r[2];
distSqr += softeningSquared;
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = (T)1.0 / (T)sqrt((double)distSqr);
T invDistCube = invDist * invDist * invDist;
// s = m_j * invDistCube [1 FLOP]
T s = posMass1[3] * invDistCube;
// (m_1 * r_01) / (d^2 + e^2)^(3/2) [6 FLOPS]
accel[0] += r[0] * s;
accel[1] += r[1] * s;
accel[2] += r[2] * s;
}
template <typename T> void BodySystemCPU<T>::_computeNBodyGravitation()
{
#ifdef OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < m_numBodies; i++) {
int indexForce = 3 * i;
T acc[3] = {0, 0, 0};
// We unroll this loop 4X for a small performance boost.
int j = 0;
while (j < m_numBodies) {
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
}
m_force[indexForce] = acc[0];
m_force[indexForce + 1] = acc[1];
m_force[indexForce + 2] = acc[2];
}
}
template <typename T> void BodySystemCPU<T>::_integrateNBodySystem(T deltaTime)
{
_computeNBodyGravitation();
#ifdef OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < m_numBodies; ++i) {
int index = 4 * i;
int indexForce = 3 * i;
for (int i = 0; i < m_numBodies; ++i) {
int index = 4 * i;
int indexForce = 3 * i;
T pos[3], vel[3], force[3];
pos[0] = m_pos[index + 0];
pos[1] = m_pos[index + 1];
pos[2] = m_pos[index + 2];
T invMass = m_pos[index + 3];
T pos[3], vel[3], force[3];
pos[0] = m_pos[index + 0];
pos[1] = m_pos[index + 1];
pos[2] = m_pos[index + 2];
T invMass = m_pos[index + 3];
vel[0] = m_vel[index + 0];
vel[1] = m_vel[index + 1];
vel[2] = m_vel[index + 2];
vel[0] = m_vel[index + 0];
vel[1] = m_vel[index + 1];
vel[2] = m_vel[index + 2];
force[0] = m_force[indexForce + 0];
force[1] = m_force[indexForce + 1];
force[2] = m_force[indexForce + 2];
force[0] = m_force[indexForce + 0];
force[1] = m_force[indexForce + 1];
force[2] = m_force[indexForce + 2];
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
vel[0] += (force[0] * invMass) * deltaTime;
vel[1] += (force[1] * invMass) * deltaTime;
vel[2] += (force[2] * invMass) * deltaTime;
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
vel[0] += (force[0] * invMass) * deltaTime;
vel[1] += (force[1] * invMass) * deltaTime;
vel[2] += (force[2] * invMass) * deltaTime;
vel[0] *= m_damping;
vel[1] *= m_damping;
vel[2] *= m_damping;
vel[0] *= m_damping;
vel[1] *= m_damping;
vel[2] *= m_damping;
// new position = old position + velocity * deltaTime
pos[0] += vel[0] * deltaTime;
pos[1] += vel[1] * deltaTime;
pos[2] += vel[2] * deltaTime;
// new position = old position + velocity * deltaTime
pos[0] += vel[0] * deltaTime;
pos[1] += vel[1] * deltaTime;
pos[2] += vel[2] * deltaTime;
m_pos[index + 0] = pos[0];
m_pos[index + 1] = pos[1];
m_pos[index + 2] = pos[2];
m_pos[index + 0] = pos[0];
m_pos[index + 1] = pos[1];
m_pos[index + 2] = pos[2];
m_vel[index + 0] = vel[0];
m_vel[index + 1] = vel[1];
m_vel[index + 2] = vel[2];
}
m_vel[index + 0] = vel[0];
m_vel[index + 1] = vel[1];
m_vel[index + 2] = vel[2];
}
}

View File

@@ -28,249 +28,246 @@
#include <helper_cuda.h>
#include <math.h>
//#include <GL/glew.h>
//#include <GL/freeglut.h>
// #include <GL/glew.h>
// #include <GL/freeglut.h>
// CUDA standard includes
#include <cuda_runtime.h>
//#include <cuda_gl_interop.h>
// #include <cuda_gl_interop.h>
#include "bodysystem.h"
__constant__ float softeningSquared;
__constant__ float softeningSquared;
__constant__ double softeningSquared_fp64;
cudaError_t setSofteningSquared(float softeningSq) {
return cudaMemcpyToSymbol(softeningSquared, &softeningSq, sizeof(float), 0,
cudaMemcpyHostToDevice);
cudaError_t setSofteningSquared(float softeningSq)
{
return cudaMemcpyToSymbol(softeningSquared, &softeningSq, sizeof(float), 0, cudaMemcpyHostToDevice);
}
cudaError_t setSofteningSquared(double softeningSq) {
return cudaMemcpyToSymbol(softeningSquared_fp64, &softeningSq, sizeof(double),
0, cudaMemcpyHostToDevice);
cudaError_t setSofteningSquared(double softeningSq)
{
return cudaMemcpyToSymbol(softeningSquared_fp64, &softeningSq, sizeof(double), 0, cudaMemcpyHostToDevice);
}
template <class T>
struct SharedMemory {
__device__ inline operator T *() {
extern __shared__ int __smem[];
return (T *)__smem;
}
template <class T> struct SharedMemory
{
__device__ inline operator T *()
{
extern __shared__ int __smem[];
return (T *)__smem;
}
__device__ inline operator const T *() const {
extern __shared__ int __smem[];
return (T *)__smem;
}
__device__ inline operator const T *() const
{
extern __shared__ int __smem[];
return (T *)__smem;
}
};
template <typename T>
__device__ T rsqrt_T(T x) {
return rsqrt(x);
}
template <typename T> __device__ T rsqrt_T(T x) { return rsqrt(x); }
template <>
__device__ float rsqrt_T<float>(float x) {
return rsqrtf(x);
}
template <> __device__ float rsqrt_T<float>(float x) { return rsqrtf(x); }
template <>
__device__ double rsqrt_T<double>(double x) {
return rsqrt(x);
}
template <> __device__ double rsqrt_T<double>(double x) { return rsqrt(x); }
// Macros to simplify shared memory addressing
#define SX(i) sharedPos[i + blockDim.x * threadIdx.y]
// This macro is only used when multithreadBodies is true (below)
#define SX_SUM(i, j) sharedPos[i + blockDim.x * j]
template <typename T>
__device__ T getSofteningSquared() {
return softeningSquared;
}
template <>
__device__ double getSofteningSquared<double>() {
return softeningSquared_fp64;
}
template <typename T> __device__ T getSofteningSquared() { return softeningSquared; }
template <> __device__ double getSofteningSquared<double>() { return softeningSquared_fp64; }
template <typename T>
struct DeviceData {
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
template <typename T> struct DeviceData
{
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
};
template <typename T>
__device__ typename vec3<T>::Type bodyBodyInteraction(
typename vec3<T>::Type ai, typename vec4<T>::Type bi,
typename vec4<T>::Type bj) {
typename vec3<T>::Type r;
__device__ typename vec3<T>::Type
bodyBodyInteraction(typename vec3<T>::Type ai, typename vec4<T>::Type bi, typename vec4<T>::Type bj)
{
typename vec3<T>::Type r;
// r_ij [3 FLOPS]
r.x = bj.x - bi.x;
r.y = bj.y - bi.y;
r.z = bj.z - bi.z;
// r_ij [3 FLOPS]
r.x = bj.x - bi.x;
r.y = bj.y - bi.y;
r.z = bj.z - bi.z;
// distSqr = dot(r_ij, r_ij) + EPS^2 [6 FLOPS]
T distSqr = r.x * r.x + r.y * r.y + r.z * r.z;
distSqr += getSofteningSquared<T>();
// distSqr = dot(r_ij, r_ij) + EPS^2 [6 FLOPS]
T distSqr = r.x * r.x + r.y * r.y + r.z * r.z;
distSqr += getSofteningSquared<T>();
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = rsqrt_T(distSqr);
T invDistCube = invDist * invDist * invDist;
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = rsqrt_T(distSqr);
T invDistCube = invDist * invDist * invDist;
// s = m_j * invDistCube [1 FLOP]
T s = bj.w * invDistCube;
// s = m_j * invDistCube [1 FLOP]
T s = bj.w * invDistCube;
// a_i = a_i + s * r_ij [6 FLOPS]
ai.x += r.x * s;
ai.y += r.y * s;
ai.z += r.z * s;
// a_i = a_i + s * r_ij [6 FLOPS]
ai.x += r.x * s;
ai.y += r.y * s;
ai.z += r.z * s;
return ai;
return ai;
}
template <typename T>
__device__ typename vec3<T>::Type computeBodyAccel(
typename vec4<T>::Type bodyPos, typename vec4<T>::Type *positions,
int numTiles) {
typename vec4<T>::Type *sharedPos = SharedMemory<typename vec4<T>::Type>();
__device__ typename vec3<T>::Type
computeBodyAccel(typename vec4<T>::Type bodyPos, typename vec4<T>::Type *positions, int numTiles)
{
typename vec4<T>::Type *sharedPos = SharedMemory<typename vec4<T>::Type>();
typename vec3<T>::Type acc = {0.0f, 0.0f, 0.0f};
typename vec3<T>::Type acc = {0.0f, 0.0f, 0.0f};
for (int tile = 0; tile < numTiles; tile++) {
sharedPos[threadIdx.x] = positions[tile * blockDim.x + threadIdx.x];
for (int tile = 0; tile < numTiles; tile++) {
sharedPos[threadIdx.x] = positions[tile * blockDim.x + threadIdx.x];
__syncthreads();
__syncthreads();
// This is the "tile_calculation" from the GPUG3 article.
// This is the "tile_calculation" from the GPUG3 article.
#pragma unroll 128
for (unsigned int counter = 0; counter < blockDim.x; counter++) {
acc = bodyBodyInteraction<T>(acc, bodyPos, sharedPos[counter]);
for (unsigned int counter = 0; counter < blockDim.x; counter++) {
acc = bodyBodyInteraction<T>(acc, bodyPos, sharedPos[counter]);
}
__syncthreads();
}
__syncthreads();
}
return acc;
return acc;
}
template <typename T>
__global__ void integrateBodies(typename vec4<T>::Type *__restrict__ newPos,
typename vec4<T>::Type *__restrict__ oldPos,
typename vec4<T>::Type *vel,
unsigned int deviceOffset,
unsigned int deviceNumBodies, float deltaTime,
float damping, int numTiles) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int deviceOffset,
unsigned int deviceNumBodies,
float deltaTime,
float damping,
int numTiles)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
if (index >= deviceNumBodies) {
return;
}
if (index >= deviceNumBodies) {
return;
}
typename vec4<T>::Type position = oldPos[deviceOffset + index];
typename vec4<T>::Type position = oldPos[deviceOffset + index];
typename vec3<T>::Type accel =
computeBodyAccel<T>(position, oldPos, numTiles);
typename vec3<T>::Type accel = computeBodyAccel<T>(position, oldPos, numTiles);
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
// note we factor out the body's mass from the equation, here and in
// bodyBodyInteraction (because they cancel out). Thus here force ==
// acceleration
typename vec4<T>::Type velocity = vel[deviceOffset + index];
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
// note we factor out the body's mass from the equation, here and in
// bodyBodyInteraction (because they cancel out). Thus here force ==
// acceleration
typename vec4<T>::Type velocity = vel[deviceOffset + index];
velocity.x += accel.x * deltaTime;
velocity.y += accel.y * deltaTime;
velocity.z += accel.z * deltaTime;
velocity.x += accel.x * deltaTime;
velocity.y += accel.y * deltaTime;
velocity.z += accel.z * deltaTime;
velocity.x *= damping;
velocity.y *= damping;
velocity.z *= damping;
velocity.x *= damping;
velocity.y *= damping;
velocity.z *= damping;
// new position = old position + velocity * deltaTime
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
position.z += velocity.z * deltaTime;
// new position = old position + velocity * deltaTime
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
position.z += velocity.z * deltaTime;
// store new position and velocity
newPos[deviceOffset + index] = position;
vel[deviceOffset + index] = velocity;
// store new position and velocity
newPos[deviceOffset + index] = position;
vel[deviceOffset + index] = velocity;
}
template <typename T>
void integrateNbodySystem(DeviceData<T> *deviceData,
void integrateNbodySystem(DeviceData<T> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead, float deltaTime,
float damping, unsigned int numBodies,
unsigned int numDevices, int blockSize,
bool bUsePBO) {
if (bUsePBO) {
checkCudaErrors(cudaGraphicsResourceSetMapFlags(
pgres[currentRead], cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsResourceSetMapFlags(
pgres[1 - currentRead], cudaGraphicsMapFlagsWriteDiscard));
checkCudaErrors(cudaGraphicsMapResources(2, pgres, 0));
size_t bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[currentRead]), &bytes,
pgres[currentRead]));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[1 - currentRead]), &bytes,
pgres[1 - currentRead]));
}
for (unsigned int dev = 0; dev != numDevices; dev++) {
if (numDevices > 1) {
cudaSetDevice(dev);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO)
{
if (bUsePBO) {
checkCudaErrors(cudaGraphicsResourceSetMapFlags(pgres[currentRead], cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsResourceSetMapFlags(pgres[1 - currentRead], cudaGraphicsMapFlagsWriteDiscard));
checkCudaErrors(cudaGraphicsMapResources(2, pgres, 0));
size_t bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[currentRead]), &bytes, pgres[currentRead]));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[1 - currentRead]), &bytes, pgres[1 - currentRead]));
}
int numBlocks = (deviceData[dev].numBodies + blockSize - 1) / blockSize;
int numTiles = (numBodies + blockSize - 1) / blockSize;
int sharedMemSize = blockSize * 4 * sizeof(T); // 4 floats for pos
for (unsigned int dev = 0; dev != numDevices; dev++) {
if (numDevices > 1) {
cudaSetDevice(dev);
}
integrateBodies<T><<<numBlocks, blockSize, sharedMemSize>>>(
(typename vec4<T>::Type *)deviceData[dev].dPos[1 - currentRead],
(typename vec4<T>::Type *)deviceData[dev].dPos[currentRead],
(typename vec4<T>::Type *)deviceData[dev].dVel, deviceData[dev].offset,
deviceData[dev].numBodies, deltaTime, damping, numTiles);
int numBlocks = (deviceData[dev].numBodies + blockSize - 1) / blockSize;
int numTiles = (numBodies + blockSize - 1) / blockSize;
int sharedMemSize = blockSize * 4 * sizeof(T); // 4 floats for pos
integrateBodies<T>
<<<numBlocks, blockSize, sharedMemSize>>>((typename vec4<T>::Type *)deviceData[dev].dPos[1 - currentRead],
(typename vec4<T>::Type *)deviceData[dev].dPos[currentRead],
(typename vec4<T>::Type *)deviceData[dev].dVel,
deviceData[dev].offset,
deviceData[dev].numBodies,
deltaTime,
damping,
numTiles);
if (numDevices > 1) {
checkCudaErrors(cudaEventRecord(deviceData[dev].event));
// MJH: Hack on older driver versions to force kernel launches to flush!
cudaStreamQuery(0);
}
// check if kernel invocation generated an error
getLastCudaError("Kernel execution failed");
}
if (numDevices > 1) {
checkCudaErrors(cudaEventRecord(deviceData[dev].event));
// MJH: Hack on older driver versions to force kernel launches to flush!
cudaStreamQuery(0);
for (unsigned int dev = 0; dev < numDevices; dev++) {
checkCudaErrors(cudaEventSynchronize(deviceData[dev].event));
}
}
// check if kernel invocation generated an error
getLastCudaError("Kernel execution failed");
}
if (numDevices > 1) {
for (unsigned int dev = 0; dev < numDevices; dev++) {
checkCudaErrors(cudaEventSynchronize(deviceData[dev].event));
if (bUsePBO) {
checkCudaErrors(cudaGraphicsUnmapResources(2, pgres, 0));
}
}
if (bUsePBO) {
checkCudaErrors(cudaGraphicsUnmapResources(2, pgres, 0));
}
}
// Explicit specializations needed to generate code
template void integrateNbodySystem<float>(DeviceData<float> *deviceData,
template void integrateNbodySystem<float>(DeviceData<float> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead,
float deltaTime, float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize, bool bUsePBO);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO);
template void integrateNbodySystem<double>(DeviceData<double> *deviceData,
template void integrateNbodySystem<double>(DeviceData<double> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead,
float deltaTime, float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize, bool bUsePBO);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO);

View File

@@ -30,70 +30,71 @@
#include "bodysystem.h"
template <typename T>
struct DeviceData {
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
template <typename T> struct DeviceData
{
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
};
// CUDA BodySystem: runs on the GPU
template <typename T>
class BodySystemCUDA : public BodySystem<T> {
public:
BodySystemCUDA(unsigned int numBodies, unsigned int numDevices,
unsigned int blockSize, bool usePBO, bool useSysMem = false);
virtual ~BodySystemCUDA();
template <typename T> class BodySystemCUDA : public BodySystem<T>
{
public:
BodySystemCUDA(unsigned int numBodies,
unsigned int numDevices,
unsigned int blockSize,
bool usePBO,
bool useSysMem = false);
virtual ~BodySystemCUDA();
virtual void loadTipsyFile(const std::string &filename);
virtual void loadTipsyFile(const std::string &filename);
virtual void update(T deltaTime);
virtual void update(T deltaTime);
virtual void setSoftening(T softening);
virtual void setDamping(T damping);
virtual void setSoftening(T softening);
virtual void setDamping(T damping);
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual unsigned int getCurrentReadBuffer() const {
return m_pbo[m_currentRead];
}
virtual unsigned int getCurrentReadBuffer() const { return m_pbo[m_currentRead]; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
protected: // methods
BodySystemCUDA() {}
protected: // methods
BodySystemCUDA() {}
virtual void _initialize(int numBodies);
virtual void _finalize();
virtual void _initialize(int numBodies);
virtual void _finalize();
protected: // data
unsigned int m_numBodies;
unsigned int m_numDevices;
bool m_bInitialized;
protected: // data
unsigned int m_numBodies;
unsigned int m_numDevices;
bool m_bInitialized;
// Host data
T *m_hPos[2];
T *m_hVel;
// Host data
T *m_hPos[2];
T *m_hVel;
DeviceData<T> *m_deviceData;
DeviceData<T> *m_deviceData;
bool m_bUsePBO;
bool m_bUseSysMem;
unsigned int m_SMVersion;
bool m_bUsePBO;
bool m_bUseSysMem;
unsigned int m_SMVersion;
T m_damping;
T m_damping;
unsigned int m_pbo[2];
cudaGraphicsResource *m_pGRes[2];
unsigned int m_currentRead;
unsigned int m_currentWrite;
unsigned int m_pbo[2];
cudaGraphicsResource *m_pGRes[2];
unsigned int m_currentRead;
unsigned int m_currentWrite;
unsigned int m_blockSize;
unsigned int m_blockSize;
};
#include "bodysystemcuda_impl.h"
#endif // __BODYSYSTEMCUDA_H__
#endif // __BODYSYSTEMCUDA_H__

View File

@@ -25,25 +25,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <helper_cuda.h>
#include <algorithm>
#include <assert.h>
#include <math.h>
#include <memory.h>
#include <cstdio>
#include <cstdlib>
#include <helper_cuda.h>
#include <math.h>
#include <memory.h>
#include <vector>
#include <algorithm>
//#include <GL/glew.h>
// #include <GL/glew.h>
#include <cuda_gl_interop.h>
template <typename T>
void integrateNbodySystem(DeviceData<T> *deviceData,
void integrateNbodySystem(DeviceData<T> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead, float deltaTime,
float damping, unsigned int numBodies,
unsigned int numDevices, int blockSize, bool bUsePBO);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO);
cudaError_t setSofteningSquared(float softeningSq);
cudaError_t setSofteningSquared(double softeningSq);
@@ -51,323 +54,323 @@ cudaError_t setSofteningSquared(double softeningSq);
template <typename T>
BodySystemCUDA<T>::BodySystemCUDA(unsigned int numBodies,
unsigned int numDevices,
unsigned int blockSize, bool usePBO,
bool useSysMem)
: m_numBodies(numBodies),
m_numDevices(numDevices),
m_bInitialized(false),
m_bUsePBO(usePBO),
m_bUseSysMem(useSysMem),
m_currentRead(0),
m_currentWrite(1),
m_blockSize(blockSize) {
m_hPos[0] = m_hPos[1] = 0;
m_hVel = 0;
unsigned int blockSize,
bool usePBO,
bool useSysMem)
: m_numBodies(numBodies)
, m_numDevices(numDevices)
, m_bInitialized(false)
, m_bUsePBO(usePBO)
, m_bUseSysMem(useSysMem)
, m_currentRead(0)
, m_currentWrite(1)
, m_blockSize(blockSize)
{
m_hPos[0] = m_hPos[1] = 0;
m_hVel = 0;
m_deviceData = 0;
m_deviceData = 0;
_initialize(numBodies);
setSoftening(0.00125f);
setDamping(0.995f);
_initialize(numBodies);
setSoftening(0.00125f);
setDamping(0.995f);
}
template <typename T>
BodySystemCUDA<T>::~BodySystemCUDA() {
_finalize();
m_numBodies = 0;
template <typename T> BodySystemCUDA<T>::~BodySystemCUDA()
{
_finalize();
m_numBodies = 0;
}
template <typename T>
void BodySystemCUDA<T>::_initialize(int numBodies) {
assert(!m_bInitialized);
template <typename T> void BodySystemCUDA<T>::_initialize(int numBodies)
{
assert(!m_bInitialized);
m_numBodies = numBodies;
m_numBodies = numBodies;
unsigned int memSize = sizeof(T) * 4 * numBodies;
unsigned int memSize = sizeof(T) * 4 * numBodies;
m_deviceData = new DeviceData<T>[m_numDevices];
m_deviceData = new DeviceData<T>[m_numDevices];
// divide up the workload amongst Devices
float *weights = new float[m_numDevices];
int *numSms = new int[m_numDevices];
float total = 0;
for (unsigned int i = 0; i < m_numDevices; i++) {
cudaDeviceProp props;
checkCudaErrors(cudaGetDeviceProperties(&props, i));
// Choose the weight based on the Compute Capability
// We estimate that a CC2.0 SM is about 4.0x faster than a CC 1.x SM for
// this application (since a 15-SM GF100 is about 2X faster than a 30-SM
// GT200).
numSms[i] = props.multiProcessorCount;
weights[i] = numSms[i] * (props.major >= 2 ? 4.f : 1.f);
total += weights[i];
}
unsigned int offset = 0;
unsigned int remaining = m_numBodies;
for (unsigned int i = 0; i < m_numDevices; i++) {
unsigned int count = (int)((weights[i] / total) * m_numBodies);
unsigned int round = numSms[i] * 256;
count = round * ((count + round - 1) / round);
if (count > remaining) {
count = remaining;
}
remaining -= count;
m_deviceData[i].offset = offset;
m_deviceData[i].numBodies = count;
offset += count;
if ((i == m_numDevices - 1) && (offset < m_numBodies - 1)) {
m_deviceData[i].numBodies += m_numBodies - offset;
}
}
delete[] weights;
delete[] numSms;
if (m_bUseSysMem) {
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[0], memSize,
cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[1], memSize,
cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hVel, memSize,
cudaHostAllocMapped | cudaHostAllocPortable));
memset(m_hPos[0], 0, memSize);
memset(m_hPos[1], 0, memSize);
memset(m_hVel, 0, memSize);
// divide up the workload amongst Devices
float *weights = new float[m_numDevices];
int *numSms = new int[m_numDevices];
float total = 0;
for (unsigned int i = 0; i < m_numDevices; i++) {
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
cudaDeviceProp props;
checkCudaErrors(cudaGetDeviceProperties(&props, i));
checkCudaErrors(cudaEventCreate(&m_deviceData[i].event));
checkCudaErrors(cudaHostGetDevicePointer(
(void **)&m_deviceData[i].dPos[0], (void *)m_hPos[0], 0));
checkCudaErrors(cudaHostGetDevicePointer(
(void **)&m_deviceData[i].dPos[1], (void *)m_hPos[1], 0));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dVel,
(void *)m_hVel, 0));
// Choose the weight based on the Compute Capability
// We estimate that a CC2.0 SM is about 4.0x faster than a CC 1.x SM for
// this application (since a 15-SM GF100 is about 2X faster than a 30-SM
// GT200).
numSms[i] = props.multiProcessorCount;
weights[i] = numSms[i] * (props.major >= 2 ? 4.f : 1.f);
total += weights[i];
}
} else {
m_hPos[0] = new T[m_numBodies * 4];
m_hVel = new T[m_numBodies * 4];
memset(m_hPos[0], 0, memSize);
memset(m_hVel, 0, memSize);
unsigned int offset = 0;
unsigned int remaining = m_numBodies;
checkCudaErrors(cudaEventCreate(&m_deviceData[0].event));
for (unsigned int i = 0; i < m_numDevices; i++) {
unsigned int count = (int)((weights[i] / total) * m_numBodies);
unsigned int round = numSms[i] * 256;
count = round * ((count + round - 1) / round);
if (m_bUsePBO) {
// create the position pixel buffer objects for rendering
// we will actually compute directly from this memory in CUDA too
glGenBuffers(2, (GLuint *)m_pbo);
for (int i = 0; i < 2; ++i) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[i]);
glBufferData(GL_ARRAY_BUFFER, memSize, m_hPos[0], GL_DYNAMIC_DRAW);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != memSize) {
fprintf(stderr, "WARNING: Pixel Buffer Object allocation failed!n");
if (count > remaining) {
count = remaining;
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&m_pGRes[i], m_pbo[i],
cudaGraphicsMapFlagsNone));
}
} else {
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[0], memSize));
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[1], memSize));
remaining -= count;
m_deviceData[i].offset = offset;
m_deviceData[i].numBodies = count;
offset += count;
if ((i == m_numDevices - 1) && (offset < m_numBodies - 1)) {
m_deviceData[i].numBodies += m_numBodies - offset;
}
}
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dVel, memSize));
}
delete[] weights;
delete[] numSms;
m_bInitialized = true;
if (m_bUseSysMem) {
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[0], memSize, cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[1], memSize, cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hVel, memSize, cudaHostAllocMapped | cudaHostAllocPortable));
memset(m_hPos[0], 0, memSize);
memset(m_hPos[1], 0, memSize);
memset(m_hVel, 0, memSize);
for (unsigned int i = 0; i < m_numDevices; i++) {
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
checkCudaErrors(cudaEventCreate(&m_deviceData[i].event));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dPos[0], (void *)m_hPos[0], 0));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dPos[1], (void *)m_hPos[1], 0));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dVel, (void *)m_hVel, 0));
}
}
else {
m_hPos[0] = new T[m_numBodies * 4];
m_hVel = new T[m_numBodies * 4];
memset(m_hPos[0], 0, memSize);
memset(m_hVel, 0, memSize);
checkCudaErrors(cudaEventCreate(&m_deviceData[0].event));
if (m_bUsePBO) {
// create the position pixel buffer objects for rendering
// we will actually compute directly from this memory in CUDA too
glGenBuffers(2, (GLuint *)m_pbo);
for (int i = 0; i < 2; ++i) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[i]);
glBufferData(GL_ARRAY_BUFFER, memSize, m_hPos[0], GL_DYNAMIC_DRAW);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != memSize) {
fprintf(stderr, "WARNING: Pixel Buffer Object allocation failed!n");
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&m_pGRes[i], m_pbo[i], cudaGraphicsMapFlagsNone));
}
}
else {
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[0], memSize));
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[1], memSize));
}
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dVel, memSize));
}
m_bInitialized = true;
}
template <typename T>
void BodySystemCUDA<T>::_finalize() {
assert(m_bInitialized);
template <typename T> void BodySystemCUDA<T>::_finalize()
{
assert(m_bInitialized);
if (m_bUseSysMem) {
checkCudaErrors(cudaFreeHost(m_hPos[0]));
checkCudaErrors(cudaFreeHost(m_hPos[1]));
checkCudaErrors(cudaFreeHost(m_hVel));
if (m_bUseSysMem) {
checkCudaErrors(cudaFreeHost(m_hPos[0]));
checkCudaErrors(cudaFreeHost(m_hPos[1]));
checkCudaErrors(cudaFreeHost(m_hVel));
for (unsigned int i = 0; i < m_numDevices; i++) {
cudaEventDestroy(m_deviceData[i].event);
}
}
else {
delete[] m_hPos[0];
delete[] m_hPos[1];
delete[] m_hVel;
checkCudaErrors(cudaFree((void **)m_deviceData[0].dVel));
if (m_bUsePBO) {
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[0]));
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[1]));
glDeleteBuffers(2, (const GLuint *)m_pbo);
}
else {
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[0]));
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[1]));
}
}
delete[] m_deviceData;
m_bInitialized = false;
}
template <typename T> void BodySystemCUDA<T>::loadTipsyFile(const std::string &filename)
{
if (m_bInitialized)
_finalize();
std::vector<typename vec4<T>::Type> positions;
std::vector<typename vec4<T>::Type> velocities;
std::vector<int> ids;
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst, nSecond, nThird);
_initialize(nBodies);
setArray(BODYSYSTEM_POSITION, (T *)&positions[0]);
setArray(BODYSYSTEM_VELOCITY, (T *)&velocities[0]);
}
template <typename T> void BodySystemCUDA<T>::setSoftening(T softening)
{
T softeningSq = softening * softening;
for (unsigned int i = 0; i < m_numDevices; i++) {
cudaEventDestroy(m_deviceData[i].event);
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
checkCudaErrors(setSofteningSquared(softeningSq));
}
} else {
delete[] m_hPos[0];
delete[] m_hPos[1];
delete[] m_hVel;
checkCudaErrors(cudaFree((void **)m_deviceData[0].dVel));
if (m_bUsePBO) {
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[0]));
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[1]));
glDeleteBuffers(2, (const GLuint *)m_pbo);
} else {
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[0]));
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[1]));
}
}
delete[] m_deviceData;
m_bInitialized = false;
}
template <typename T>
void BodySystemCUDA<T>::loadTipsyFile(const std::string &filename) {
if (m_bInitialized) _finalize();
template <typename T> void BodySystemCUDA<T>::setDamping(T damping) { m_damping = damping; }
std::vector<typename vec4<T>::Type> positions;
std::vector<typename vec4<T>::Type> velocities;
std::vector<int> ids;
template <typename T> void BodySystemCUDA<T>::update(T deltaTime)
{
assert(m_bInitialized);
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
integrateNbodySystem<T>(m_deviceData,
m_pGRes,
m_currentRead,
(float)deltaTime,
(float)m_damping,
m_numBodies,
m_numDevices,
m_blockSize,
m_bUsePBO);
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst,
nSecond, nThird);
_initialize(nBodies);
setArray(BODYSYSTEM_POSITION, (T *)&positions[0]);
setArray(BODYSYSTEM_VELOCITY, (T *)&velocities[0]);
std::swap(m_currentRead, m_currentWrite);
}
template <typename T>
void BodySystemCUDA<T>::setSoftening(T softening) {
T softeningSq = softening * softening;
template <typename T> T *BodySystemCUDA<T>::getArray(BodyArray array)
{
assert(m_bInitialized);
for (unsigned int i = 0; i < m_numDevices; i++) {
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
T *hdata = 0;
T *ddata = 0;
checkCudaErrors(setSofteningSquared(softeningSq));
}
}
cudaGraphicsResource *pgres = NULL;
template <typename T>
void BodySystemCUDA<T>::setDamping(T damping) {
m_damping = damping;
}
int currentReadHost = m_bUseSysMem ? m_currentRead : 0;
template <typename T>
void BodySystemCUDA<T>::update(T deltaTime) {
assert(m_bInitialized);
integrateNbodySystem<T>(m_deviceData, m_pGRes, m_currentRead,
(float)deltaTime, (float)m_damping, m_numBodies,
m_numDevices, m_blockSize, m_bUsePBO);
std::swap(m_currentRead, m_currentWrite);
}
template <typename T>
T *BodySystemCUDA<T>::getArray(BodyArray array) {
assert(m_bInitialized);
T *hdata = 0;
T *ddata = 0;
cudaGraphicsResource *pgres = NULL;
int currentReadHost = m_bUseSysMem ? m_currentRead : 0;
switch (array) {
switch (array) {
default:
case BODYSYSTEM_POSITION:
hdata = m_hPos[currentReadHost];
ddata = m_deviceData[0].dPos[m_currentRead];
hdata = m_hPos[currentReadHost];
ddata = m_deviceData[0].dPos[m_currentRead];
if (m_bUsePBO) {
pgres = m_pGRes[m_currentRead];
}
break;
case BODYSYSTEM_VELOCITY:
hdata = m_hVel;
ddata = m_deviceData[0].dVel;
break;
}
if (!m_bUseSysMem) {
if (pgres) {
checkCudaErrors(
cudaGraphicsResourceSetMapFlags(pgres, cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsMapResources(1, &pgres, 0));
size_t bytes;
checkCudaErrors(
cudaGraphicsResourceGetMappedPointer((void **)&ddata, &bytes, pgres));
}
checkCudaErrors(cudaMemcpy(hdata, ddata, m_numBodies * 4 * sizeof(T),
cudaMemcpyDeviceToHost));
if (pgres) {
checkCudaErrors(cudaGraphicsUnmapResources(1, &pgres, 0));
}
}
return hdata;
}
template <typename T>
void BodySystemCUDA<T>::setArray(BodyArray array, const T *data) {
assert(m_bInitialized);
m_currentRead = 0;
m_currentWrite = 1;
switch (array) {
default:
case BODYSYSTEM_POSITION: {
if (m_bUsePBO) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[m_currentRead]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(T) * m_numBodies, data);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != 4 * (sizeof(T) * m_numBodies)) {
fprintf(stderr, "WARNING: Pixel Buffer Object download failed!n");
if (m_bUsePBO) {
pgres = m_pGRes[m_currentRead];
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
} else {
if (m_bUseSysMem) {
memcpy(m_hPos[m_currentRead], data, m_numBodies * 4 * sizeof(T));
} else
checkCudaErrors(cudaMemcpy(m_deviceData[0].dPos[m_currentRead], data,
m_numBodies * 4 * sizeof(T),
cudaMemcpyHostToDevice));
}
break;
case BODYSYSTEM_VELOCITY:
hdata = m_hVel;
ddata = m_deviceData[0].dVel;
break;
}
if (!m_bUseSysMem) {
if (pgres) {
checkCudaErrors(cudaGraphicsResourceSetMapFlags(pgres, cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsMapResources(1, &pgres, 0));
size_t bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&ddata, &bytes, pgres));
}
checkCudaErrors(cudaMemcpy(hdata, ddata, m_numBodies * 4 * sizeof(T), cudaMemcpyDeviceToHost));
if (pgres) {
checkCudaErrors(cudaGraphicsUnmapResources(1, &pgres, 0));
}
}
return hdata;
}
template <typename T> void BodySystemCUDA<T>::setArray(BodyArray array, const T *data)
{
assert(m_bInitialized);
m_currentRead = 0;
m_currentWrite = 1;
switch (array) {
default:
case BODYSYSTEM_POSITION: {
if (m_bUsePBO) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[m_currentRead]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(T) * m_numBodies, data);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != 4 * (sizeof(T) * m_numBodies)) {
fprintf(stderr, "WARNING: Pixel Buffer Object download failed!n");
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
else {
if (m_bUseSysMem) {
memcpy(m_hPos[m_currentRead], data, m_numBodies * 4 * sizeof(T));
}
else
checkCudaErrors(cudaMemcpy(
m_deviceData[0].dPos[m_currentRead], data, m_numBodies * 4 * sizeof(T), cudaMemcpyHostToDevice));
}
} break;
case BODYSYSTEM_VELOCITY:
if (m_bUseSysMem) {
memcpy(m_hVel, data, m_numBodies * 4 * sizeof(T));
} else
checkCudaErrors(cudaMemcpy(m_deviceData[0].dVel, data,
m_numBodies * 4 * sizeof(T),
cudaMemcpyHostToDevice));
if (m_bUseSysMem) {
memcpy(m_hVel, data, m_numBodies * 4 * sizeof(T));
}
else
checkCudaErrors(
cudaMemcpy(m_deviceData[0].dVel, data, m_numBodies * 4 * sizeof(T), cudaMemcpyHostToDevice));
break;
}
break;
}
}

View File

@@ -27,294 +27,294 @@
#include "render_particles.h"
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>
#include <helper_cuda.h>
#include <math.h>
#include <assert.h>
#include <cuda_gl_interop.h>
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include <math.h>
void mat_identity(matrix4 m) {
m[0][1] = m[0][2] = m[0][3] = m[1][0] = m[1][2] = m[1][3] = m[2][0] =
m[2][1] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
void mat_identity(matrix4 m)
{
m[0][1] = m[0][2] = m[0][3] = m[1][0] = m[1][2] = m[1][3] = m[2][0] = m[2][1] = m[2][3] = m[3][0] = m[3][1] =
m[3][2] = 0.0f;
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
}
void mat_multiply(matrix4 m0, matrix4 m1) {
float m[4];
void mat_multiply(matrix4 m0, matrix4 m1)
{
float m[4];
for (int r = 0; r < 4; r++) {
m[0] = m[1] = m[2] = m[3] = 0.0f;
for (int r = 0; r < 4; r++) {
m[0] = m[1] = m[2] = m[3] = 0.0f;
for (int c = 0; c < 4; c++) {
for (int i = 0; i < 4; i++) {
m[c] += m0[i][r] * m1[c][i];
}
for (int c = 0; c < 4; c++) {
for (int i = 0; i < 4; i++) {
m[c] += m0[i][r] * m1[c][i];
}
}
for (int c = 0; c < 4; c++) {
m0[c][r] = m[c];
}
}
for (int c = 0; c < 4; c++) {
m0[c][r] = m[c];
}
}
}
void mat_translate(matrix4 m, vector3 v) {
matrix4 m2;
m2[0][0] = m2[1][1] = m2[2][2] = m2[3][3] = 1.0f;
m2[0][1] = m2[0][2] = m2[0][3] = m2[1][0] = m2[1][2] = m2[1][3] = m2[2][0] =
m2[2][1] = m2[2][3] = 0.0f;
m2[3][0] = v[0];
m2[3][1] = v[1];
m2[3][2] = v[2];
mat_multiply(m, m2);
void mat_translate(matrix4 m, vector3 v)
{
matrix4 m2;
m2[0][0] = m2[1][1] = m2[2][2] = m2[3][3] = 1.0f;
m2[0][1] = m2[0][2] = m2[0][3] = m2[1][0] = m2[1][2] = m2[1][3] = m2[2][0] = m2[2][1] = m2[2][3] = 0.0f;
m2[3][0] = v[0];
m2[3][1] = v[1];
m2[3][2] = v[2];
mat_multiply(m, m2);
}
void mat_perspective(matrix4 m, GLfloat fovy, GLfloat aspect, GLfloat znear,
GLfloat zfar) {
matrix4 m2;
m2[1][0] = m2[2][0] = m2[3][0] = m2[0][1] = m2[2][1] = m2[3][1] = m2[0][2] =
m2[1][2] = m2[0][3] = m2[1][3] = m2[3][3] = 0.0f;
m2[2][3] = -1.0f;
void mat_perspective(matrix4 m, GLfloat fovy, GLfloat aspect, GLfloat znear, GLfloat zfar)
{
matrix4 m2;
m2[1][0] = m2[2][0] = m2[3][0] = m2[0][1] = m2[2][1] = m2[3][1] = m2[0][2] = m2[1][2] = m2[0][3] = m2[1][3] =
m2[3][3] = 0.0f;
m2[2][3] = -1.0f;
float f = 1 / tan((fovy * M_PI / 180) / 2);
m2[0][0] = f / aspect;
m2[1][1] = f;
float f = 1 / tan((fovy * M_PI / 180) / 2);
m2[0][0] = f / aspect;
m2[1][1] = f;
m2[2][2] = ((znear + zfar) / (znear - zfar));
m2[3][2] = ((2 * znear * zfar) / (znear - zfar));
m2[2][2] = ((znear + zfar) / (znear - zfar));
m2[3][2] = ((2 * znear * zfar) / (znear - zfar));
mat_multiply(m, m2);
mat_multiply(m, m2);
}
ParticleRenderer::ParticleRenderer(unsigned int windowWidth,
unsigned int windowHeight)
: m_pos(0),
m_numParticles(0),
m_pointSize(1.0f),
m_spriteSize(2.0f),
m_vertexShader(0),
m_vertexShaderPoints(0),
m_fragmentShader(0),
m_programPoints(0),
m_programSprites(0),
m_texture(0),
m_pbo(0),
m_vboColor(0),
m_windowWidth(windowWidth),
m_windowHeight(windowHeight),
m_bFp64Positions(false) {
m_camera[0] = 0;
m_camera[1] = 0;
m_camera[2] = 0;
_initGL();
ParticleRenderer::ParticleRenderer(unsigned int windowWidth, unsigned int windowHeight)
: m_pos(0)
, m_numParticles(0)
, m_pointSize(1.0f)
, m_spriteSize(2.0f)
, m_vertexShader(0)
, m_vertexShaderPoints(0)
, m_fragmentShader(0)
, m_programPoints(0)
, m_programSprites(0)
, m_texture(0)
, m_pbo(0)
, m_vboColor(0)
, m_windowWidth(windowWidth)
, m_windowHeight(windowHeight)
, m_bFp64Positions(false)
{
m_camera[0] = 0;
m_camera[1] = 0;
m_camera[2] = 0;
_initGL();
}
ParticleRenderer::~ParticleRenderer() { m_pos = 0; }
void ParticleRenderer::resetPBO() { glDeleteBuffers(1, (GLuint *)&m_pbo); }
void ParticleRenderer::setPositions(float *pos, int numParticles) {
m_pos = pos;
m_numParticles = numParticles;
void ParticleRenderer::setPositions(float *pos, int numParticles)
{
m_pos = pos;
m_numParticles = numParticles;
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), pos,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle float position");
}
void ParticleRenderer::setPositions(double *pos, int numParticles) {
m_bFp64Positions = true;
m_pos_fp64 = pos;
m_numParticles = numParticles;
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(double), pos,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle double position");
}
void ParticleRenderer::setColors(float *color, int numParticles) {
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), color,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void ParticleRenderer::setBaseColor(float color[4]) {
for (int i = 0; i < 4; i++) m_baseColor[i] = color[i];
}
void ParticleRenderer::setPBO(unsigned int pbo, int numParticles, bool fp64) {
m_pbo = pbo;
m_numParticles = numParticles;
if (fp64) m_bFp64Positions = true;
}
void ParticleRenderer::display() {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(GL_FALSE);
glUseProgram(m_programSprites);
// Set modelview and projection matrices
GLint h_ModelViewMatrix = glGetUniformLocation(m_programSprites, "modelview");
GLint h_ProjectionMatrix =
glGetUniformLocation(m_programSprites, "projection");
matrix4 modelview;
matrix4 projection;
mat_identity(modelview);
mat_identity(projection);
mat_translate(modelview, m_camera);
mat_perspective(projection, 60, (float)m_windowWidth / (float)m_windowHeight,
0.1, 1000.0);
glUniformMatrix4fv(h_ModelViewMatrix, 1, GL_FALSE, (GLfloat *)modelview);
glUniformMatrix4fv(h_ProjectionMatrix, 1, GL_FALSE, (GLfloat *)projection);
// Set point size
GLint h_PointSize = glGetUniformLocation(m_programSprites, "size");
glUniform1f(h_PointSize, m_spriteSize);
// Set base and secondary colors
GLint h_BaseColor = glGetUniformLocation(m_programSprites, "baseColor");
GLint h_SecondaryColor =
glGetUniformLocation(m_programSprites, "secondaryColor");
glUniform4f(h_BaseColor, 1.0, 1.0, 1.0, 1.0);
glUniform4f(h_SecondaryColor, m_baseColor[0], m_baseColor[1], m_baseColor[2],
m_baseColor[3]);
// Set position coords
GLint h_position = glGetAttribLocation(m_programSprites, "a_position");
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glEnableVertexAttribArray(h_position);
glVertexAttribPointer(h_position, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLuint texLoc = glGetUniformLocation(m_programSprites, "splatTexture");
glUniform1i(texLoc, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_POINTS, 0, m_numParticles);
glDisableVertexAttribArray(h_position);
glUseProgram(0);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
}
const char vertexShader[] = {
"attribute vec4 a_position;"
"uniform mat4 projection;"
"uniform mat4 modelview;"
"uniform float size;"
"void main()"
"{"
"float pointSize = 500.0 * size;"
"vec4 vert = a_position;"
"vert.w = 1.0;"
"vec3 pos_eye = vec3(modelview * vert);"
"gl_PointSize = max(1.0, pointSize / (1.0 - pos_eye.z));"
"gl_Position = projection * modelview * a_position;"
"}"};
const char fragmentShader[] = {
"uniform sampler2D splatTexture;"
"uniform lowp vec4 baseColor;"
"uniform lowp vec4 secondaryColor;"
"void main()"
"{"
"lowp vec4 textureColor = (0.6 + 0.4 * baseColor) * "
"texture2D(splatTexture, gl_PointCoord);"
"gl_FragColor = textureColor * secondaryColor;"
"}"};
// Checks if the shader is compiled.
static int CheckCompiled(GLuint shader) {
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (!isCompiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = (char *)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("Error compiling program:\n%s\n", infoLog);
free(infoLog);
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
return 0;
}
return 1;
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), pos, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle float position");
}
void ParticleRenderer::_initGL() {
m_vertexShader = glCreateShader(GL_VERTEX_SHADER);
m_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
void ParticleRenderer::setPositions(double *pos, int numParticles)
{
m_bFp64Positions = true;
m_pos_fp64 = pos;
m_numParticles = numParticles;
const char *v = vertexShader;
const char *f = fragmentShader;
glShaderSource(m_vertexShader, 1, &v, 0);
glShaderSource(m_fragmentShader, 1, &f, 0);
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
checkGLErrors("Shader Source");
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(double), pos, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle double position");
}
glCompileShader(m_vertexShader);
glCompileShader(m_fragmentShader);
void ParticleRenderer::setColors(float *color, int numParticles)
{
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), color, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (!CheckCompiled(m_vertexShader) || !CheckCompiled(m_fragmentShader)) {
printf("A shader failed to compile.\n");
exit(1);
}
void ParticleRenderer::setBaseColor(float color[4])
{
for (int i = 0; i < 4; i++)
m_baseColor[i] = color[i];
}
m_programSprites = glCreateProgram();
void ParticleRenderer::setPBO(unsigned int pbo, int numParticles, bool fp64)
{
m_pbo = pbo;
m_numParticles = numParticles;
checkGLErrors("create program");
if (fp64)
m_bFp64Positions = true;
}
glAttachShader(m_programSprites, m_vertexShader);
glAttachShader(m_programSprites, m_fragmentShader);
void ParticleRenderer::display()
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(GL_FALSE);
checkGLErrors("attaching shaders");
glUseProgram(m_programSprites);
glLinkProgram(m_programSprites);
// Set modelview and projection matrices
GLint h_ModelViewMatrix = glGetUniformLocation(m_programSprites, "modelview");
GLint h_ProjectionMatrix = glGetUniformLocation(m_programSprites, "projection");
matrix4 modelview;
matrix4 projection;
mat_identity(modelview);
mat_identity(projection);
mat_translate(modelview, m_camera);
mat_perspective(projection, 60, (float)m_windowWidth / (float)m_windowHeight, 0.1, 1000.0);
glUniformMatrix4fv(h_ModelViewMatrix, 1, GL_FALSE, (GLfloat *)modelview);
glUniformMatrix4fv(h_ProjectionMatrix, 1, GL_FALSE, (GLfloat *)projection);
checkGLErrors("linking program");
// Set point size
GLint h_PointSize = glGetUniformLocation(m_programSprites, "size");
glUniform1f(h_PointSize, m_spriteSize);
EGLint linked;
glGetProgramiv(m_programSprites, GL_LINK_STATUS, &linked);
if (!linked) {
printf("A shader failed to link.\n");
exit(1);
}
// Set base and secondary colors
GLint h_BaseColor = glGetUniformLocation(m_programSprites, "baseColor");
GLint h_SecondaryColor = glGetUniformLocation(m_programSprites, "secondaryColor");
glUniform4f(h_BaseColor, 1.0, 1.0, 1.0, 1.0);
glUniform4f(h_SecondaryColor, m_baseColor[0], m_baseColor[1], m_baseColor[2], m_baseColor[3]);
_createTexture(32);
// Set position coords
GLint h_position = glGetAttribLocation(m_programSprites, "a_position");
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glEnableVertexAttribArray(h_position);
glVertexAttribPointer(h_position, 4, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, (GLuint *)&m_vboColor);
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, m_numParticles * 4 * sizeof(float), 0,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLuint texLoc = glGetUniformLocation(m_programSprites, "splatTexture");
glUniform1i(texLoc, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_POINTS, 0, m_numParticles);
glDisableVertexAttribArray(h_position);
glUseProgram(0);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
}
const char vertexShader[] = {"attribute vec4 a_position;"
"uniform mat4 projection;"
"uniform mat4 modelview;"
"uniform float size;"
"void main()"
"{"
"float pointSize = 500.0 * size;"
"vec4 vert = a_position;"
"vert.w = 1.0;"
"vec3 pos_eye = vec3(modelview * vert);"
"gl_PointSize = max(1.0, pointSize / (1.0 - pos_eye.z));"
"gl_Position = projection * modelview * a_position;"
"}"};
const char fragmentShader[] = {"uniform sampler2D splatTexture;"
"uniform lowp vec4 baseColor;"
"uniform lowp vec4 secondaryColor;"
"void main()"
"{"
"lowp vec4 textureColor = (0.6 + 0.4 * baseColor) * "
"texture2D(splatTexture, gl_PointCoord);"
"gl_FragColor = textureColor * secondaryColor;"
"}"};
// Checks if the shader is compiled.
static int CheckCompiled(GLuint shader)
{
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (!isCompiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = (char *)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("Error compiling program:\n%s\n", infoLog);
free(infoLog);
}
return 0;
}
return 1;
}
void ParticleRenderer::_initGL()
{
m_vertexShader = glCreateShader(GL_VERTEX_SHADER);
m_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const char *v = vertexShader;
const char *f = fragmentShader;
glShaderSource(m_vertexShader, 1, &v, 0);
glShaderSource(m_fragmentShader, 1, &f, 0);
checkGLErrors("Shader Source");
glCompileShader(m_vertexShader);
glCompileShader(m_fragmentShader);
if (!CheckCompiled(m_vertexShader) || !CheckCompiled(m_fragmentShader)) {
printf("A shader failed to compile.\n");
exit(1);
}
m_programSprites = glCreateProgram();
checkGLErrors("create program");
glAttachShader(m_programSprites, m_vertexShader);
glAttachShader(m_programSprites, m_fragmentShader);
checkGLErrors("attaching shaders");
glLinkProgram(m_programSprites);
checkGLErrors("linking program");
EGLint linked;
glGetProgramiv(m_programSprites, GL_LINK_STATUS, &linked);
if (!linked) {
printf("A shader failed to link.\n");
exit(1);
}
_createTexture(32);
glGenBuffers(1, (GLuint *)&m_vboColor);
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, m_numParticles * 4 * sizeof(float), 0, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//------------------------------------------------------------------------------
@@ -325,50 +325,53 @@ void ParticleRenderer::_initGL() {
* EvalHermite(float pA, float pB, float vA, float vB, float u)
* @brief Evaluates Hermite basis functions for the specified coefficients.
*/
inline float evalHermite(float pA, float pB, float vA, float vB, float u) {
float u2 = (u * u), u3 = u2 * u;
float B0 = 2 * u3 - 3 * u2 + 1;
float B1 = -2 * u3 + 3 * u2;
float B2 = u3 - 2 * u2 + u;
float B3 = u3 - u;
return (B0 * pA + B1 * pB + B2 * vA + B3 * vB);
inline float evalHermite(float pA, float pB, float vA, float vB, float u)
{
float u2 = (u * u), u3 = u2 * u;
float B0 = 2 * u3 - 3 * u2 + 1;
float B1 = -2 * u3 + 3 * u2;
float B2 = u3 - 2 * u2 + u;
float B3 = u3 - u;
return (B0 * pA + B1 * pB + B2 * vA + B3 * vB);
}
unsigned char *createGaussianMap(int N) {
float *M = new float[2 * N * N];
unsigned char *B = new unsigned char[4 * N * N];
float X, Y, Y2, Dist;
float Incr = 2.0f / N;
int i = 0;
int j = 0;
Y = -1.0f;
unsigned char *createGaussianMap(int N)
{
float *M = new float[2 * N * N];
unsigned char *B = new unsigned char[4 * N * N];
float X, Y, Y2, Dist;
float Incr = 2.0f / N;
int i = 0;
int j = 0;
Y = -1.0f;
// float mmax = 0;
for (int y = 0; y < N; y++, Y += Incr) {
Y2 = Y * Y;
X = -1.0f;
// float mmax = 0;
for (int y = 0; y < N; y++, Y += Incr) {
Y2 = Y * Y;
X = -1.0f;
for (int x = 0; x < N; x++, X += Incr, i += 2, j += 4) {
Dist = (float)sqrtf(X * X + Y2);
for (int x = 0; x < N; x++, X += Incr, i += 2, j += 4) {
Dist = (float)sqrtf(X * X + Y2);
if (Dist > 1) Dist = 1;
if (Dist > 1)
Dist = 1;
M[i + 1] = M[i] = evalHermite(1.0f, 0, 0, 0, Dist);
B[j + 3] = B[j + 2] = B[j + 1] = B[j] = (unsigned char)(M[i] * 255);
M[i + 1] = M[i] = evalHermite(1.0f, 0, 0, 0, Dist);
B[j + 3] = B[j + 2] = B[j + 1] = B[j] = (unsigned char)(M[i] * 255);
}
}
}
delete[] M;
return (B);
delete[] M;
return (B);
}
void ParticleRenderer::_createTexture(int resolution) {
unsigned char *data = createGaussianMap(resolution);
glGenTextures(1, (GLuint *)&m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR); //_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, resolution, resolution, 0, GL_RGBA,
GL_UNSIGNED_BYTE, data);
void ParticleRenderer::_createTexture(int resolution)
{
unsigned char *data = createGaussianMap(resolution);
glGenTextures(1, (GLuint *)&m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR); //_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, resolution, resolution, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}

View File

@@ -31,80 +31,76 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl31.h>
#include <cstdio>
typedef float matrix4[4][4];
typedef float vector3[3];
// check for OpenGL errors
inline void checkGLErrors(const char *s) {
EGLenum error;
inline void checkGLErrors(const char *s)
{
EGLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "%s: error - %d\n", s, error);
}
while ((error = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "%s: error - %d\n", s, error);
}
}
class ParticleRenderer {
public:
ParticleRenderer(unsigned int windowWidth = 720,
unsigned int windowHeight = 480);
~ParticleRenderer();
class ParticleRenderer
{
public:
ParticleRenderer(unsigned int windowWidth = 720, unsigned int windowHeight = 480);
~ParticleRenderer();
void setPositions(float *pos, int numParticles);
void setPositions(double *pos, int numParticles);
void setBaseColor(float color[4]);
void setColors(float *color, int numParticles);
void setPBO(unsigned int pbo, int numParticles, bool fp64);
void setPositions(float *pos, int numParticles);
void setPositions(double *pos, int numParticles);
void setBaseColor(float color[4]);
void setColors(float *color, int numParticles);
void setPBO(unsigned int pbo, int numParticles, bool fp64);
enum DisplayMode {
PARTICLE_POINTS,
PARTICLE_SPRITES,
PARTICLE_SPRITES_COLOR,
PARTICLE_NUM_MODES
};
enum DisplayMode { PARTICLE_POINTS, PARTICLE_SPRITES, PARTICLE_SPRITES_COLOR, PARTICLE_NUM_MODES };
void display();
void display();
void setPointSize(float size) { m_pointSize = size; }
void setSpriteSize(float size) { m_spriteSize = size; }
void setPointSize(float size) { m_pointSize = size; }
void setSpriteSize(float size) { m_spriteSize = size; }
void setCameraPos(vector3 camera_pos) {
m_camera[0] = camera_pos[0];
m_camera[1] = camera_pos[1];
m_camera[2] = camera_pos[2];
}
void setCameraPos(vector3 camera_pos)
{
m_camera[0] = camera_pos[0];
m_camera[1] = camera_pos[1];
m_camera[2] = camera_pos[2];
}
void resetPBO();
void resetPBO();
protected: // methods
void _initGL();
void _createTexture(int resolution);
protected: // methods
void _initGL();
void _createTexture(int resolution);
protected: // data
float *m_pos;
double *m_pos_fp64;
int m_numParticles;
protected: // data
float *m_pos;
double *m_pos_fp64;
int m_numParticles;
float m_pointSize;
float m_spriteSize;
vector3 m_camera;
float m_pointSize;
float m_spriteSize;
vector3 m_camera;
unsigned int m_vertexShader;
unsigned int m_vertexShaderPoints;
unsigned int m_fragmentShader;
unsigned int m_programPoints;
unsigned int m_programSprites;
unsigned int m_texture;
unsigned int m_pbo;
unsigned int m_vboColor;
unsigned int m_windowWidth;
unsigned int m_windowHeight;
unsigned int m_vertexShader;
unsigned int m_vertexShaderPoints;
unsigned int m_fragmentShader;
unsigned int m_programPoints;
unsigned int m_programSprites;
unsigned int m_texture;
unsigned int m_pbo;
unsigned int m_vboColor;
unsigned int m_windowWidth;
unsigned int m_windowHeight;
float m_baseColor[4];
float m_baseColor[4];
bool m_bFp64Positions;
bool m_bFp64Positions;
};
#endif //__ RENDER_PARTICLES__
#endif //__ RENDER_PARTICLES__

View File

@@ -17,11 +17,11 @@ struct gas_particle
Real rho;
Real temp;
Real hsmooth;
Real metals ;
Real phi ;
} ;
Real metals;
Real phi;
};
//struct gas_particle *gas_particles;
// struct gas_particle *gas_particles;
struct dark_particle
{
@@ -29,45 +29,45 @@ struct dark_particle
Real pos[MAXDIM];
Real vel[MAXDIM];
Real eps;
int phi ;
} ;
int phi;
};
//struct dark_particle *dark_particles;
// struct dark_particle *dark_particles;
struct star_particle
{
Real mass;
Real pos[MAXDIM];
Real vel[MAXDIM];
Real metals ;
Real tform ;
Real metals;
Real tform;
Real eps;
int phi ;
} ;
int phi;
};
//struct star_particle *star_particles;
// struct star_particle *star_particles;
struct dump
{
double time ;
int nbodies ;
int ndim ;
int nsph ;
int ndark ;
int nstar ;
} ;
double time;
int nbodies;
int ndim;
int nsph;
int ndark;
int nstar;
};
typedef struct dump header ;
typedef struct dump header;
template <typename real4>
void read_tipsy_file(vector<real4> &bodyPositions,
vector<real4> &bodyVelocities,
vector<int> &bodiesIDs,
void read_tipsy_file(vector<real4> &bodyPositions,
vector<real4> &bodyVelocities,
vector<int> &bodiesIDs,
const std::string &fileName,
int &NTotal,
int &NFirst,
int &NSecond,
int &NThird)
int &NTotal,
int &NFirst,
int &NSecond,
int &NThird)
{
/*
Read in our custom version of the tipsy file format written by
@@ -82,59 +82,55 @@ void read_tipsy_file(vector<real4> &bodyPositions,
ifstream inputFile(fullFileName, ios::in | ios::binary);
if (!inputFile.is_open())
{
if (!inputFile.is_open()) {
cout << "Can't open input file \n";
exit(EXIT_SUCCESS);
}
dump h;
dump h;
inputFile.read((char *)&h, sizeof(h));
int idummy;
int idummy;
real4 positions;
real4 velocity;
//Read tipsy header
NTotal = h.nbodies;
NFirst = h.ndark;
NSecond = h.nstar;
NThird = h.nsph;
// Read tipsy header
NTotal = h.nbodies;
NFirst = h.ndark;
NSecond = h.nstar;
NThird = h.nsph;
//Start reading
// Start reading
int particleCount = 0;
dark_particle d;
star_particle s;
for (int i=0; i < NTotal; i++)
{
if (i < NFirst)
{
for (int i = 0; i < NTotal; i++) {
if (i < NFirst) {
inputFile.read((char *)&d, sizeof(d));
velocity.w = d.eps;
positions.w = d.mass;
positions.x = d.pos[0];
positions.y = d.pos[1];
positions.z = d.pos[2];
velocity.x = d.vel[0];
velocity.y = d.vel[1];
velocity.z = d.vel[2];
idummy = d.phi;
velocity.w = d.eps;
positions.w = d.mass;
positions.x = d.pos[0];
positions.y = d.pos[1];
positions.z = d.pos[2];
velocity.x = d.vel[0];
velocity.y = d.vel[1];
velocity.z = d.vel[2];
idummy = d.phi;
}
else
{
else {
inputFile.read((char *)&s, sizeof(s));
velocity.w = s.eps;
positions.w = s.mass;
positions.x = s.pos[0];
positions.y = s.pos[1];
positions.z = s.pos[2];
velocity.x = s.vel[0];
velocity.y = s.vel[1];
velocity.z = s.vel[2];
idummy = s.phi;
velocity.w = s.eps;
positions.w = s.mass;
positions.x = s.pos[0];
positions.y = s.pos[1];
positions.z = s.pos[2];
velocity.x = s.vel[0];
velocity.y = s.vel[1];
velocity.z = s.vel[2];
idummy = s.phi;
}
bodyPositions.push_back(positions);
@@ -142,18 +138,16 @@ void read_tipsy_file(vector<real4> &bodyPositions,
bodiesIDs.push_back(idummy);
particleCount++;
}//end for
} // end for
// round up to a multiple of 256 bodies since our kernel only supports that...
int newTotal = NTotal;
if (NTotal % 256)
{
if (NTotal % 256) {
newTotal = ((NTotal / 256) + 1) * 256;
}
for (int i = NTotal; i < newTotal; i++)
{
for (int i = NTotal; i < newTotal; i++) {
positions.w = positions.x = positions.y = positions.z = 0;
velocity.x = velocity.y = velocity.z = 0;
bodyPositions.push_back(positions);

View File

@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -26,45 +26,42 @@
*/
Display *display;
int screen;
Window win = 0;
int screen;
Window win = 0;
#include <GLES3/gl31.h>
//#include <GLES3/gl3ext.h> // not (yet) needed
// #include <GLES3/gl3ext.h> // not (yet) needed
#include <EGL/egl.h>
#include <EGL/eglext.h>
#define GET_GLERROR(ret) \
{ \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) \
{ \
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, \
err); \
fflush(stderr); \
\
switch (err) \
{ \
case GL_INVALID_ENUM: \
printf("GL_INVALID_ENUM\n"); \
break; \
case GL_INVALID_VALUE: \
printf("GL_INVALID_VALUE\n"); \
break; \
case GL_INVALID_OPERATION: \
printf("GL_INVALID_OPERATION\n"); \
break; \
case GL_OUT_OF_MEMORY: \
printf("GL_OUT_OF_MEMORY\n"); \
break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \
break; \
default: \
printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \
}; \
} \
}
#define GET_GLERROR(ret) \
{ \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, err); \
fflush(stderr); \
\
switch (err) { \
case GL_INVALID_ENUM: \
printf("GL_INVALID_ENUM\n"); \
break; \
case GL_INVALID_VALUE: \
printf("GL_INVALID_VALUE\n"); \
break; \
case GL_INVALID_OPERATION: \
printf("GL_INVALID_OPERATION\n"); \
break; \
case GL_OUT_OF_MEMORY: \
printf("GL_OUT_OF_MEMORY\n"); \
break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \
break; \
default: \
printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \
}; \
} \
}
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLSurface eglSurface = EGL_NO_SURFACE;
@@ -85,111 +82,128 @@ typedef GL_APICALL void (*GL_APIENTRY glGetProgramivTYPE) (GLuint program, GLenu
glGetProgramivTYPE my_glGetProgramiv;
#endif
int graphics_setup_window(int xpos, int ypos, int width, int height,
const char *windowname)
int graphics_setup_window(int xpos, int ypos, int width, int height, const char *windowname)
{
#ifdef USE_GL
// OpenGL 4.3 Core Profile creation through EGL - would be even available on
// desktop, but CUDA interop doesn't yet work for OpenGL context established
// through EGL
EGLint configAttrs[] = {EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1,
// EGL_DEPTH_SIZE, 16,
EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0, EGL_CONFORMANT,
EGL_OPENGL_BIT,
// EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
// EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, 1,
EGL_NONE};
EGLint contextAttrs[] = {// EGL_CONTEXT_MAJOR_VERSION_KHR, 4,
// EGL_CONTEXT_MINOR_VERSION_KHR, 3,
EGL_NONE};
// OpenGL 4.3 Core Profile creation through EGL - would be even available on
// desktop, but CUDA interop doesn't yet work for OpenGL context established
// through EGL
EGLint configAttrs[] = {EGL_RED_SIZE,
1,
EGL_GREEN_SIZE,
1,
EGL_BLUE_SIZE,
1,
// EGL_DEPTH_SIZE, 16,
EGL_SAMPLE_BUFFERS,
0,
EGL_SAMPLES,
0,
EGL_CONFORMANT,
EGL_OPENGL_BIT,
// EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
// EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, 1,
EGL_NONE};
EGLint contextAttrs[] = {// EGL_CONTEXT_MAJOR_VERSION_KHR, 4,
// EGL_CONTEXT_MINOR_VERSION_KHR, 3,
EGL_NONE};
#else // OpenGL ES 3.1
EGLint configAttrs[] = {
EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_DEPTH_SIZE, 16,
EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0,
// EGL_CONFORMANT, EGL_OPENGL_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // 3_BIT_KHR,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLint configAttrs[] = {EGL_RED_SIZE,
1,
EGL_GREEN_SIZE,
1,
EGL_BLUE_SIZE,
1,
EGL_DEPTH_SIZE,
16,
EGL_SAMPLE_BUFFERS,
0,
EGL_SAMPLES,
0,
// EGL_CONFORMANT, EGL_OPENGL_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT, // 3_BIT_KHR,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
#endif
EGLint windowAttrs[] = {EGL_NONE};
EGLConfig *configList = NULL;
EGLint configCount;
EGLint windowAttrs[] = {EGL_NONE};
EGLConfig *configList = NULL;
EGLint configCount;
display = XOpenDisplay(NULL);
if (!display)
error_exit("Error opening X display.\n");
display = XOpenDisplay(NULL);
if (!display)
error_exit("Error opening X display.\n");
screen = DefaultScreen(display);
screen = DefaultScreen(display);
eglDisplay = eglGetDisplay(display);
if (eglDisplay == EGL_NO_DISPLAY)
error_exit("EGL failed to obtain display\n");
eglDisplay = eglGetDisplay(display);
if (eglDisplay == EGL_NO_DISPLAY)
error_exit("EGL failed to obtain display\n");
if (!eglInitialize(eglDisplay, 0, 0))
error_exit("EGL failed to initialize\n");
if (!eglInitialize(eglDisplay, 0, 0))
error_exit("EGL failed to initialize\n");
if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) ||
!configCount)
error_exit("EGL failed to return any matching configurations\n");
if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) || !configCount)
error_exit("EGL failed to return any matching configurations\n");
configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig));
configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig));
if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount,
&configCount) ||
!configCount)
error_exit("EGL failed to populate configuration list\n");
if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount, &configCount) || !configCount)
error_exit("EGL failed to populate configuration list\n");
win = XCreateSimpleWindow(display, RootWindow(display, screen), xpos, ypos,
width, height, 0, BlackPixel(display, screen),
WhitePixel(display, screen));
win = XCreateSimpleWindow(display,
RootWindow(display, screen),
xpos,
ypos,
width,
height,
0,
BlackPixel(display, screen),
WhitePixel(display, screen));
XStoreName(display, win, windowname);
XStoreName(display, win, windowname);
XSelectInput(display, win,
ExposureMask | ButtonPressMask | KeyPressMask |
StructureNotifyMask | ButtonReleaseMask | KeyReleaseMask |
EnterWindowMask | LeaveWindowMask | PointerMotionMask |
Button1MotionMask | Button2MotionMask |
VisibilityChangeMask | ColormapChangeMask);
XSelectInput(display,
win,
ExposureMask | ButtonPressMask | KeyPressMask | StructureNotifyMask | ButtonReleaseMask
| KeyReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | Button1MotionMask
| Button2MotionMask | VisibilityChangeMask | ColormapChangeMask);
XMapWindow(display, win);
XMapWindow(display, win);
eglSurface = eglCreateWindowSurface(eglDisplay, configList[0],
(EGLNativeWindowType)win, windowAttrs);
if (!eglSurface)
error_exit("EGL couldn't create window\n");
eglSurface = eglCreateWindowSurface(eglDisplay, configList[0], (EGLNativeWindowType)win, windowAttrs);
if (!eglSurface)
error_exit("EGL couldn't create window\n");
#ifdef USE_GL
eglBindAPI(EGL_OPENGL_API);
eglBindAPI(EGL_OPENGL_API);
#else
eglBindAPI(EGL_OPENGL_ES_API);
eglBindAPI(EGL_OPENGL_ES_API);
#endif
eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs);
if (!eglContext)
error_exit("EGL couldn't create context\n");
eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs);
if (!eglContext)
error_exit("EGL couldn't create context\n");
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
error_exit("EGL couldn't make context/surface current\n");
if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
error_exit("EGL couldn't make context/surface current\n");
EGLint Context_RendererType;
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE,
&Context_RendererType);
EGLint Context_RendererType;
eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE, &Context_RendererType);
switch (Context_RendererType)
{
case EGL_OPENGL_API:
printf("Using OpenGL API\n");
break;
case EGL_OPENGL_ES_API:
printf("Using OpenGL ES API");
break;
case EGL_OPENVG_API:
error_exit("Context Query Returned OpenVG. This is Unsupported\n");
default:
error_exit("Unknown Context Type. %04X\n", Context_RendererType);
}
switch (Context_RendererType) {
case EGL_OPENGL_API:
printf("Using OpenGL API\n");
break;
case EGL_OPENGL_ES_API:
printf("Using OpenGL ES API");
break;
case EGL_OPENVG_API:
error_exit("Context Query Returned OpenVG. This is Unsupported\n");
default:
error_exit("Unknown Context Type. %04X\n", Context_RendererType);
}
#if 0 // obtain API function pointers _manually_ (see function pointer \
// declarations above)
@@ -207,33 +221,29 @@ int graphics_setup_window(int xpos, int ypos, int width, int height,
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
#endif
return 1;
return 1;
}
void graphics_set_windowtitle(const char *windowname)
{
XStoreName(display, win, windowname);
}
void graphics_set_windowtitle(const char *windowname) { XStoreName(display, win, windowname); }
void graphics_swap_buffers() { eglSwapBuffers(eglDisplay, eglSurface); }
void graphics_close_window()
{
if (eglDisplay != EGL_NO_DISPLAY)
{
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (eglContext != EGL_NO_CONTEXT)
eglDestroyContext(eglDisplay, eglContext);
if (eglContext != EGL_NO_CONTEXT)
eglDestroyContext(eglDisplay, eglContext);
if (eglSurface != EGL_NO_SURFACE)
eglDestroySurface(eglDisplay, eglSurface);
if (eglSurface != EGL_NO_SURFACE)
eglDestroySurface(eglDisplay, eglSurface);
eglTerminate(eglDisplay);
}
eglTerminate(eglDisplay);
}
if (win)
XDestroyWindow(display, win);
if (win)
XDestroyWindow(display, win);
XCloseDisplay(display);
XCloseDisplay(display);
}

View File

@@ -41,22 +41,22 @@
*/
// includes, system
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void error_exit(const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
void error_exit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
#include "graphics_interface.c"
@@ -68,64 +68,64 @@ void error_exit(const char *format, ...) {
#endif
// includes, cuda
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>
#include <cuda_runtime.h>
// Utilities and timing functions
#include <helper_functions.h> // includes cuda.h and cuda_runtime_api.h
#include <helper_functions.h> // includes cuda.h and cuda_runtime_api.h
// CUDA helper functions
#include <helper_cuda.h> // helper functions for CUDA error check
//#include <helper_cuda_gl.h> // helper functions for CUDA/GL interop
#include <helper_cuda.h> // helper functions for CUDA error check
// #include <helper_cuda_gl.h> // helper functions for CUDA/GL interop
#include <vector_types.h>
#define MAX_EPSILON_ERROR 0.0f
#define THRESHOLD 0.0f
#define REFRESH_DELAY 1 // ms
#define THRESHOLD 0.0f
#define REFRESH_DELAY 1 // ms
#define GUI_IDLE 0x100
#define GUI_ROTATE 0x101
#define GUI_IDLE 0x100
#define GUI_ROTATE 0x101
#define GUI_TRANSLATE 0x102
int gui_mode;
////////////////////////////////////////////////////////////////////////////////
// constants
const unsigned int window_width = 512;
const unsigned int window_width = 512;
const unsigned int window_height = 512;
const unsigned int mesh_width = 256;
const unsigned int mesh_width = 256;
const unsigned int mesh_height = 256;
// OpenGL ES variables and interop with CUDA C
GLuint mesh_vao, mesh_vbo;
GLuint mesh_vao, mesh_vbo;
struct cudaGraphicsResource *cuda_vbo_resource;
void *d_vbo_buffer = NULL;
void *d_vbo_buffer = NULL;
float g_fAnim = 0.0;
// UI / mouse controls
int mouse_old_x, mouse_old_y;
int mouse_buttons = 0;
int mouse_old_x, mouse_old_y;
int mouse_buttons = 0;
float rotate_x = 0.0, rotate_y = 0.0;
float translate_z = -3.0;
StopWatchInterface *timer = NULL;
// Frame statistics
int frame;
int fpsCount = 0; // FPS count for averaging
int fpsLimit = 1; // FPS limit for sampling
int g_Index = 0;
float avgFPS = 0.0f;
unsigned int frameCount = 0;
int frame;
int fpsCount = 0; // FPS count for averaging
int fpsLimit = 1; // FPS limit for sampling
int g_Index = 0;
float avgFPS = 0.0f;
unsigned int frameCount = 0;
unsigned int g_TotalErrors = 0;
// Auto-Verification Code
bool g_bQAReadback = false;
int *pArgc = NULL;
int *pArgc = NULL;
char **pArgv = NULL;
#define MAX(a, b) ((a > b) ? a : b)
@@ -140,76 +140,76 @@ void checkResultCuda(int argc, char **argv, const GLuint &vbo);
const char *sSDKsample = "simpleGLES (VBO)";
void computeFPS() {
frameCount++;
fpsCount++;
void computeFPS()
{
frameCount++;
fpsCount++;
if (fpsCount == fpsLimit) {
avgFPS = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
fpsCount = 0;
fpsLimit = (int)MAX(avgFPS, 1.f);
if (fpsCount == fpsLimit) {
avgFPS = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
fpsCount = 0;
fpsLimit = (int)MAX(avgFPS, 1.f);
sdkResetTimer(&timer);
}
sdkResetTimer(&timer);
}
char fps[256];
sprintf(fps, "Cuda/OpenGL ES Interop (VBO): %3.1f fps (Max 1000 fps)",
avgFPS);
graphics_set_windowtitle(fps);
char fps[256];
sprintf(fps, "Cuda/OpenGL ES Interop (VBO): %3.1f fps (Max 1000 fps)", avgFPS);
graphics_set_windowtitle(fps);
}
///////////////////////////////////////////////////////////////////////////////
//! Simple kernel to modify vertex positions in sine wave pattern
//! @param data data in global memory
///////////////////////////////////////////////////////////////////////////////
__global__ void simple_vbo_kernel(float4 *pos, unsigned int width,
unsigned int height, float time) {
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
__global__ void simple_vbo_kernel(float4 *pos, unsigned int width, unsigned int height, float time)
{
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
// calculate uv coordinates
float u = x / (float)width;
float v = y / (float)height;
u = u * 2.0f - 1.0f;
v = v * 2.0f - 1.0f;
// calculate uv coordinates
float u = x / (float)width;
float v = y / (float)height;
u = u * 2.0f - 1.0f;
v = v * 2.0f - 1.0f;
// calculate simple sine wave pattern
float freq = 4.0f;
float w = sinf(u * freq + time) * cosf(v * freq + time) * 0.5f;
// calculate simple sine wave pattern
float freq = 4.0f;
float w = sinf(u * freq + time) * cosf(v * freq + time) * 0.5f;
// write output vertex
pos[y * width + x] = make_float4(u, w, v, 1.0f);
// write output vertex
pos[y * width + x] = make_float4(u, w, v, 1.0f);
}
void launch_kernel(float4 *pos, unsigned int mesh_width,
unsigned int mesh_height, float time) {
// execute the kernel
dim3 block(8, 8, 1);
dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
simple_vbo_kernel<<<grid, block>>>(pos, mesh_width, mesh_height, time);
void launch_kernel(float4 *pos, unsigned int mesh_width, unsigned int mesh_height, float time)
{
// execute the kernel
dim3 block(8, 8, 1);
dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
simple_vbo_kernel<<<grid, block>>>(pos, mesh_width, mesh_height, time);
}
////////////////////////////////////////////////////////////////////////////////
//! Run the Cuda part of the computation
////////////////////////////////////////////////////////////////////////////////
void runCuda(struct cudaGraphicsResource **vbo_resource) {
// map OpenGL buffer object for writing from CUDA
float4 *dptr;
cudaGraphicsMapResources(1, vbo_resource, 0);
size_t num_bytes;
cudaGraphicsResourceGetMappedPointer((void **)&dptr, &num_bytes,
*vbo_resource);
// printf("Sample CUDA mapped VBO: May access %ld bytes\n", num_bytes);
void runCuda(struct cudaGraphicsResource **vbo_resource)
{
// map OpenGL buffer object for writing from CUDA
float4 *dptr;
cudaGraphicsMapResources(1, vbo_resource, 0);
size_t num_bytes;
cudaGraphicsResourceGetMappedPointer((void **)&dptr, &num_bytes, *vbo_resource);
// printf("Sample CUDA mapped VBO: May access %ld bytes\n", num_bytes);
// execute the kernel
// dim3 block(8, 8, 1);
// dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
// kernel<<< grid, block>>>(dptr, mesh_width, mesh_height, g_fAnim);
// execute the kernel
// dim3 block(8, 8, 1);
// dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
// kernel<<< grid, block>>>(dptr, mesh_width, mesh_height, g_fAnim);
launch_kernel(dptr, mesh_width, mesh_height, g_fAnim);
launch_kernel(dptr, mesh_width, mesh_height, g_fAnim);
// unmap buffer object
cudaGraphicsUnmapResources(1, vbo_resource, 0);
// unmap buffer object
cudaGraphicsUnmapResources(1, vbo_resource, 0);
}
#ifdef _WIN32
@@ -222,406 +222,410 @@ void runCuda(struct cudaGraphicsResource **vbo_resource) {
#endif
#endif
void sdkDumpBin2(void *data, unsigned int bytes, const char *filename) {
printf("sdkDumpBin: <%s>\n", filename);
FILE *fp;
FOPEN(fp, filename, "wb");
fwrite(data, bytes, 1, fp);
fflush(fp);
fclose(fp);
void sdkDumpBin2(void *data, unsigned int bytes, const char *filename)
{
printf("sdkDumpBin: <%s>\n", filename);
FILE *fp;
FOPEN(fp, filename, "wb");
fwrite(data, bytes, 1, fp);
fflush(fp);
fclose(fp);
}
////////////////////////////////////////////////////////////////////////////////
//! Run the Cuda part of the computation
////////////////////////////////////////////////////////////////////////////////
void runAutoTest(int devID, char **argv, char *ref_file) {
char *reference_file = NULL;
void *imageData = malloc(mesh_width * mesh_height * sizeof(float));
void runAutoTest(int devID, char **argv, char *ref_file)
{
char *reference_file = NULL;
void *imageData = malloc(mesh_width * mesh_height * sizeof(float));
// execute the kernel
launch_kernel((float4 *)d_vbo_buffer, mesh_width, mesh_height, g_fAnim);
// execute the kernel
launch_kernel((float4 *)d_vbo_buffer, mesh_width, mesh_height, g_fAnim);
cudaDeviceSynchronize();
getLastCudaError("launch_kernel failed");
cudaDeviceSynchronize();
getLastCudaError("launch_kernel failed");
cudaMemcpy(imageData, d_vbo_buffer, mesh_width * mesh_height * sizeof(float),
cudaMemcpyDeviceToHost);
cudaMemcpy(imageData, d_vbo_buffer, mesh_width * mesh_height * sizeof(float), cudaMemcpyDeviceToHost);
sdkDumpBin2(imageData, mesh_width * mesh_height * sizeof(float),
"simpleGL.bin");
reference_file = sdkFindFilePath(ref_file, argv[0]);
sdkDumpBin2(imageData, mesh_width * mesh_height * sizeof(float), "simpleGL.bin");
reference_file = sdkFindFilePath(ref_file, argv[0]);
if (reference_file &&
!sdkCompareBin2BinFloat("simpleGL.bin", reference_file,
mesh_width * mesh_height * sizeof(float),
MAX_EPSILON_ERROR, THRESHOLD, pArgv[0])) {
g_TotalErrors++;
}
if (reference_file
&& !sdkCompareBin2BinFloat("simpleGL.bin",
reference_file,
mesh_width * mesh_height * sizeof(float),
MAX_EPSILON_ERROR,
THRESHOLD,
pArgv[0])) {
g_TotalErrors++;
}
}
////////////////////////////////////////////////////////////////////////////////
//! Display callback
////////////////////////////////////////////////////////////////////////////////
void display_thisframe(float time_delta) {
sdkStartTimer(&timer);
void display_thisframe(float time_delta)
{
sdkStartTimer(&timer);
// run CUDA kernel to generate vertex positions
runCuda(&cuda_vbo_resource);
// run CUDA kernel to generate vertex positions
runCuda(&cuda_vbo_resource);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// GET_GLERROR(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// GET_GLERROR(0);
// set view matrix: broken, it doesn't work in OpenGL ES! Must put into shader
// glMatrixMode(GL_MODELVIEW);
// glLoadIdentity();
// glTranslatef(0.0, 0.0, translate_z);
// glRotatef(rotate_x, 1.0, 0.0, 0.0);
// glRotatef(rotate_y, 0.0, 1.0, 0.0);
// set view matrix: broken, it doesn't work in OpenGL ES! Must put into shader
// glMatrixMode(GL_MODELVIEW);
// glLoadIdentity();
// glTranslatef(0.0, 0.0, translate_z);
// glRotatef(rotate_x, 1.0, 0.0, 0.0);
// glRotatef(rotate_y, 0.0, 1.0, 0.0);
glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height);
glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height);
// GET_GLERROR(0);
glFinish();
// GET_GLERROR(0);
// GET_GLERROR(0);
glFinish();
// GET_GLERROR(0);
g_fAnim += time_delta;
g_fAnim += time_delta;
sdkStopTimer(&timer);
computeFPS();
sdkStopTimer(&timer);
computeFPS();
}
////////////////////////////////////////////////////////////////////////////////
//! Check if the result is correct or write data to file for external
//! regression testing
////////////////////////////////////////////////////////////////////////////////
void checkResultCuda(int argc, char **argv, const GLuint &vbo) {
if (!d_vbo_buffer) {
printf("%s: Mapping result buffer from OpenGL ES\n", __FUNCTION__);
void checkResultCuda(int argc, char **argv, const GLuint &vbo)
{
if (!d_vbo_buffer) {
printf("%s: Mapping result buffer from OpenGL ES\n", __FUNCTION__);
cudaGraphicsUnregisterResource(cuda_vbo_resource);
cudaGraphicsUnregisterResource(cuda_vbo_resource);
// map buffer object
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float *data = (float *)glMapBufferRange(
GL_ARRAY_BUFFER, 0, mesh_width * mesh_height * 4 * sizeof(float),
GL_READ_ONLY);
// map buffer object
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float *data =
(float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, mesh_width * mesh_height * 4 * sizeof(float), GL_READ_ONLY);
// check result
if (checkCmdLineFlag(argc, (const char **)argv, "regression")) {
// write file for regression test
sdkWriteFile<float>("./data/regression.dat", data,
mesh_width * mesh_height * 3, 0.0, false);
// check result
if (checkCmdLineFlag(argc, (const char **)argv, "regression")) {
// write file for regression test
sdkWriteFile<float>("./data/regression.dat", data, mesh_width * mesh_height * 3, 0.0, false);
}
// unmap GL buffer object
if (!glUnmapBuffer(GL_ARRAY_BUFFER)) {
fprintf(stderr, "Unmap buffer failed.\n");
fflush(stderr);
}
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, vbo, cudaGraphicsMapFlagsWriteDiscard));
GET_GLERROR(0);
}
// unmap GL buffer object
if (!glUnmapBuffer(GL_ARRAY_BUFFER)) {
fprintf(stderr, "Unmap buffer failed.\n");
fflush(stderr);
}
checkCudaErrors(cudaGraphicsGLRegisterBuffer(
&cuda_vbo_resource, vbo, cudaGraphicsMapFlagsWriteDiscard));
GET_GLERROR(0);
}
}
GLuint mesh_shader = 0;
void readAndCompileShaderFromGLSLFile(GLuint new_shaderprogram,
const char *filename, GLenum shaderType) {
FILE *file = fopen(filename, "rb"); // open shader text file
if (!file) error_exit("Filename %s does not exist\n", filename);
void readAndCompileShaderFromGLSLFile(GLuint new_shaderprogram, const char *filename, GLenum shaderType)
{
FILE *file = fopen(filename, "rb"); // open shader text file
if (!file)
error_exit("Filename %s does not exist\n", filename);
/* get the size of the file and read it */
fseek(file, 0, SEEK_END);
GLint size = ftell(file);
char *data = (char *)malloc(sizeof(char) * (size + 1));
memset(data, 0, sizeof(char) * (size + 1));
fseek(file, 0, SEEK_SET);
size_t res = fread(data, 1, size, file);
fclose(file);
/* get the size of the file and read it */
fseek(file, 0, SEEK_END);
GLint size = ftell(file);
char *data = (char *)malloc(sizeof(char) * (size + 1));
memset(data, 0, sizeof(char) * (size + 1));
fseek(file, 0, SEEK_SET);
size_t res = fread(data, 1, size, file);
fclose(file);
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const GLchar **)&data, &size);
glCompileShader(shader);
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const GLchar **)&data, &size);
glCompileShader(shader);
GET_GLERROR(0);
GLint compile_success = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_success);
GET_GLERROR(0);
GET_GLERROR(0);
GLint compile_success = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_success);
GET_GLERROR(0);
if (compile_success == GL_FALSE) {
printf("Compilation of %s failed!\n Reason:\n", filename);
if (compile_success == GL_FALSE) {
printf("Compilation of %s failed!\n Reason:\n", filename);
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
char errorLog[maxLength];
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
char errorLog[maxLength];
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
printf("%s", errorLog);
printf("%s", errorLog);
glDeleteShader(shader);
exit(1);
}
glDeleteShader(shader);
exit(1);
}
glAttachShader(new_shaderprogram, shader);
glDeleteShader(shader); // good to do?
glAttachShader(new_shaderprogram, shader);
glDeleteShader(shader); // good to do?
free(data);
free(data);
}
GLuint ShaderCreate(const char *vshader_filename,
const char *fshader_filename) {
printf("Loading GLSL shaders %s %s\n", vshader_filename, fshader_filename);
GLuint ShaderCreate(const char *vshader_filename, const char *fshader_filename)
{
printf("Loading GLSL shaders %s %s\n", vshader_filename, fshader_filename);
GLuint new_shaderprogram = glCreateProgram();
GLuint new_shaderprogram = glCreateProgram();
GET_GLERROR(0);
if (vshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, vshader_filename,
GL_VERTEX_SHADER);
GET_GLERROR(0);
if (vshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, vshader_filename, GL_VERTEX_SHADER);
GET_GLERROR(0);
if (fshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, fshader_filename,
GL_FRAGMENT_SHADER);
GET_GLERROR(0);
if (fshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, fshader_filename, GL_FRAGMENT_SHADER);
GET_GLERROR(0);
GET_GLERROR(0);
glLinkProgram(new_shaderprogram);
glLinkProgram(new_shaderprogram);
GET_GLERROR(0);
GLint link_success;
glGetProgramiv(new_shaderprogram, GL_LINK_STATUS, &link_success);
GET_GLERROR(0);
GLint link_success;
glGetProgramiv(new_shaderprogram, GL_LINK_STATUS, &link_success);
if (link_success == GL_FALSE) {
printf("Linking of %s with %s failed!\n Reason:\n", vshader_filename,
fshader_filename);
if (link_success == GL_FALSE) {
printf("Linking of %s with %s failed!\n Reason:\n", vshader_filename, fshader_filename);
GLint maxLength = 0;
glGetShaderiv(new_shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
GLint maxLength = 0;
glGetShaderiv(new_shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
char errorLog[maxLength];
glGetShaderInfoLog(new_shaderprogram, maxLength, &maxLength, &errorLog[0]);
char errorLog[maxLength];
glGetShaderInfoLog(new_shaderprogram, maxLength, &maxLength, &errorLog[0]);
printf("%s", errorLog);
printf("%s", errorLog);
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
return new_shaderprogram;
return new_shaderprogram;
}
//===========================================================================
// InitGraphicsState() - initialize OpenGL
//===========================================================================
static void InitGraphicsState(void) {
char *GL_version = (char *)glGetString(GL_VERSION);
char *GL_vendor = (char *)glGetString(GL_VENDOR);
char *GL_renderer = (char *)glGetString(GL_RENDERER);
static void InitGraphicsState(void)
{
char *GL_version = (char *)glGetString(GL_VERSION);
char *GL_vendor = (char *)glGetString(GL_VENDOR);
char *GL_renderer = (char *)glGetString(GL_RENDERER);
printf("Version: %s\n", GL_version);
printf("Vendor: %s\n", GL_vendor);
printf("Renderer: %s\n", GL_renderer);
printf("Version: %s\n", GL_version);
printf("Vendor: %s\n", GL_vendor);
printf("Renderer: %s\n", GL_renderer);
// RENDERING SETUP (OpenGL ES or OpenGL Core Profile!)
glGenVertexArrays(1, &mesh_vao); // Features' Vertex Array Object allocation
glBindVertexArray(mesh_vao); // bind VAO
// RENDERING SETUP (OpenGL ES or OpenGL Core Profile!)
glGenVertexArrays(1, &mesh_vao); // Features' Vertex Array Object allocation
glBindVertexArray(mesh_vao); // bind VAO
// initialize buffer object
glGenBuffers(1, &mesh_vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo);
// initialize buffer object
glGenBuffers(1, &mesh_vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo);
unsigned int size = mesh_width * mesh_height * 4 * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
unsigned int size = mesh_width * mesh_height * 4 * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, mesh_vbo,
cudaGraphicsMapFlagsNone));
// glBindVertexArray(0); // keep above Vertex Array Object bound (it's the
// only one throughout)
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, mesh_vbo, cudaGraphicsMapFlagsNone));
// glBindVertexArray(0); // keep above Vertex Array Object bound (it's the
// only one throughout)
// GLSL stuff
char *vertex_shader_path = sdkFindFilePath("mesh.vert.glsl", pArgv[0]);
char *fragment_shader_path = sdkFindFilePath("mesh.frag.glsl", pArgv[0]);
// GLSL stuff
char *vertex_shader_path = sdkFindFilePath("mesh.vert.glsl", pArgv[0]);
char *fragment_shader_path = sdkFindFilePath("mesh.frag.glsl", pArgv[0]);
if (vertex_shader_path == NULL || fragment_shader_path == NULL) {
printf("Error finding shader file\n");
exit(EXIT_FAILURE);
}
if (vertex_shader_path == NULL || fragment_shader_path == NULL) {
printf("Error finding shader file\n");
exit(EXIT_FAILURE);
}
mesh_shader = ShaderCreate(vertex_shader_path, fragment_shader_path);
GET_GLERROR(0);
mesh_shader = ShaderCreate(vertex_shader_path, fragment_shader_path);
GET_GLERROR(0);
free(vertex_shader_path);
free(fragment_shader_path);
free(vertex_shader_path);
free(fragment_shader_path);
glUseProgram(mesh_shader);
glUseProgram(mesh_shader);
}
////////////////////////////////////////////////////////////////////////////////
//! Run a simple test for CUDA
////////////////////////////////////////////////////////////////////////////////
bool runTest(int argc, char **argv, char *ref_file) {
// Create the CUTIL timer
sdkCreateTimer(&timer);
bool runTest(int argc, char **argv, char *ref_file)
{
// Create the CUTIL timer
sdkCreateTimer(&timer);
int devID = 0;
int devID = 0;
#if defined(__aarch64__) || defined(__arm__)
// find iGPU on the system which is compute capable which will perform
// GLES-CUDA interop
devID = findIntegratedGPU();
// find iGPU on the system which is compute capable which will perform
// GLES-CUDA interop
devID = findIntegratedGPU();
#else
// use command-line specified CUDA device, otherwise use device with highest
// Gflops/s
devID = findCudaDevice(argc, (const char **)argv);
// use command-line specified CUDA device, otherwise use device with highest
// Gflops/s
devID = findCudaDevice(argc, (const char **)argv);
#endif
// command line mode only
if (ref_file != NULL) {
// create VBO
checkCudaErrors(cudaMalloc((void **)&d_vbo_buffer,
mesh_width * mesh_height * 4 * sizeof(float)));
// command line mode only
if (ref_file != NULL) {
// create VBO
checkCudaErrors(cudaMalloc((void **)&d_vbo_buffer, mesh_width * mesh_height * 4 * sizeof(float)));
// run the cuda part
runAutoTest(devID, argv, ref_file);
// run the cuda part
runAutoTest(devID, argv, ref_file);
// check result of Cuda step
checkResultCuda(argc, argv, mesh_vbo);
// check result of Cuda step
checkResultCuda(argc, argv, mesh_vbo);
cudaFree(d_vbo_buffer);
d_vbo_buffer = NULL;
} else {
// this would use command-line specified CUDA device, note that CUDA
// defaults to highest Gflops/s device
if (checkCmdLineFlag(argc, (const char **)argv, "device"))
error_exit("Device setting not yet implemented!\n");
cudaFree(d_vbo_buffer);
d_vbo_buffer = NULL;
}
else {
// this would use command-line specified CUDA device, note that CUDA
// defaults to highest Gflops/s device
if (checkCmdLineFlag(argc, (const char **)argv, "device"))
error_exit("Device setting not yet implemented!\n");
// create X11 window and set up associated OpenGL ES context
graphics_setup_window(0, 0, window_width, window_height, sSDKsample);
// create X11 window and set up associated OpenGL ES context
graphics_setup_window(0, 0, window_width, window_height, sSDKsample);
InitGraphicsState(); // set up GLES stuff
InitGraphicsState(); // set up GLES stuff
glClearColor(0, 0.5, 1, 1); // blue-ish background
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0, 0.5, 1, 1); // blue-ish background
glClear(GL_COLOR_BUFFER_BIT);
// printf("WP%d\n", __LINE__);
graphics_swap_buffers();
// printf("WP%d\n", __LINE__);
graphics_swap_buffers();
XEvent event;
KeySym key;
char text[255];
XEvent event;
KeySym key;
char text[255];
int frame = 0;
int frame = 0;
while (frame < 100000) {
if (XPending(display)) {
XNextEvent(display, &event);
while (frame < 100000) {
if (XPending(display)) {
XNextEvent(display, &event);
if (event.type == Expose && event.xexpose.count == 0) {
printf("Redraw requested!\n");
}
if (event.type == KeyPress &&
XLookupString(&event.xkey, text, 255, &key, 0) == 1) {
if (text[0] == 27) goto label_stop_x;
if (event.type == Expose && event.xexpose.count == 0) {
printf("Redraw requested!\n");
}
if (event.type == KeyPress && XLookupString(&event.xkey, text, 255, &key, 0) == 1) {
if (text[0] == 27)
goto label_stop_x;
printf("You pressed the %c key!\n", text[0]);
printf("You pressed the %c key!\n", text[0]);
}
if (event.type == ButtonPress) {
printf(
"Mouse button %d press at (%d,%d)\n", event.xbutton.button, event.xbutton.x, event.xbutton.y);
if (event.xbutton.button == Button1)
gui_mode = GUI_TRANSLATE;
if (event.xbutton.button == Button3)
gui_mode = GUI_ROTATE;
mouse_old_x = event.xbutton.x;
mouse_old_y = event.xbutton.y;
}
if (event.type == ButtonRelease) {
printf("Mouse button %d released at (%d,%d)\n",
event.xbutton.button,
event.xbutton.x,
event.xbutton.y);
gui_mode = GUI_IDLE;
mouse_old_x = event.xbutton.x;
mouse_old_y = event.xbutton.y;
}
if (event.type == MotionNotify) {
// printf("Mouse motion towards %d %d, GUI mode is 0x%x\n",
// event.xmotion.x, event.xmotion.y, gui_mode);
float dx, dy;
dx = (float)(event.xmotion.x - mouse_old_x);
dy = (float)(event.xmotion.y - mouse_old_y);
if (gui_mode == GUI_ROTATE) {
rotate_x += dy * 0.2f;
rotate_y += dx * 0.2f;
printf("rot x %f y %f\n", rotate_x, rotate_y);
}
if (gui_mode == GUI_TRANSLATE) {
translate_z += dy * 0.01f;
printf("translate z %f\n", translate_z);
}
mouse_old_x = event.xmotion.x;
mouse_old_y = event.xmotion.y;
}
}
display_thisframe(0.010);
usleep(1000); // need not take full CPU and GPU
graphics_swap_buffers();
// printf("frame %d\n",frame++);
}
if (event.type == ButtonPress) {
printf("Mouse button %d press at (%d,%d)\n", event.xbutton.button,
event.xbutton.x, event.xbutton.y);
label_stop_x:
// NOTE: Before destroying OpenGL ES context, must unregister all shared
// resources from CUDA !
cudaGraphicsUnregisterResource(cuda_vbo_resource);
if (event.xbutton.button == Button1) gui_mode = GUI_TRANSLATE;
if (event.xbutton.button == Button3) gui_mode = GUI_ROTATE;
mouse_old_x = event.xbutton.x;
mouse_old_y = event.xbutton.y;
}
graphics_close_window(); // close window and destroy OpenGL ES context
if (event.type == ButtonRelease) {
printf("Mouse button %d released at (%d,%d)\n", event.xbutton.button,
event.xbutton.x, event.xbutton.y);
gui_mode = GUI_IDLE;
mouse_old_x = event.xbutton.x;
mouse_old_y = event.xbutton.y;
}
if (event.type == MotionNotify) {
// printf("Mouse motion towards %d %d, GUI mode is 0x%x\n",
// event.xmotion.x, event.xmotion.y, gui_mode);
float dx, dy;
dx = (float)(event.xmotion.x - mouse_old_x);
dy = (float)(event.xmotion.y - mouse_old_y);
if (gui_mode == GUI_ROTATE) {
rotate_x += dy * 0.2f;
rotate_y += dx * 0.2f;
printf("rot x %f y %f\n", rotate_x, rotate_y);
}
if (gui_mode == GUI_TRANSLATE) {
translate_z += dy * 0.01f;
printf("translate z %f\n", translate_z);
}
mouse_old_x = event.xmotion.x;
mouse_old_y = event.xmotion.y;
}
}
display_thisframe(0.010);
usleep(1000); // need not take full CPU and GPU
graphics_swap_buffers();
// printf("frame %d\n",frame++);
sdkDeleteTimer(&timer);
}
label_stop_x:
// NOTE: Before destroying OpenGL ES context, must unregister all shared
// resources from CUDA !
cudaGraphicsUnregisterResource(cuda_vbo_resource);
graphics_close_window(); // close window and destroy OpenGL ES context
sdkDeleteTimer(&timer);
}
return true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
char *ref_file = NULL;
int main(int argc, char **argv)
{
char *ref_file = NULL;
pArgc = &argc;
pArgv = argv;
pArgc = &argc;
pArgv = argv;
#if defined(__linux__)
setenv("DISPLAY", ":0", 0);
setenv("DISPLAY", ":0", 0);
#endif
printf("%s starting...\n", sSDKsample);
printf("%s starting...\n", sSDKsample);
if (argc > 1) {
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
// In this mode, we run without OpenGL and see if VBO is generated
// correctly
getCmdLineArgumentString(argc, (const char **)argv, "file",
(char **)&ref_file);
if (argc > 1) {
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
// In this mode, we run without OpenGL and see if VBO is generated
// correctly
getCmdLineArgumentString(argc, (const char **)argv, "file", (char **)&ref_file);
}
}
}
printf("\n");
printf("\n");
runTest(argc, argv, ref_file);
runTest(argc, argv, ref_file);
printf("%s completed, returned %s\n", sSDKsample,
(g_TotalErrors == 0) ? "OK" : "ERROR!");
printf("%s completed, returned %s\n", sSDKsample, (g_TotalErrors == 0) ? "OK" : "ERROR!");
exit(g_TotalErrors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
exit(g_TotalErrors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@@ -39,4 +39,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -42,19 +42,19 @@
// includes, system
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
void error_exit(const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
void error_exit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
#if 0
@@ -74,60 +74,60 @@ void error_exit(const char *format, ...) {
#include <cuda_runtime.h>
// Utilities and timing functions
#include <helper_functions.h> // includes cuda.h and cuda_runtime_api.h
#include <helper_functions.h> // includes cuda.h and cuda_runtime_api.h
// CUDA helper functions
#include <helper_cuda.h> // helper functions for CUDA error check
//#include <helper_cuda_gl.h> // helper functions for CUDA/GL interop
#include <helper_cuda.h> // helper functions for CUDA error check
// #include <helper_cuda_gl.h> // helper functions for CUDA/GL interop
#include <vector_types.h>
#define MAX_EPSILON_ERROR 0.0f
#define THRESHOLD 0.0f
#define REFRESH_DELAY 1 // ms
#define THRESHOLD 0.0f
#define REFRESH_DELAY 1 // ms
#define GUI_IDLE 0x100
#define GUI_ROTATE 0x101
#define GUI_IDLE 0x100
#define GUI_ROTATE 0x101
#define GUI_TRANSLATE 0x102
int gui_mode;
////////////////////////////////////////////////////////////////////////////////
// constants
const unsigned int window_width = 512;
const unsigned int window_width = 512;
const unsigned int window_height = 512;
const unsigned int mesh_width = 256;
const unsigned int mesh_width = 256;
const unsigned int mesh_height = 256;
// OpenGL ES variables and interop with CUDA C
GLuint mesh_vao, mesh_vbo;
GLuint mesh_vao, mesh_vbo;
struct cudaGraphicsResource *cuda_vbo_resource;
void *d_vbo_buffer = NULL;
void *d_vbo_buffer = NULL;
float g_fAnim = 0.0;
// UI / mouse controls
int mouse_old_x, mouse_old_y;
int mouse_buttons = 0;
int mouse_old_x, mouse_old_y;
int mouse_buttons = 0;
float rotate_x = 0.0, rotate_y = 0.0;
float translate_z = -3.0;
StopWatchInterface *timer = NULL;
// Frame statistics
int frame;
int fpsCount = 0; // FPS count for averaging
int fpsLimit = 1; // FPS limit for sampling
int g_Index = 0;
float avgFPS = 0.0f;
unsigned int frameCount = 0;
int frame;
int fpsCount = 0; // FPS count for averaging
int fpsLimit = 1; // FPS limit for sampling
int g_Index = 0;
float avgFPS = 0.0f;
unsigned int frameCount = 0;
unsigned int g_TotalErrors = 0;
// Auto-Verification Code
bool g_bQAReadback = false;
int *pArgc = NULL;
int *pArgc = NULL;
char **pArgv = NULL;
#define MAX(a, b) ((a > b) ? a : b)
@@ -142,76 +142,76 @@ void checkResultCuda(int argc, char **argv, const GLuint &vbo);
const char *sSDKsample = "simpleGLES (VBO)";
void computeFPS() {
frameCount++;
fpsCount++;
void computeFPS()
{
frameCount++;
fpsCount++;
if (fpsCount == fpsLimit) {
avgFPS = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
fpsCount = 0;
fpsLimit = (int)MAX(avgFPS, 1.f);
if (fpsCount == fpsLimit) {
avgFPS = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);
fpsCount = 0;
fpsLimit = (int)MAX(avgFPS, 1.f);
sdkResetTimer(&timer);
}
sdkResetTimer(&timer);
}
char fps[256];
sprintf(fps, "Cuda/OpenGL ES Interop (VBO): %3.1f fps (Max 1000 fps)",
avgFPS);
graphics_set_windowtitle(fps);
char fps[256];
sprintf(fps, "Cuda/OpenGL ES Interop (VBO): %3.1f fps (Max 1000 fps)", avgFPS);
graphics_set_windowtitle(fps);
}
///////////////////////////////////////////////////////////////////////////////
//! Simple kernel to modify vertex positions in sine wave pattern
//! @param data data in global memory
///////////////////////////////////////////////////////////////////////////////
__global__ void simple_vbo_kernel(float4 *pos, unsigned int width,
unsigned int height, float time) {
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
__global__ void simple_vbo_kernel(float4 *pos, unsigned int width, unsigned int height, float time)
{
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
// calculate uv coordinates
float u = x / (float)width;
float v = y / (float)height;
u = u * 2.0f - 1.0f;
v = v * 2.0f - 1.0f;
// calculate uv coordinates
float u = x / (float)width;
float v = y / (float)height;
u = u * 2.0f - 1.0f;
v = v * 2.0f - 1.0f;
// calculate simple sine wave pattern
float freq = 4.0f;
float w = sinf(u * freq + time) * cosf(v * freq + time) * 0.5f;
// calculate simple sine wave pattern
float freq = 4.0f;
float w = sinf(u * freq + time) * cosf(v * freq + time) * 0.5f;
// write output vertex
pos[y * width + x] = make_float4(u, w, v, 1.0f);
// write output vertex
pos[y * width + x] = make_float4(u, w, v, 1.0f);
}
void launch_kernel(float4 *pos, unsigned int mesh_width,
unsigned int mesh_height, float time) {
// execute the kernel
dim3 block(8, 8, 1);
dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
simple_vbo_kernel<<<grid, block>>>(pos, mesh_width, mesh_height, time);
void launch_kernel(float4 *pos, unsigned int mesh_width, unsigned int mesh_height, float time)
{
// execute the kernel
dim3 block(8, 8, 1);
dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
simple_vbo_kernel<<<grid, block>>>(pos, mesh_width, mesh_height, time);
}
////////////////////////////////////////////////////////////////////////////////
//! Run the Cuda part of the computation
////////////////////////////////////////////////////////////////////////////////
void runCuda(struct cudaGraphicsResource **vbo_resource) {
// map OpenGL buffer object for writing from CUDA
float4 *dptr;
cudaGraphicsMapResources(1, vbo_resource, 0);
size_t num_bytes;
cudaGraphicsResourceGetMappedPointer((void **)&dptr, &num_bytes,
*vbo_resource);
// printf("Sample CUDA mapped VBO: May access %ld bytes\n", num_bytes);
void runCuda(struct cudaGraphicsResource **vbo_resource)
{
// map OpenGL buffer object for writing from CUDA
float4 *dptr;
cudaGraphicsMapResources(1, vbo_resource, 0);
size_t num_bytes;
cudaGraphicsResourceGetMappedPointer((void **)&dptr, &num_bytes, *vbo_resource);
// printf("Sample CUDA mapped VBO: May access %ld bytes\n", num_bytes);
// execute the kernel
// dim3 block(8, 8, 1);
// dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
// kernel<<< grid, block>>>(dptr, mesh_width, mesh_height, g_fAnim);
// execute the kernel
// dim3 block(8, 8, 1);
// dim3 grid(mesh_width / block.x, mesh_height / block.y, 1);
// kernel<<< grid, block>>>(dptr, mesh_width, mesh_height, g_fAnim);
launch_kernel(dptr, mesh_width, mesh_height, g_fAnim);
launch_kernel(dptr, mesh_width, mesh_height, g_fAnim);
// unmap buffer object
cudaGraphicsUnmapResources(1, vbo_resource, 0);
// unmap buffer object
cudaGraphicsUnmapResources(1, vbo_resource, 0);
}
#ifdef _WIN32
@@ -224,348 +224,348 @@ void runCuda(struct cudaGraphicsResource **vbo_resource) {
#endif
#endif
void sdkDumpBin2(void *data, unsigned int bytes, const char *filename) {
printf("sdkDumpBin: <%s>\n", filename);
FILE *fp;
FOPEN(fp, filename, "wb");
fwrite(data, bytes, 1, fp);
fflush(fp);
fclose(fp);
void sdkDumpBin2(void *data, unsigned int bytes, const char *filename)
{
printf("sdkDumpBin: <%s>\n", filename);
FILE *fp;
FOPEN(fp, filename, "wb");
fwrite(data, bytes, 1, fp);
fflush(fp);
fclose(fp);
}
////////////////////////////////////////////////////////////////////////////////
//! Run the Cuda part of the computation
////////////////////////////////////////////////////////////////////////////////
void runAutoTest(int devID, char **argv, char *ref_file) {
char *reference_file = NULL;
void *imageData = malloc(mesh_width * mesh_height * sizeof(float));
void runAutoTest(int devID, char **argv, char *ref_file)
{
char *reference_file = NULL;
void *imageData = malloc(mesh_width * mesh_height * sizeof(float));
// execute the kernel
launch_kernel((float4 *)d_vbo_buffer, mesh_width, mesh_height, g_fAnim);
// execute the kernel
launch_kernel((float4 *)d_vbo_buffer, mesh_width, mesh_height, g_fAnim);
cudaDeviceSynchronize();
getLastCudaError("launch_kernel failed");
cudaDeviceSynchronize();
getLastCudaError("launch_kernel failed");
cudaMemcpy(imageData, d_vbo_buffer, mesh_width * mesh_height * sizeof(float),
cudaMemcpyDeviceToHost);
cudaMemcpy(imageData, d_vbo_buffer, mesh_width * mesh_height * sizeof(float), cudaMemcpyDeviceToHost);
sdkDumpBin2(imageData, mesh_width * mesh_height * sizeof(float),
"simpleGL.bin");
reference_file = sdkFindFilePath(ref_file, argv[0]);
sdkDumpBin2(imageData, mesh_width * mesh_height * sizeof(float), "simpleGL.bin");
reference_file = sdkFindFilePath(ref_file, argv[0]);
if (reference_file &&
!sdkCompareBin2BinFloat("simpleGL.bin", reference_file,
mesh_width * mesh_height * sizeof(float),
MAX_EPSILON_ERROR, THRESHOLD, pArgv[0])) {
g_TotalErrors++;
}
if (reference_file
&& !sdkCompareBin2BinFloat("simpleGL.bin",
reference_file,
mesh_width * mesh_height * sizeof(float),
MAX_EPSILON_ERROR,
THRESHOLD,
pArgv[0])) {
g_TotalErrors++;
}
}
////////////////////////////////////////////////////////////////////////////////
//! Display callback
////////////////////////////////////////////////////////////////////////////////
void display_thisframe(float time_delta) {
sdkStartTimer(&timer);
void display_thisframe(float time_delta)
{
sdkStartTimer(&timer);
// run CUDA kernel to generate vertex positions
runCuda(&cuda_vbo_resource);
// run CUDA kernel to generate vertex positions
runCuda(&cuda_vbo_resource);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// GET_GLERROR(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// GET_GLERROR(0);
// set view matrix: broken, it doesn't work in OpenGL ES! Must put into shader
// glMatrixMode(GL_MODELVIEW);
// glLoadIdentity();
// glTranslatef(0.0, 0.0, translate_z);
// glRotatef(rotate_x, 1.0, 0.0, 0.0);
// glRotatef(rotate_y, 0.0, 1.0, 0.0);
// set view matrix: broken, it doesn't work in OpenGL ES! Must put into shader
// glMatrixMode(GL_MODELVIEW);
// glLoadIdentity();
// glTranslatef(0.0, 0.0, translate_z);
// glRotatef(rotate_x, 1.0, 0.0, 0.0);
// glRotatef(rotate_y, 0.0, 1.0, 0.0);
glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height);
glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height);
// GET_GLERROR(0);
glFinish();
// GET_GLERROR(0);
// GET_GLERROR(0);
glFinish();
// GET_GLERROR(0);
g_fAnim += time_delta;
g_fAnim += time_delta;
sdkStopTimer(&timer);
computeFPS();
sdkStopTimer(&timer);
computeFPS();
}
////////////////////////////////////////////////////////////////////////////////
//! Check if the result is correct or write data to file for external
//! regression testing
////////////////////////////////////////////////////////////////////////////////
void checkResultCuda(int argc, char **argv, const GLuint &vbo) {
if (!d_vbo_buffer) {
printf("%s: Mapping result buffer from OpenGL ES\n", __FUNCTION__);
void checkResultCuda(int argc, char **argv, const GLuint &vbo)
{
if (!d_vbo_buffer) {
printf("%s: Mapping result buffer from OpenGL ES\n", __FUNCTION__);
cudaGraphicsUnregisterResource(cuda_vbo_resource);
cudaGraphicsUnregisterResource(cuda_vbo_resource);
// map buffer object
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float *data = (float *)glMapBufferRange(
GL_ARRAY_BUFFER, 0, mesh_width * mesh_height * 4 * sizeof(float),
GL_READ_ONLY);
// map buffer object
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float *data =
(float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, mesh_width * mesh_height * 4 * sizeof(float), GL_READ_ONLY);
// check result
if (checkCmdLineFlag(argc, (const char **)argv, "regression")) {
// write file for regression test
sdkWriteFile<float>("./data/regression.dat", data,
mesh_width * mesh_height * 3, 0.0, false);
// check result
if (checkCmdLineFlag(argc, (const char **)argv, "regression")) {
// write file for regression test
sdkWriteFile<float>("./data/regression.dat", data, mesh_width * mesh_height * 3, 0.0, false);
}
// unmap GL buffer object
if (!glUnmapBuffer(GL_ARRAY_BUFFER)) {
fprintf(stderr, "Unmap buffer failed.\n");
fflush(stderr);
}
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, vbo, cudaGraphicsMapFlagsWriteDiscard));
GET_GLERROR(0);
}
// unmap GL buffer object
if (!glUnmapBuffer(GL_ARRAY_BUFFER)) {
fprintf(stderr, "Unmap buffer failed.\n");
fflush(stderr);
}
checkCudaErrors(cudaGraphicsGLRegisterBuffer(
&cuda_vbo_resource, vbo, cudaGraphicsMapFlagsWriteDiscard));
GET_GLERROR(0);
}
}
GLuint mesh_shader = 0;
void readAndCompileShaderFromGLSLFile(GLuint new_shaderprogram,
const char *filename, GLenum shaderType) {
FILE *file = fopen(filename, "rb"); // open shader text file
if (!file) error_exit("Filename %s does not exist\n", filename);
void readAndCompileShaderFromGLSLFile(GLuint new_shaderprogram, const char *filename, GLenum shaderType)
{
FILE *file = fopen(filename, "rb"); // open shader text file
if (!file)
error_exit("Filename %s does not exist\n", filename);
/* get the size of the file and read it */
fseek(file, 0, SEEK_END);
GLint size = ftell(file);
char *data = (char *)malloc(sizeof(char) * (size + 1));
memset(data, 0, sizeof(char) * (size + 1));
fseek(file, 0, SEEK_SET);
size_t res = fread(data, 1, size, file);
fclose(file);
/* get the size of the file and read it */
fseek(file, 0, SEEK_END);
GLint size = ftell(file);
char *data = (char *)malloc(sizeof(char) * (size + 1));
memset(data, 0, sizeof(char) * (size + 1));
fseek(file, 0, SEEK_SET);
size_t res = fread(data, 1, size, file);
fclose(file);
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const GLchar **)&data, &size);
glCompileShader(shader);
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, (const GLchar **)&data, &size);
glCompileShader(shader);
GET_GLERROR(0);
GLint compile_success = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_success);
GET_GLERROR(0);
GET_GLERROR(0);
GLint compile_success = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_success);
GET_GLERROR(0);
if (compile_success == GL_FALSE) {
printf("Compilation of %s failed!\n Reason:\n", filename);
if (compile_success == GL_FALSE) {
printf("Compilation of %s failed!\n Reason:\n", filename);
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
char errorLog[maxLength];
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
char errorLog[maxLength];
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
printf("%s", errorLog);
printf("%s", errorLog);
glDeleteShader(shader);
exit(1);
}
glDeleteShader(shader);
exit(1);
}
glAttachShader(new_shaderprogram, shader);
glDeleteShader(shader); // good to do?
glAttachShader(new_shaderprogram, shader);
glDeleteShader(shader); // good to do?
free(data);
free(data);
}
GLuint ShaderCreate(const char *vshader_filename,
const char *fshader_filename) {
printf("Loading GLSL shaders %s %s\n", vshader_filename, fshader_filename);
GLuint ShaderCreate(const char *vshader_filename, const char *fshader_filename)
{
printf("Loading GLSL shaders %s %s\n", vshader_filename, fshader_filename);
GLuint new_shaderprogram = glCreateProgram();
GLuint new_shaderprogram = glCreateProgram();
GET_GLERROR(0);
if (vshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, vshader_filename,
GL_VERTEX_SHADER);
GET_GLERROR(0);
if (vshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, vshader_filename, GL_VERTEX_SHADER);
GET_GLERROR(0);
if (fshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, fshader_filename,
GL_FRAGMENT_SHADER);
GET_GLERROR(0);
if (fshader_filename)
readAndCompileShaderFromGLSLFile(new_shaderprogram, fshader_filename, GL_FRAGMENT_SHADER);
GET_GLERROR(0);
GET_GLERROR(0);
glLinkProgram(new_shaderprogram);
glLinkProgram(new_shaderprogram);
GET_GLERROR(0);
GLint link_success;
glGetProgramiv(new_shaderprogram, GL_LINK_STATUS, &link_success);
GET_GLERROR(0);
GLint link_success;
glGetProgramiv(new_shaderprogram, GL_LINK_STATUS, &link_success);
if (link_success == GL_FALSE) {
printf("Linking of %s with %s failed!\n Reason:\n", vshader_filename,
fshader_filename);
if (link_success == GL_FALSE) {
printf("Linking of %s with %s failed!\n Reason:\n", vshader_filename, fshader_filename);
GLint maxLength = 0;
glGetShaderiv(new_shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
GLint maxLength = 0;
glGetShaderiv(new_shaderprogram, GL_INFO_LOG_LENGTH, &maxLength);
char errorLog[maxLength];
glGetShaderInfoLog(new_shaderprogram, maxLength, &maxLength, &errorLog[0]);
char errorLog[maxLength];
glGetShaderInfoLog(new_shaderprogram, maxLength, &maxLength, &errorLog[0]);
printf("%s", errorLog);
printf("%s", errorLog);
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
return new_shaderprogram;
return new_shaderprogram;
}
//===========================================================================
// InitGraphicsState() - initialize OpenGL
//===========================================================================
static void InitGraphicsState(char **argv) {
char *GL_version = (char *)glGetString(GL_VERSION);
char *GL_vendor = (char *)glGetString(GL_VENDOR);
char *GL_renderer = (char *)glGetString(GL_RENDERER);
static void InitGraphicsState(char **argv)
{
char *GL_version = (char *)glGetString(GL_VERSION);
char *GL_vendor = (char *)glGetString(GL_VENDOR);
char *GL_renderer = (char *)glGetString(GL_RENDERER);
printf("Version: %s\n", GL_version);
printf("Vendor: %s\n", GL_vendor);
printf("Renderer: %s\n", GL_renderer);
printf("Version: %s\n", GL_version);
printf("Vendor: %s\n", GL_vendor);
printf("Renderer: %s\n", GL_renderer);
// RENDERING SETUP (OpenGL ES or OpenGL Core Profile!)
glGenVertexArrays(1, &mesh_vao); // Features' Vertex Array Object allocation
glBindVertexArray(mesh_vao); // bind VAO
// RENDERING SETUP (OpenGL ES or OpenGL Core Profile!)
glGenVertexArrays(1, &mesh_vao); // Features' Vertex Array Object allocation
glBindVertexArray(mesh_vao); // bind VAO
// initialize buffer object
glGenBuffers(1, &mesh_vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo);
// initialize buffer object
glGenBuffers(1, &mesh_vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo);
unsigned int size = mesh_width * mesh_height * 4 * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
unsigned int size = mesh_width * mesh_height * 4 * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, mesh_vbo,
cudaGraphicsMapFlagsNone));
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_vbo_resource, mesh_vbo, cudaGraphicsMapFlagsNone));
// glBindVertexArray(0); // keep above Vertex Array Object bound (it's the
// only one throughout)
// glBindVertexArray(0); // keep above Vertex Array Object bound (it's the
// only one throughout)
// GLSL stuff
char *vertex_shader_path = sdkFindFilePath("mesh.vert.glsl", argv[0]);
char *fragment_shader_path = sdkFindFilePath("mesh.frag.glsl", argv[0]);
// GLSL stuff
char *vertex_shader_path = sdkFindFilePath("mesh.vert.glsl", argv[0]);
char *fragment_shader_path = sdkFindFilePath("mesh.frag.glsl", argv[0]);
if (vertex_shader_path == NULL || fragment_shader_path == NULL) {
printf("Error finding shader file\n");
exit(EXIT_FAILURE);
}
if (vertex_shader_path == NULL || fragment_shader_path == NULL) {
printf("Error finding shader file\n");
exit(EXIT_FAILURE);
}
mesh_shader = ShaderCreate(vertex_shader_path, fragment_shader_path);
GET_GLERROR(0);
mesh_shader = ShaderCreate(vertex_shader_path, fragment_shader_path);
GET_GLERROR(0);
free(vertex_shader_path);
free(fragment_shader_path);
free(vertex_shader_path);
free(fragment_shader_path);
glUseProgram(mesh_shader);
glUseProgram(mesh_shader);
}
////////////////////////////////////////////////////////////////////////////////
//! Run a simple test for CUDA
////////////////////////////////////////////////////////////////////////////////
bool runTest(int argc, char **argv, char *ref_file) {
// Create the CUTIL timer
sdkCreateTimer(&timer);
bool runTest(int argc, char **argv, char *ref_file)
{
// Create the CUTIL timer
sdkCreateTimer(&timer);
int devID = 0;
int devID = 0;
#if defined(__aarch64__) || defined(__arm__)
// find iGPU on the system which is compute capable which will perform
// GLES-CUDA interop
devID = findIntegratedGPU();
// find iGPU on the system which is compute capable which will perform
// GLES-CUDA interop
devID = findIntegratedGPU();
#else
// use command-line specified CUDA device, otherwise use device with highest
// Gflops/s
devID = findCudaDevice(argc, (const char **)argv);
// use command-line specified CUDA device, otherwise use device with highest
// Gflops/s
devID = findCudaDevice(argc, (const char **)argv);
#endif
// command line mode only
if (ref_file != NULL) {
// create VBO
checkCudaErrors(cudaMalloc((void **)&d_vbo_buffer,
mesh_width * mesh_height * 4 * sizeof(float)));
// command line mode only
if (ref_file != NULL) {
// create VBO
checkCudaErrors(cudaMalloc((void **)&d_vbo_buffer, mesh_width * mesh_height * 4 * sizeof(float)));
// run the cuda part
runAutoTest(devID, argv, ref_file);
// run the cuda part
runAutoTest(devID, argv, ref_file);
// check result of Cuda step
checkResultCuda(argc, argv, mesh_vbo);
// check result of Cuda step
checkResultCuda(argc, argv, mesh_vbo);
cudaFree(d_vbo_buffer);
d_vbo_buffer = NULL;
} else {
// this would use command-line specified CUDA device, note that CUDA
// defaults to highest Gflops/s device
if (checkCmdLineFlag(argc, (const char **)argv, "device"))
error_exit("Device setting not yet implemented!\n");
cudaFree(d_vbo_buffer);
d_vbo_buffer = NULL;
}
else {
// this would use command-line specified CUDA device, note that CUDA
// defaults to highest Gflops/s device
if (checkCmdLineFlag(argc, (const char **)argv, "device"))
error_exit("Device setting not yet implemented!\n");
// create X11 window and set up associated OpenGL ES context
graphics_setup_window(0, 0, window_width, window_height, sSDKsample);
// create X11 window and set up associated OpenGL ES context
graphics_setup_window(0, 0, window_width, window_height, sSDKsample);
InitGraphicsState(argv); // set up GLES stuff
InitGraphicsState(argv); // set up GLES stuff
glClearColor(0, 0.5, 1, 1); // blue-ish background
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0, 0.5, 1, 1); // blue-ish background
glClear(GL_COLOR_BUFFER_BIT);
// printf("WP%d\n", __LINE__);
graphics_swap_buffers();
// printf("WP%d\n", __LINE__);
graphics_swap_buffers();
int frame = 0;
int frame = 0;
while (frame < 1000) {
display_thisframe(0.010);
usleep(1000); // need not take full CPU and GPU
while (frame < 1000) {
display_thisframe(0.010);
usleep(1000); // need not take full CPU and GPU
graphics_swap_buffers();
// printf("frame %d\n",frame++);
graphics_swap_buffers();
// printf("frame %d\n",frame++);
}
// NOTE: Before destroying OpenGL ES context, must unregister all shared
// resources from CUDA !
cudaGraphicsUnregisterResource(cuda_vbo_resource);
graphics_close_window(); // close window and destroy OpenGL ES context
sdkDeleteTimer(&timer);
}
// NOTE: Before destroying OpenGL ES context, must unregister all shared
// resources from CUDA !
cudaGraphicsUnregisterResource(cuda_vbo_resource);
graphics_close_window(); // close window and destroy OpenGL ES context
sdkDeleteTimer(&timer);
}
return true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
char *ref_file = NULL;
int main(int argc, char **argv)
{
char *ref_file = NULL;
pArgc = &argc;
pArgv = argv;
pArgc = &argc;
pArgv = argv;
#if defined(__linux__)
setenv("DISPLAY", ":0", 0);
setenv("DISPLAY", ":0", 0);
#endif
printf("%s starting...\n", sSDKsample);
printf("%s starting...\n", sSDKsample);
if (argc > 1) {
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
// In this mode, we run without OpenGL and see if VBO is generated
// correctly
getCmdLineArgumentString(argc, (const char **)argv, "file",
(char **)&ref_file);
if (argc > 1) {
if (checkCmdLineFlag(argc, (const char **)argv, "file")) {
// In this mode, we run without OpenGL and see if VBO is generated
// correctly
getCmdLineArgumentString(argc, (const char **)argv, "file", (char **)&ref_file);
}
}
}
printf("\n");
printf("\n");
runTest(argc, argv, ref_file);
runTest(argc, argv, ref_file);
printf("%s completed, returned %s\n", sSDKsample,
(g_TotalErrors == 0) ? "OK" : "ERROR!");
printf("%s completed, returned %s\n", sSDKsample, (g_TotalErrors == 0) ? "OK" : "ERROR!");
exit(g_TotalErrors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
exit(g_TotalErrors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}