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
16 extern "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)
59 typedef unsigned GfxResourceHandle;
60 #elif defined(USE_FORGE_CUDA_COPY_HELPERS)
61 typedef cudaGraphicsResource* GfxResourceHandle;
62 #elif defined(USE_FORGE_OPENCL_COPY_HELPERS)
63 typedef cl_mem GfxResourceHandle;
64 #endif
65
66
73 typedef void* ComputeResourceHandle;
74
75 typedef enum {
76 FORGE_IMAGE_BUFFER = 0,
77 FORGE_VERTEX_BUFFER = 1
78 } BufferType;
79
80 typedef struct {
81 GfxResourceHandle mId;
82 BufferType mTarget;
83 } GfxHandle;
84
85
87
88 #if defined(USE_FORGE_CPU_COPY_HELPERS)
89
90 static
91 void 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
101 static
102 void releaseGLBuffer(GfxHandle* pHandle)
103 {
104 free(pHandle);
105 }
106
107 static
108 void 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
124 static 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
134 static
135 void 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
152 static
153 void releaseGLBuffer(GfxHandle* pHandle)
154 {
155 FORGE_CUDA_CHECK(cudaGraphicsUnregisterResource(pHandle->mId));
156 free(pHandle);
157 }
158
159 static
160 void 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 #if defined(__GNUC__)
182 #pragma GCC diagnostic push
183 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
184 #endif
185
186 #define FORGE_OCL_CHECK(cl_status, message) \
187 if(cl_status != CL_SUCCESS) \
188 { \
189 printf("Error: %s \nError Code: %d\n", message, cl_status);\
190 printf("Location: %s:%i\n", __FILE__, __LINE__);\
191 exit(EXIT_FAILURE); \
192 }
193
194 static
195 void createGLBuffer(GfxHandle** pOut, const unsigned pResourceId, const BufferType pTarget)
196 {
197 GfxHandle* temp = (GfxHandle*)malloc(sizeof(GfxHandle));
198
199 temp->mTarget = pTarget;
200
201 cl_int returnCode = CL_SUCCESS;
202
203 temp->mId = clCreateFromGLBuffer(getContext(), CL_MEM_WRITE_ONLY, pResourceId, &returnCode);
204
205 FORGE_OCL_CHECK(returnCode, "Failed in clCreateFromGLBuffer");
206
207 *pOut = temp;
208 }
209
210 static
211 void releaseGLBuffer(GfxHandle* pHandle)
212 {
213 FORGE_OCL_CHECK(clReleaseMemObject(pHandle->mId), "Failed in clReleaseMemObject");
214 free(pHandle);
215 }
216
217 static
218 void copyToGLBuffer(GfxHandle* pGLDestination, ComputeResourceHandle pSource, const size_t pSize)
219 {
220 // The user is expected to implement a function
221 // `cl_command_queue getCommandQueue()`
222 cl_command_queue queue = getCommandQueue();
223
224 cl_event waitEvent;
225
226 cl_mem src = (cl_mem)pSource;
227 cl_mem dst = pGLDestination->mId;
228
229 fg_finish();
230
231 FORGE_OCL_CHECK(clEnqueueAcquireGLObjects(queue, 1, &dst, 0, NULL, &waitEvent),
232 "Failed in clEnqueueAcquireGLObjects");
233
234 FORGE_OCL_CHECK(clWaitForEvents(1, &waitEvent),
235 "Failed in clWaitForEvents after clEnqueueAcquireGLObjects");
236
237 FORGE_OCL_CHECK(clEnqueueCopyBuffer(queue, src, dst, 0, 0, pSize, 0, NULL, &waitEvent),
238 "Failed in clEnqueueCopyBuffer");
239
240 FORGE_OCL_CHECK(clEnqueueReleaseGLObjects(queue, 1, &dst, 0, NULL, &waitEvent),
241 "Failed in clEnqueueReleaseGLObjects");
242
243 FORGE_OCL_CHECK(clWaitForEvents(1, &waitEvent),
244 "Failed in clWaitForEvents after clEnqueueReleaseGLObjects");
245 }
246
247 #if defined(__GNUC__)
248 #pragma GCC diagnostic pop
249 #endif
250
251 #endif
252
254
255 #ifdef __cplusplus
256 }
257 #endif
258
259 #endif
FORGE_IMAGE_BUFFER
OpenGL Pixel Buffer Object.
Definition: ComputeCopy.h:76
FORGE_VERTEX_BUFFER
OpenGL Vertex Buffer Object.
Definition: ComputeCopy.h:77
GfxHandle::mId
GfxResourceHandle mId
Definition: ComputeCopy.h:81
ComputeResourceHandle
void * ComputeResourceHandle
A backend-agnostic handle to a compute memory resource originating from an OpenGL resource...
Definition: ComputeCopy.h:73
fg_update_pixel_buffer
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.
GfxHandle
Definition: ComputeCopy.h:80
fg_update_vertex_buffer
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.
GfxHandle::mTarget
BufferType mTarget
Definition: ComputeCopy.h:82
BufferType
BufferType
Definition: ComputeCopy.h:75
fg_finish
FGAPI fg_err fg_finish()
Sync all rendering operations till this point.