diff --git a/c_api/include/taichi/taichi_opengl.h b/c_api/include/taichi/taichi_opengl.h index 925e1f8a75c9f..ce255a2eea7d0 100644 --- a/c_api/include/taichi/taichi_opengl.h +++ b/c_api/include/taichi/taichi_opengl.h @@ -11,27 +11,36 @@ typedef struct TiOpenglRuntimeInteropInfo { void *get_proc_addr; } TiOpenglRuntimeInteropInfo; +// Structure `TiOpenglMemoryInteropInfo` +typedef struct TiOpenglMemoryInteropInfo { + GLuint buffer; + GLsizeiptr size; +} TiOpenglMemoryInteropInfo; + +// Structure `TiOpenglImageInteropInfo` +typedef struct TiOpenglImageInteropInfo { + GLuint texture; + GLenum target; + GLsizei levels; + GLenum format; + GLsizei width; + GLsizei height; + GLsizei depth; +} TiOpenglImageInteropInfo; + // Function `ti_import_opengl_runtime` -TI_DLL_EXPORT void TI_API_CALL -ti_import_opengl_runtime(TiRuntime runtime, - TiOpenglRuntimeInteropInfo *interop_info); +TI_DLL_EXPORT TiRuntime TI_API_CALL +ti_import_opengl_runtime(TiOpenglRuntimeInteropInfo *interop_info); // Function `ti_export_opengl_runtime` TI_DLL_EXPORT void TI_API_CALL ti_export_opengl_runtime(TiRuntime runtime, TiOpenglRuntimeInteropInfo *interop_info); -// Structure `TiOpenglMemoryInteropInfo` -typedef struct TiOpenglMemoryInteropInfo { - GLuint buffer; - uint64_t size; -} TiOpenglMemoryInteropInfo; - // Function `ti_import_opengl_memory` -TI_DLL_EXPORT void TI_API_CALL +TI_DLL_EXPORT TiMemory TI_API_CALL ti_import_opengl_memory(TiRuntime runtime, - TiMemory memory, - TiOpenglMemoryInteropInfo *interop_info); + const TiOpenglMemoryInteropInfo *interop_info); // Function `ti_export_opengl_memory` TI_DLL_EXPORT void TI_API_CALL @@ -39,6 +48,17 @@ ti_export_opengl_memory(TiRuntime runtime, TiMemory memory, TiOpenglMemoryInteropInfo *interop_info); +// Function `ti_import_opengl_image` +TI_DLL_EXPORT TiImage TI_API_CALL +ti_import_opengl_image(TiRuntime runtime, + const TiOpenglImageInteropInfo *interop_info); + +// Function `ti_export_opengl_image` +TI_DLL_EXPORT void TI_API_CALL +ti_export_opengl_image(TiRuntime runtime, + TiImage image, + TiOpenglImageInteropInfo *interop_info); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/c_api/src/taichi_opengl_impl.cpp b/c_api/src/taichi_opengl_impl.cpp index ff9d7f290c350..835cd22b8e4a0 100644 --- a/c_api/src/taichi_opengl_impl.cpp +++ b/c_api/src/taichi_opengl_impl.cpp @@ -27,6 +27,22 @@ void ti_export_opengl_runtime(TiRuntime runtime, TI_CAPI_TRY_CATCH_END(); } +TiMemory ti_import_opengl_memory(TiRuntime runtime, + TiOpenglMemoryInteropInfo *interop_info) { + TiMemory out = TI_NULL_HANDLE; + TI_CAPI_TRY_CATCH_BEGIN(); + TI_CAPI_ARGUMENT_NULL_RV(runtime); + TI_CAPI_ARGUMENT_NULL_RV(interop_info); + + OpenglRuntime *runtime2 = static_cast((Runtime *)runtime); + taichi::lang::DeviceAllocation devalloc{}; + devalloc.device = &runtime2->get_gl(); + devalloc.alloc_id = (taichi::lang::DeviceAllocationId)interop_info->buffer; + out = devalloc2devmem(*runtime2, devalloc); + TI_CAPI_TRY_CATCH_END(); + return out; +} + void ti_export_opengl_memory(TiRuntime runtime, TiMemory memory, TiOpenglMemoryInteropInfo *interop_info) { @@ -39,7 +55,56 @@ void ti_export_opengl_memory(TiRuntime runtime, OpenglRuntime *runtime2 = static_cast((Runtime *)runtime); taichi::lang::DeviceAllocation devalloc = devmem2devalloc(*runtime2, memory); interop_info->buffer = devalloc.alloc_id; - interop_info->size = runtime2->get_gl().get_devalloc_size(devalloc); + interop_info->size = + (GLsizeiptr)runtime2->get_gl().get_devalloc_size(devalloc); + TI_CAPI_TRY_CATCH_END(); +} + +TiImage ti_import_opengl_image(TiRuntime runtime, + TiOpenglImageInteropInfo *interop_info) { + TiImage out = TI_NULL_HANDLE; + TI_CAPI_TRY_CATCH_BEGIN(); + TI_CAPI_ARGUMENT_NULL_RV(runtime); + TI_CAPI_ARGUMENT_NULL_RV(interop_info); + TI_CAPI_INVALID_INTEROP_ARCH_RV(((Runtime *)runtime)->arch, opengl); + + OpenglRuntime *runtime2 = static_cast((Runtime *)runtime); + taichi::lang::opengl::GLImageAllocation gl_image{}; + gl_image.target = interop_info->target; + gl_image.levels = interop_info->levels; + gl_image.format = interop_info->format; + gl_image.width = interop_info->width; + gl_image.height = interop_info->height; + gl_image.depth = interop_info->depth; + gl_image.external = true; + taichi::lang::DeviceAllocation devalloc = runtime2->get_gl().import_image( + interop_info->texture, std::move(gl_image)); + out = devalloc2devimg(*runtime2, devalloc); + TI_CAPI_TRY_CATCH_END(); + return out; +} + +void ti_export_opengl_image(TiRuntime runtime, + TiImage image, + TiOpenglImageInteropInfo *interop_info) { + TI_CAPI_TRY_CATCH_BEGIN(); + TI_CAPI_ARGUMENT_NULL(runtime); + TI_CAPI_ARGUMENT_NULL(image); + TI_CAPI_ARGUMENT_NULL(interop_info); + TI_CAPI_INVALID_INTEROP_ARCH(((Runtime *)runtime)->arch, opengl); + + OpenglRuntime *runtime2 = static_cast((Runtime *)runtime); + taichi::lang::DeviceAllocation devalloc = devimg2devalloc(*runtime2, image); + GLuint texture = (GLuint)devalloc.alloc_id; + const taichi::lang::opengl::GLImageAllocation &gl_image = + runtime2->get_gl().get_gl_image(texture); + interop_info->texture = texture; + interop_info->target = gl_image.target; + interop_info->levels = gl_image.levels; + interop_info->format = gl_image.format; + interop_info->width = gl_image.width; + interop_info->height = gl_image.height; + interop_info->depth = gl_image.depth; TI_CAPI_TRY_CATCH_END(); } diff --git a/c_api/taichi.json b/c_api/taichi.json index ba4c77302de75..a25922738f2cc 100644 --- a/c_api/taichi.json +++ b/c_api/taichi.json @@ -1347,11 +1347,60 @@ } ] }, + { + "name": "opengl_memory_interop_info", + "type": "structure", + "fields": [ + { + "name": "buffer", + "type": "GLuint" + }, + { + "name": "size", + "type": "GLsizeiptr" + } + ] + }, + { + "name": "opengl_image_interop_info", + "type": "structure", + "fields": [ + { + "name": "texture", + "type": "GLuint" + }, + { + "name": "target", + "type": "GLenum" + }, + { + "name": "levels", + "type": "GLsizei" + }, + { + "name": "format", + "type": "GLenum" + }, + { + "name": "width", + "type": "GLsizei" + }, + { + "name": "height", + "type": "GLsizei" + }, + { + "name": "depth", + "type": "GLsizei" + } + ] + }, { "name": "import_opengl_runtime", "type": "function", "parameters": [ { + "name": "@return", "type": "handle.runtime" }, { @@ -1376,21 +1425,25 @@ ] }, { - "name": "opengl_memory_interop_info", - "type": "structure", - "fields": [ + "name": "import_opengl_memory", + "type": "function", + "parameters": [ { - "name": "buffer", - "type": "GLuint" + "name": "@return", + "type": "handle.memory" }, { - "name": "size", - "type": "uint64_t" + "type": "handle.runtime" + }, + { + "name": "interop_info", + "type": "structure.opengl_memory_interop_info", + "by_ref": true } ] }, { - "name": "import_opengl_memory", + "name": "export_opengl_memory", "type": "function", "parameters": [ { @@ -1407,18 +1460,36 @@ ] }, { - "name": "export_opengl_memory", + "name": "import_opengl_image", "type": "function", "parameters": [ + { + "name": "@return", + "type": "handle.image" + }, { "type": "handle.runtime" }, { - "type": "handle.memory" + "name": "interop_info", + "type": "structure.opengl_image_interop_info", + "by_ref": true + } + ] + }, + { + "name": "export_opengl_image", + "type": "function", + "parameters": [ + { + "type": "handle.runtime" + }, + { + "type": "handle.image" }, { "name": "interop_info", - "type": "structure.opengl_memory_interop_info", + "type": "structure.opengl_image_interop_info", "by_mut": true } ] diff --git a/misc/generate_c_api.py b/misc/generate_c_api.py index a7dd56766de13..f34c9ad865a6e 100644 --- a/misc/generate_c_api.py +++ b/misc/generate_c_api.py @@ -331,6 +331,9 @@ def generate_module_header(module): BuiltInType("char", "char"), BuiltInType("GLuint", "GLuint"), BuiltInType("VkDeviceMemory", "VkDeviceMemory"), + BuiltInType("GLenum", "GLenum"), + BuiltInType("GLsizei", "GLsizei"), + BuiltInType("GLsizeiptr", "GLsizeiptr"), } for module in Module.load_all(builtin_tys): diff --git a/misc/generate_c_api_docs.py b/misc/generate_c_api_docs.py index 4e267b716caf9..53e51d09aff90 100644 --- a/misc/generate_c_api_docs.py +++ b/misc/generate_c_api_docs.py @@ -91,6 +91,9 @@ def generate_module_header(module): BuiltInType("char", "char"), BuiltInType("GLuint", "GLuint"), BuiltInType("VkDeviceMemory", "VkDeviceMemory"), + BuiltInType("GLenum", "GLenum"), + BuiltInType("GLsizei", "GLsizei"), + BuiltInType("GLsizeiptr", "GLsizeiptr"), } for module in Module.load_all(builtin_tys): diff --git a/taichi/rhi/opengl/opengl_device.cpp b/taichi/rhi/opengl/opengl_device.cpp index a531a227623fa..79c75afa7ccdd 100644 --- a/taichi/rhi/opengl/opengl_device.cpp +++ b/taichi/rhi/opengl/opengl_device.cpp @@ -336,7 +336,7 @@ RhiResult GLCommandList::bind_shader_resources(ShaderResourceSet *res, auto cmd = std::make_unique(); cmd->texture = texture; cmd->index = binding; - cmd->target = device_->get_image_gl_dims(texture); + cmd->target = device_->get_gl_image(texture).target; recorded_commands_.push_back(std::move(cmd)); } @@ -692,18 +692,39 @@ DeviceAllocation GLDevice::create_image(const ImageParams ¶ms) { alloc.device = this; alloc.alloc_id = tex; - image_to_dims_[tex] = gl_texture_dims; - image_to_int_format_[tex] = format; + GLImageAllocation gl_image{}; + gl_image.target = gl_texture_dims; + gl_image.levels = 1; + gl_image.format = format; + gl_image.width = params.x; + gl_image.height = params.y; + gl_image.depth = params.z; + gl_image.external = false; + image_allocs_[tex] = std::move(gl_image); return alloc; } void GLDevice::destroy_image(DeviceAllocation handle) { GLuint texture = GLuint(handle.alloc_id); - glDeleteTextures(1, &texture); - check_opengl_error("glDeleteTextures"); - image_to_dims_.erase(handle.alloc_id); - image_to_int_format_.erase(handle.alloc_id); + auto it = image_allocs_.find(texture); + if (it != image_allocs_.end()) { + if (!it->second.external) { + glDeleteTextures(1, &texture); + check_opengl_error("glDeleteTextures"); + } + image_allocs_.erase(it); + } +} + +DeviceAllocation GLDevice::import_image(GLuint texture, + GLImageAllocation &&gl_image) { + image_allocs_[texture] = std::move(gl_image); + + DeviceAllocation out{}; + out.device = this; + out.alloc_id = (DeviceAllocationId)texture; + return out; } void GLDevice::image_transition(DeviceAllocation img, @@ -835,8 +856,9 @@ void GLCommandList::CmdImageTransition::execute() { } void GLCommandList::CmdBufferToImage::execute() { - GLuint image_dims = device->get_image_gl_dims(image); - GLuint image_internal_format = device->get_image_gl_internal_format(image); + const GLImageAllocation &gl_image = device->get_gl_image(image); + GLuint image_dims = gl_image.target; + GLuint image_internal_format = gl_image.format; GLuint image_format = gl_internal_format_to_format.at(image_internal_format); GLuint gl_type = gl_internal_format_to_type.at(image_internal_format); @@ -869,8 +891,9 @@ void GLCommandList::CmdBufferToImage::execute() { } void GLCommandList::CmdImageToBuffer::execute() { - auto image_dims = device->get_image_gl_dims(image); - auto image_format = device->get_image_gl_internal_format(image); + const GLImageAllocation &gl_image = device->get_gl_image(image); + auto image_dims = gl_image.target; + auto image_format = gl_image.format; auto gl_type = gl_internal_format_to_type.at(image_format); auto unsized_format = gl_internal_format_to_format.at(image_format); diff --git a/taichi/rhi/opengl/opengl_device.h b/taichi/rhi/opengl/opengl_device.h index a77c1a3a37753..221d167144827 100644 --- a/taichi/rhi/opengl/opengl_device.h +++ b/taichi/rhi/opengl/opengl_device.h @@ -178,7 +178,7 @@ class GLCommandList : public CommandList { struct CmdBufferToImage : public Cmd { BufferImageCopyParams params; - GLuint image{0}; + DeviceAllocationId image{0}; GLuint buffer{0}; size_t offset{0}; GLDevice *device{nullptr}; @@ -187,7 +187,7 @@ class GLCommandList : public CommandList { struct CmdImageToBuffer : public Cmd { BufferImageCopyParams params; - GLuint image{0}; + DeviceAllocationId image{0}; GLuint buffer{0}; size_t offset{0}; GLDevice *device{nullptr}; @@ -218,6 +218,16 @@ class GLStream : public Stream { GLDevice *device_{nullptr}; }; +struct GLImageAllocation { + GLenum target; + GLsizei levels; + GLenum format; + GLsizei width; + GLsizei height; + GLsizei depth; + bool external; +}; + class GLDevice : public GraphicsDevice { public: GLDevice(); @@ -273,6 +283,8 @@ class GLDevice : public GraphicsDevice { DeviceAllocation create_image(const ImageParams ¶ms) override; void destroy_image(DeviceAllocation handle) override; + DeviceAllocation import_image(GLuint texture, GLImageAllocation &&gl_image); + void image_transition(DeviceAllocation img, ImageLayout old_layout, ImageLayout new_layout) override; @@ -285,19 +297,14 @@ class GLDevice : public GraphicsDevice { ImageLayout img_layout, const BufferImageCopyParams ¶ms) override; - GLuint get_image_gl_dims(GLuint image) const { - return image_to_dims_.at(image); - } - - GLuint get_image_gl_internal_format(GLuint image) const { - return image_to_int_format_.at(image); + GLImageAllocation get_gl_image(GLuint image) const { + return image_allocs_.at(image); } private: GLStream stream_; std::unordered_map buffer_to_access_; - std::unordered_map image_to_dims_; - std::unordered_map image_to_int_format_; + std::unordered_map image_allocs_; }; class GLSurface : public Surface {