diff options
-rw-r--r-- | source/blender/gpu/GPU_common.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/GPU_framebuffer.h | 5 | ||||
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 6 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.cc | 19 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer_private.hh | 9 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.cc | 19 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture_private.hh | 7 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_framebuffer.c | 58 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_framebuffer.h | 7 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_texture.c | 32 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_texture.h | 3 | ||||
m--------- | source/tools | 0 |
12 files changed, 142 insertions, 24 deletions
diff --git a/source/blender/gpu/GPU_common.h b/source/blender/gpu/GPU_common.h index 1be74701176..bc57a381f00 100644 --- a/source/blender/gpu/GPU_common.h +++ b/source/blender/gpu/GPU_common.h @@ -24,6 +24,7 @@ #pragma once #define PROGRAM_NO_OPTI 0 +#define USE_PY_REFERENCES 1 #if defined(NDEBUG) # define TRUST_NO_ONE 0 diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index af94c1fb0e6..ccab80c5702 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -209,6 +209,11 @@ void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *fb, void (*callback)(void *userData, int level), void *userData); +#if USE_PY_REFERENCES +void **GPU_framebuffer_py_reference_get(GPUFrameBuffer *gpu_fb); +void GPU_framebuffer_py_reference_set(GPUFrameBuffer *gpu_fb, void **py_ref); +#endif + void GPU_framebuffer_push(GPUFrameBuffer *fb); GPUFrameBuffer *GPU_framebuffer_pop(void); uint GPU_framebuffer_stack_level_get(void); diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index d9a01663de0..21d3070e252 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -269,6 +269,12 @@ bool GPU_texture_cube(const GPUTexture *tex); bool GPU_texture_depth(const GPUTexture *tex); bool GPU_texture_stencil(const GPUTexture *tex); bool GPU_texture_integer(const GPUTexture *tex); + +#if USE_PY_REFERENCES +void **GPU_texture_py_reference_get(GPUTexture *tex); +void GPU_texture_py_reference_set(GPUTexture *tex, void **py_ref); +#endif + int GPU_texture_opengl_bindcode(const GPUTexture *tex); void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size); diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 1e3cf479462..f593a5e4182 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -71,6 +71,12 @@ FrameBuffer::~FrameBuffer() reinterpret_cast<Texture *>(attachment.tex)->detach_from(this); } } + +#if USE_PY_REFERENCES + if (this->py_ref) { + *this->py_ref = nullptr; + } +#endif } /** \} */ @@ -473,6 +479,19 @@ void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *gpu_fb, unwrap(gpu_fb)->recursive_downsample(max_lvl, callback, userData); } +#if USE_PY_REFERENCES +void **GPU_framebuffer_py_reference_get(GPUFrameBuffer *gpu_fb) +{ + return unwrap(gpu_fb)->py_ref; +} + +void GPU_framebuffer_py_reference_set(GPUFrameBuffer *gpu_fb, void **py_ref) +{ + BLI_assert(ref == nullptr || unwrap(gpu_fb)->py_ref == nullptr); + unwrap(gpu_fb)->py_ref = py_ref; +} +#endif + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index d63d72cf4f7..6e4be6de42a 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -100,6 +100,15 @@ class FrameBuffer { bool scissor_test_ = false; bool dirty_state_ = true; +#if USE_PY_REFERENCES + public: + /** + * Reference of a pointer that needs to be cleaned when deallocating the frame-buffer. + * Points to #BPyGPUFrameBuffer.fb + */ + void **py_ref = nullptr; +#endif + public: FrameBuffer(const char *name); virtual ~FrameBuffer(); diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index c3e9058c6c7..b0b0fb970d7 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -60,6 +60,12 @@ Texture::~Texture() fb_[i]->attachment_remove(fb_attachment_[i]); } } + +#if USE_PY_REFERENCES + if (this->py_ref) { + *this->py_ref = nullptr; + } +#endif } bool Texture::init_1D(int w, int layers, eGPUTextureFormat format) @@ -581,6 +587,19 @@ bool GPU_texture_array(const GPUTexture *tex) return (reinterpret_cast<const Texture *>(tex)->type_get() & GPU_TEXTURE_ARRAY) != 0; } +#if USE_PY_REFERENCES +void **GPU_texture_py_reference_get(GPUTexture *tex) +{ + return unwrap(tex)->py_ref; +} + +void GPU_texture_py_reference_set(GPUTexture *tex, void **py_ref) +{ + BLI_assert(py_ref == nullptr || unwrap(tex)->py_ref == nullptr); + unwrap(tex)->py_ref = py_ref; +} +#endif + /* TODO remove */ int GPU_texture_opengl_bindcode(const GPUTexture *tex) { diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index 3d808bce152..9f185e03493 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -80,6 +80,13 @@ class Texture { int refcount = 1; /** Width & Height (of source data), optional. */ int src_w = 0, src_h = 0; +#if USE_PY_REFERENCES + /** + * Reference of a pointer that needs to be cleaned when deallocating the texture. + * Points to #BPyGPUTexture.tex + */ + void **py_ref = nullptr; +#endif protected: /* ---- Texture format (immutable after init). ---- */ diff --git a/source/blender/python/gpu/gpu_py_framebuffer.c b/source/blender/python/gpu/gpu_py_framebuffer.c index bc393aaafa4..0e58327737a 100644 --- a/source/blender/python/gpu/gpu_py_framebuffer.c +++ b/source/blender/python/gpu/gpu_py_framebuffer.c @@ -46,13 +46,7 @@ static int pygpu_framebuffer_valid_check(BPyGPUFrameBuffer *bpygpu_fb) { if (UNLIKELY(bpygpu_fb->fb == NULL)) { - PyErr_SetString(PyExc_ReferenceError, -#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD - "GPU framebuffer was freed, no further access is valid" -#else - "GPU framebuffer: internal error" -#endif - ); + PyErr_SetString(PyExc_ReferenceError, "GPU framebuffer was freed, no further access is valid"); return -1; } return 0; @@ -68,10 +62,6 @@ static int pygpu_framebuffer_valid_check(BPyGPUFrameBuffer *bpygpu_fb) static void pygpu_framebuffer_free_if_possible(GPUFrameBuffer *fb) { - if (!fb) { - return; - } - if (GPU_is_init()) { GPU_framebuffer_free(fb); } @@ -80,6 +70,21 @@ static void pygpu_framebuffer_free_if_possible(GPUFrameBuffer *fb) } } +static void pygpu_framebuffer_free_safe(BPyGPUFrameBuffer *self) +{ + if (self->fb) { +#if GPU_USE_PY_REFERENCES + GPU_framebuffer_py_reference_set(self->fb, NULL); + if (!self->shared_reference) +#endif + { + pygpu_framebuffer_free_if_possible(self->fb); + } + + self->fb = NULL; + } +} + /* Keep less than or equal to #FRAMEBUFFER_STACK_DEPTH */ #define GPU_PY_FRAMEBUFFER_STACK_LEN 16 @@ -336,7 +341,7 @@ static PyObject *pygpu_framebuffer__tp_new(PyTypeObject *UNUSED(self), GPUFrameBuffer *fb_python = GPU_framebuffer_create("fb_python"); GPU_framebuffer_config_array(fb_python, config, color_attachements_len + 1); - return BPyGPUFrameBuffer_CreatePyObject(fb_python); + return BPyGPUFrameBuffer_CreatePyObject(fb_python, false); } PyDoc_STRVAR(pygpu_framebuffer_is_bound_doc, @@ -459,15 +464,14 @@ PyDoc_STRVAR(pygpu_framebuffer_free_doc, static PyObject *pygpu_framebuffer_free(BPyGPUFrameBuffer *self) { PYGPU_FRAMEBUFFER_CHECK_OBJ(self); - pygpu_framebuffer_free_if_possible(self->fb); - self->fb = NULL; + pygpu_framebuffer_free_safe(self); Py_RETURN_NONE; } #endif static void BPyGPUFrameBuffer__tp_dealloc(BPyGPUFrameBuffer *self) { - pygpu_framebuffer_free_if_possible(self->fb); + pygpu_framebuffer_free_safe(self); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -531,13 +535,35 @@ PyTypeObject BPyGPUFrameBuffer_Type = { /** \name Public API * \{ */ -PyObject *BPyGPUFrameBuffer_CreatePyObject(GPUFrameBuffer *fb) +PyObject *BPyGPUFrameBuffer_CreatePyObject(GPUFrameBuffer *fb, bool shared_reference) { BPyGPUFrameBuffer *self; +#if GPU_USE_PY_REFERENCES + if (shared_reference) { + void **ref = GPU_framebuffer_py_reference_get(fb); + if (ref) { + /* Retrieve BPyGPUFrameBuffer reference. */ + self = POINTER_OFFSET(ref, -offsetof(BPyGPUFrameBuffer, fb)); + BLI_assert(self->fb == fb); + Py_INCREF(self); + return (PyObject *)self; + } + } +#else + UNUSED_VARS(shared_reference); +#endif + self = PyObject_New(BPyGPUFrameBuffer, &BPyGPUFrameBuffer_Type); self->fb = fb; +#if GPU_USE_PY_REFERENCES + self->shared_reference = shared_reference; + + BLI_assert(GPU_framebuffer_py_reference_get(fb) == NULL); + GPU_framebuffer_py_reference_set(fb, &self->fb); +#endif + return (PyObject *)self; } diff --git a/source/blender/python/gpu/gpu_py_framebuffer.h b/source/blender/python/gpu/gpu_py_framebuffer.h index 7113e7c35aa..0049cc2fac7 100644 --- a/source/blender/python/gpu/gpu_py_framebuffer.h +++ b/source/blender/python/gpu/gpu_py_framebuffer.h @@ -28,6 +28,11 @@ extern PyTypeObject BPyGPUFrameBuffer_Type; typedef struct BPyGPUFrameBuffer { PyObject_HEAD struct GPUFrameBuffer *fb; + +#if GPU_USE_PY_REFERENCES + bool shared_reference; +#endif } BPyGPUFrameBuffer; -PyObject *BPyGPUFrameBuffer_CreatePyObject(struct GPUFrameBuffer *fb) ATTR_NONNULL(1); +PyObject *BPyGPUFrameBuffer_CreatePyObject(struct GPUFrameBuffer *fb, bool shared_reference) + ATTR_NONNULL(1); diff --git a/source/blender/python/gpu/gpu_py_texture.c b/source/blender/python/gpu/gpu_py_texture.c index 1ae65c1dd11..9cc6a9df8fa 100644 --- a/source/blender/python/gpu/gpu_py_texture.c +++ b/source/blender/python/gpu/gpu_py_texture.c @@ -247,7 +247,7 @@ static PyObject *pygpu_texture__tp_new(PyTypeObject *UNUSED(self), PyObject *arg return NULL; } - return BPyGPUTexture_CreatePyObject(tex); + return BPyGPUTexture_CreatePyObject(tex, false); } PyDoc_STRVAR(pygpu_texture_width_doc, "Width of the texture.\n\n:type: `int`"); @@ -412,6 +412,9 @@ static PyObject *pygpu_texture_free(BPyGPUTexture *self) static void BPyGPUTexture__tp_dealloc(BPyGPUTexture *self) { if (self->tex) { +#if GPU_USE_PY_REFERENCES + GPU_texture_py_reference_set(self->tex, NULL); +#endif GPU_texture_free(self->tex); } Py_TYPE(self)->tp_free((PyObject *)self); @@ -535,10 +538,7 @@ static PyObject *pygpu_texture_from_image(PyObject *UNUSED(self), PyObject *arg) BKE_imageuser_default(&iuser); GPUTexture *tex = BKE_image_get_gpu_texture(ima, &iuser, NULL); - /* Increase the texture reference count. */ - GPU_texture_ref(tex); - - return BPyGPUTexture_CreatePyObject(tex); + return BPyGPUTexture_CreatePyObject(tex, true); } static struct PyMethodDef pygpu_texture__m_methods[] = { @@ -595,13 +595,33 @@ PyObject *bpygpu_texture_init(void) /** \name Public API * \{ */ -PyObject *BPyGPUTexture_CreatePyObject(GPUTexture *tex) +PyObject *BPyGPUTexture_CreatePyObject(GPUTexture *tex, bool shared_reference) { BPyGPUTexture *self; + if (shared_reference) { +#if GPU_USE_PY_REFERENCES + void **ref = GPU_texture_py_reference_get(tex); + if (ref) { + /* Retrieve BPyGPUTexture reference. */ + self = POINTER_OFFSET(ref, -offsetof(BPyGPUTexture, tex)); + BLI_assert(self->tex == tex); + Py_INCREF(self); + return (PyObject *)self; + } +#endif + + GPU_texture_ref(tex); + } + self = PyObject_New(BPyGPUTexture, &BPyGPUTexture_Type); self->tex = tex; +#if GPU_USE_PY_REFERENCES + BLI_assert(GPU_texture_py_reference_get(tex) == NULL); + GPU_texture_py_reference_set(tex, &self->tex); +#endif + return (PyObject *)self; } diff --git a/source/blender/python/gpu/gpu_py_texture.h b/source/blender/python/gpu/gpu_py_texture.h index 5130273f971..457ddcfc931 100644 --- a/source/blender/python/gpu/gpu_py_texture.h +++ b/source/blender/python/gpu/gpu_py_texture.h @@ -33,4 +33,5 @@ typedef struct BPyGPUTexture { int bpygpu_ParseTexture(PyObject *o, void *p); PyObject *bpygpu_texture_init(void); -PyObject *BPyGPUTexture_CreatePyObject(struct GPUTexture *tex) ATTR_NONNULL(1); +PyObject *BPyGPUTexture_CreatePyObject(struct GPUTexture *tex, bool weak_reference) + ATTR_NONNULL(1); diff --git a/source/tools b/source/tools -Subproject f99d29ae3e6ad44d45d79309454c45f8088781a +Subproject 2afbb8ec472cac5102eb239f57b006f8c938768 |