mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-25 22:28:17 +08:00
Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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, §ionId) != 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, §ionId) != 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, §ionId) != 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, §ionId)
|
||||
!= 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, §ionId) != 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, §ionId)
|
||||
!= 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, §ionId) != 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, §ionId)
|
||||
!= 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++;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user