PeriDyno 1.0.0
Loading...
Searching...
No Matches
GPUTexture.cpp
Go to the documentation of this file.
1#include "GPUTexture.h"
2
3#include <Vector.h>
4
5#include <glad/glad.h>
6
7#ifdef CUDA_BACKEND
8#include <cuda_gl_interop.h>
9#endif
10
11#ifdef VK_BACKEND
12#include <VkSystem.h>
13#include <VkContext.h>
14
15#ifdef WIN32
16#include <handleapi.h>
17#else
18#include <unistd.h>
19#endif // WIN32
20
21#endif // VK_BACKEND
22
23
24namespace dyno
25{
26 template<typename T>
28 {
29 if (typeid(T) == typeid(dyno::Vec4f)) {
30 this->format = GL_RGBA;
31 this->internalFormat = GL_RGBA32F;
32 this->type = GL_FLOAT;
33 }
34 else if (typeid(T) == typeid(dyno::Vec3f)) {
35 this->format = GL_RGB;
36 this->internalFormat = GL_RGB32F;
37 this->type = GL_FLOAT;
38 }
39 else if (typeid(T) == typeid(dyno::Vec3u)) {
40 this->format = GL_RGB;
41 this->internalFormat = GL_RGB8;
42 this->type = GL_UNSIGNED_BYTE;
43 }
44
46 }
47
48 template<typename T>
50 {
51 return width > 0 && height > 0;
52 }
53
54
55 template<typename T>
57 {
58#ifdef CUDA_BACKEND
59 buffer.assign(data);
60#endif // CUDA_BACKEND
61
62#ifdef VK_BACKEND
63
64 temp.assign(data);
65
66 VkBuffer src = data.buffer();
67 int size = data.size() * sizeof(T);
69 auto device = ctx->deviceHandle();
70
71 if (this->width != data.nx() ||
72 this->height != data.ny()) {
73
74 this->width = data.nx();
75 this->height = data.ny();
76 this->resized = true;
77
78 // allocate buffer
79 // free current buffer
80 vkDestroyBuffer(device, buffer, nullptr);
81 vkFreeMemory(device, memory, nullptr);
82
83 VkExternalMemoryHandleTypeFlags type;
84 // OS platforms
85#ifdef WIN32
86 type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
87#else
88 type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
89#endif
90
91 // create vulkan buffer
92 {
93 VkBufferCreateInfo bufferInfo{};
94 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
95 bufferInfo.size = size;
96 bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
97 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
98
99 VkExternalMemoryBufferCreateInfo externalInfo{};
100 externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
101 externalInfo.handleTypes = type;
102 bufferInfo.pNext = &externalInfo;
103
104 if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
105 throw std::runtime_error("failed to create buffer!");
106 }
107 }
108
109 // create memory
110 {
111 VkMemoryRequirements memRequirements;
112 vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
113
114 VkMemoryAllocateInfo allocInfo{};
115 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
116 allocInfo.allocationSize = memRequirements.size;
117 allocInfo.memoryTypeIndex = ctx->getMemoryType(memRequirements.memoryTypeBits,
118 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
119
120 // enable export memory
121 VkExportMemoryAllocateInfo memoryHandleEx{};
122 memoryHandleEx.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
123 memoryHandleEx.handleTypes = type;
124 allocInfo.pNext = &memoryHandleEx; // <-- Enabling Export
125
126 if (vkAllocateMemory(device, &allocInfo, nullptr, &memory) != VK_SUCCESS) {
127 throw std::runtime_error("failed to allocate buffer memory!");
128 }
129 }
130
131 vkBindBufferMemory(device, buffer, memory, 0);
132
133 }
134
135 // get the real allocated size of the buffer
136 VkMemoryRequirements req;
137 vkGetBufferMemoryRequirements(device, buffer, &req);
138
139 // copy data
140 {
141 if (copyCmd == VK_NULL_HANDLE) {
142 copyCmd = ctx->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
143 }
144
145 // begin
146 VkCommandBufferBeginInfo beginInfo{};
147 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
148 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
149 VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &beginInfo));
150
151 VkBufferCopy copyRegion{};
152 copyRegion.srcOffset = 0; // Optional
153 copyRegion.dstOffset = 0; // Optional
154 copyRegion.size = size;
155 vkCmdCopyBuffer(copyCmd, src, buffer, 1, &copyRegion);
156
157 // end and flush
158 ctx->flushCommandBuffer(copyCmd, ctx->transferQueue, false);
159 }
160
161 {
162 //test copy back
164 wtf.resize(width, height);
165
166 // begin
167 VkCommandBufferBeginInfo beginInfo{};
168 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
169 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
170 VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &beginInfo));
171
172 VkBufferCopy copyRegion{};
173 copyRegion.srcOffset = 0; // Optional
174 copyRegion.dstOffset = 0; // Optional
175 copyRegion.size = size;
176 vkCmdCopyBuffer(copyCmd, buffer, wtf.buffer(), 1, &copyRegion);
177
178 // end and flush
179 ctx->flushCommandBuffer(copyCmd, ctx->transferQueue, false);
180
181 temp.assign(wtf);
182 }
183
184 // get memory handle for importing
185#ifdef WIN32
186 VkMemoryGetWin32HandleInfoKHR info{};
187 info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
188 info.memory = memory;
189 info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
190
191 auto vkGetMemoryWin32HandleKHR =
192 PFN_vkGetMemoryWin32HandleKHR(vkGetDeviceProcAddr(device, "vkGetMemoryWin32HandleKHR"));
193 vkGetMemoryWin32HandleKHR(device, &info, &handle);
194#else
195 // TODO: for linux and other OS
196#endif
197
198#endif
199 }
200
201 template<typename T>
203 {
204#ifdef CUDA_BACKEND
205
206 if (buffer.size() <= 0) {
207 width = buffer.nx();
208 height = buffer.ny();
209 return;
210 }
211
212 if (width != buffer.nx() || height != buffer.ny()) {
213 // resize texture
214 this->release();
215 this->create();
216 this->resize(buffer.nx(), buffer.ny());
217
218 width = buffer.nx();
219 height = buffer.ny();
220
221 // re-register resource when size changed...
222 if (resource)
223 cuSafeCall(cudaGraphicsUnregisterResource(resource));
224 cuSafeCall(cudaGraphicsGLRegisterImage(&resource, this->id, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard));
225 }
226
227 // Map buffer objects to get CUDA device pointers
228 cudaArray* texture_ptr;
229 cuSafeCall(cudaGraphicsMapResources(1, &resource));
230 cuSafeCall(cudaGraphicsSubResourceGetMappedArray(&texture_ptr, resource, 0, 0));
231
232 // copy data with pitch
233 cuSafeCall(cudaMemcpy2DToArray(texture_ptr, 0, 0,
234 buffer.begin(), buffer.pitch(), buffer.nx() * sizeof(T), buffer.ny(),
235 cudaMemcpyDeviceToDevice));
236
237 cuSafeCall(cudaGraphicsUnmapResources(1, &resource));
238
239#endif // CUDA_BACKEND
240
241
242#ifdef VK_BACKEND
243
244 if (width <= 0 || height <= 0)
245 return;
246
247 if (this->resized)
248 {
249 this->resized = false;
250
251 // re-import memory object
252 if (memoryObject)
253 glDeleteMemoryObjectsEXT(1, &memoryObject);
254 glCreateMemoryObjectsEXT(1, &memoryObject);
255
256#ifdef WIN32
257 glImportMemoryWin32HandleEXT(memoryObject,
258 width * height * sizeof(T) * 2,
259 GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, handle);
260#else
261 //glImportMemoryFdEXT(bufGl.memoryObject, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, bufGl.fd);
262 // fd got consumed
263 //bufGl.fd = -1;
264#endif
265 // named buffer
266 if (this->id != GL_INVALID_INDEX)
267 glDeleteTextures(1, &this->id);
268
269 //glGenTextures(1, &this->id);
270 glCreateTextures(GL_TEXTURE_2D, 1, &this->id);
271 glBindTexture(GL_TEXTURE_2D, this->id);
272 //this->create();
273
274 glTextureParameteri(this->id, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING_EXT);
275
276 glCheckError();
277
278 //glTexStorageMem2DEXT(GL_TEXTURE_2D,
279 // 1, GL_RGBA32F, width, height, memoryObject, 0);
280
281 glTextureStorageMem2DEXT(this->id,
282 1, GL_RGBA32F, width, height, memoryObject, 0);
283
284 glCheckError();
285
286 //Texture2D::load(temp.nx(), temp.ny(), temp.handle()->data());
287
288 glCheckError();
289 }
290
291
292#endif // VK_BACKEND
293 }
294}
295
296
297
298
299
#define glCheckError()
#define VK_CHECK_RESULT(f)
Definition VulkanTools.h:55
virtual void create() override
Definition Texture.cpp:63
virtual void resize(int w, int h)
Definition Texture.cpp:81
unsigned int internalFormat
Definition Texture.h:40
virtual void release() override
Definition Texture.cpp:25
unsigned int format
Definition Texture.h:41
unsigned int type
Definition Texture.h:42
VkDevice deviceHandle()
Definition VkContext.h:26
VkContext * currentContext()
Definition VkSystem.h:21
static VkSystem * instance()
Definition VkSystem.cpp:10
bool isValid() const
virtual void create() override
void load(dyno::DArray2D< T > data)
#define T(t)
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
Vector< uint, 3 > Vec3u
Definition Vector3D.h:96
Vector< float, 4 > Vec4f
Definition Vector4D.h:86
Array2D< T, DeviceType::GPU > DArray2D
Definition Array2D.inl:90
Vector< float, 3 > Vec3f
Definition Vector3D.h:93