Forge
ComputeCopy.h
Go to the documentation of this file.
1/*******************************************************
2 * Copyright (c) 2015-2019, ArrayFire
3 * All rights reserved.
4 *
5 * This file is distributed under 3-clause BSD license.
6 * The complete license agreement can be obtained at:
7 * http://arrayfire.com/licenses/BSD-3-Clause
8 ********************************************************/
9
10#ifndef __COMPUTE_DATA_COPY_H__
11#define __COMPUTE_DATA_COPY_H__
12
13#include <stdlib.h>
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
19
20#if defined(USE_FORGE_CPU_COPY_HELPERS)
21
22// No special headers for cpu backend
23
24#elif defined(USE_FORGE_CUDA_COPY_HELPERS)
25
26#include <stdio.h>
27
28#ifndef GL_VERSION
29// gl.h is required by cuda_gl_interop to be included before it
30// And gl.h requires windows.h to be included before it
31#if defined(OS_WIN)
32#include <windows.h>
33#endif // OS_WIN
34#include <GL/gl.h>
35#endif // GL_VERSION
36
37#include <cuda.h>
38#include <cuda_runtime.h>
39#include <cuda_gl_interop.h>
40
41#elif defined(USE_FORGE_OPENCL_COPY_HELPERS)
42
43// No special headers for opencl backend
44
45#else
46
47 #error "Invalid Compute model, exiting."
48
49#endif
50
51
58#if defined(USE_FORGE_CPU_COPY_HELPERS)
59typedef unsigned GfxResourceHandle;
60#elif defined(USE_FORGE_CUDA_COPY_HELPERS)
61typedef cudaGraphicsResource* GfxResourceHandle;
62#elif defined(USE_FORGE_OPENCL_COPY_HELPERS)
63typedef cl_mem GfxResourceHandle;
64#endif
65
66
74
79
80typedef struct {
81 GfxResourceHandle mId;
83} GfxHandle;
84
85
87
88#if defined(USE_FORGE_CPU_COPY_HELPERS)
89
90static
91void createGLBuffer(GfxHandle** pOut, const unsigned pResourceId, const BufferType pTarget)
92{
93 GfxHandle* temp = (GfxHandle*)malloc(sizeof(GfxHandle));
94
95 temp->mId = pResourceId;
96 temp->mTarget = pTarget;
97
98 *pOut = temp;
99}
100
101static
102void releaseGLBuffer(GfxHandle* pHandle)
103{
104 free(pHandle);
105}
106
107static
108void copyToGLBuffer(GfxHandle* pGLDestination, ComputeResourceHandle pSource, const size_t pSize)
109{
110 GfxHandle* temp = pGLDestination;
111
112 if (temp->mTarget==FORGE_IMAGE_BUFFER) {
113 fg_update_pixel_buffer(temp->mId, pSize, pSource);
114 } else if (temp->mTarget==FORGE_VERTEX_BUFFER) {
115 fg_update_vertex_buffer(temp->mId, pSize, pSource);
116 }
117}
118#endif
119
121
122#if defined(USE_FORGE_CUDA_COPY_HELPERS)
123
124static void handleCUDAError(cudaError_t err, const char *file, int line)
125{
126 if (err != cudaSuccess) {
127 printf( "%s in %s at line %d\n", cudaGetErrorString(err), file, line);
128 exit(EXIT_FAILURE);
129 }
130}
131
132#define FORGE_CUDA_CHECK(err) (handleCUDAError(err, __FILE__, __LINE__ ))
133
134static
135void createGLBuffer(GfxHandle** pOut, const unsigned pResourceId, const BufferType pTarget)
136{
137 GfxHandle* temp = (GfxHandle*)malloc(sizeof(GfxHandle));
138
139 temp->mTarget = pTarget;
140
141 cudaGraphicsResource *cudaImageResource;
142
143 FORGE_CUDA_CHECK(cudaGraphicsGLRegisterBuffer(&cudaImageResource,
144 pResourceId,
145 cudaGraphicsMapFlagsWriteDiscard));
146
147 temp->mId = cudaImageResource;
148
149 *pOut = temp;
150}
151
152static
153void releaseGLBuffer(GfxHandle* pHandle)
154{
155 FORGE_CUDA_CHECK(cudaGraphicsUnregisterResource(pHandle->mId));
156 free(pHandle);
157}
158
159static
160void copyToGLBuffer(GfxHandle* pGLDestination, ComputeResourceHandle pSource, const size_t pSize)
161{
162 size_t numBytes;
163 void* pointer = NULL;
164
165 cudaGraphicsResource *cudaResource = pGLDestination->mId;
166
167 FORGE_CUDA_CHECK(cudaGraphicsMapResources(1, &cudaResource, 0));
168
169 FORGE_CUDA_CHECK(cudaGraphicsResourceGetMappedPointer(&pointer, &numBytes, cudaResource));
170
171 FORGE_CUDA_CHECK(cudaMemcpy(pointer, pSource, numBytes, cudaMemcpyDeviceToDevice));
172
173 FORGE_CUDA_CHECK(cudaGraphicsUnmapResources(1, &cudaResource, 0));
174}
175#endif
176
178
179#if defined(USE_FORGE_OPENCL_COPY_HELPERS)
180
181#pragma GCC diagnostic push
182#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
183
184#define FORGE_OCL_CHECK(cl_status, message) \
185 if(cl_status != CL_SUCCESS) \
186 { \
187 printf("Error: %s \nError Code: %d\n", message, cl_status);\
188 printf("Location: %s:%i\n", __FILE__, __LINE__);\
189 exit(EXIT_FAILURE); \
190 }
191
192static
193void createGLBuffer(GfxHandle** pOut, const unsigned pResourceId, const BufferType pTarget)
194{
195 GfxHandle* temp = (GfxHandle*)malloc(sizeof(GfxHandle));
196
197 temp->mTarget = pTarget;
198
199 cl_int returnCode = CL_SUCCESS;
200
201 temp->mId = clCreateFromGLBuffer(getContext(), CL_MEM_WRITE_ONLY, pResourceId, &returnCode);
202
203 FORGE_OCL_CHECK(returnCode, "Failed in clCreateFromGLBuffer");
204
205 *pOut = temp;
206}
207
208static
209void releaseGLBuffer(GfxHandle* pHandle)
210{
211 FORGE_OCL_CHECK(clReleaseMemObject(pHandle->mId), "Failed in clReleaseMemObject");
212 free(pHandle);
213}
214
215static
216void copyToGLBuffer(GfxHandle* pGLDestination, ComputeResourceHandle pSource, const size_t pSize)
217{
218 // The user is expected to implement a function
219 // `cl_command_queue getCommandQueue()`
220 cl_command_queue queue = getCommandQueue();
221
222 cl_event waitEvent;
223
224 cl_mem src = (cl_mem)pSource;
225 cl_mem dst = pGLDestination->mId;
226
227 fg_finish();
228
229 FORGE_OCL_CHECK(clEnqueueAcquireGLObjects(queue, 1, &dst, 0, NULL, &waitEvent),
230 "Failed in clEnqueueAcquireGLObjects");
231
232 FORGE_OCL_CHECK(clWaitForEvents(1, &waitEvent),
233 "Failed in clWaitForEvents after clEnqueueAcquireGLObjects");
234
235 FORGE_OCL_CHECK(clEnqueueCopyBuffer(queue, src, dst, 0, 0, pSize, 0, NULL, &waitEvent),
236 "Failed in clEnqueueCopyBuffer");
237
238 FORGE_OCL_CHECK(clEnqueueReleaseGLObjects(queue, 1, &dst, 0, NULL, &waitEvent),
239 "Failed in clEnqueueReleaseGLObjects");
240
241 FORGE_OCL_CHECK(clWaitForEvents(1, &waitEvent),
242 "Failed in clWaitForEvents after clEnqueueReleaseGLObjects");
243}
244
245#pragma GCC diagnostic pop
246
247#endif
248
250
251#ifdef __cplusplus
252}
253#endif
254
255#endif
void * ComputeResourceHandle
A backend-agnostic handle to a compute memory resource originating from an OpenGL resource.
Definition ComputeCopy.h:73
BufferType
Definition ComputeCopy.h:75
@ FORGE_VERTEX_BUFFER
OpenGL Vertex Buffer Object.
Definition ComputeCopy.h:77
@ FORGE_IMAGE_BUFFER
OpenGL Pixel Buffer Object.
Definition ComputeCopy.h:76
FGAPI fg_err fg_update_vertex_buffer(const unsigned pBufferId, const size_t pBufferSize, const void *pBufferData)
Update backend specific vertex buffer from given host side memory.
FGAPI fg_err fg_update_pixel_buffer(const unsigned pBufferId, const size_t pBufferSize, const void *pBufferData)
Update backend specific pixel buffer from given host side memory.
FGAPI fg_err fg_finish()
Sync all rendering operations till this point.
Definition ComputeCopy.h:80
BufferType mTarget
Definition ComputeCopy.h:82
GfxResourceHandle mId
Definition ComputeCopy.h:81