I took a quick stab at using the buffer protocol, it’s working and looking rather hopeful, but it’s gonna need some spit and polish and testing before i can submit it.
size | time in seconds |
---|---|
512px | 0.004001s |
1024px | 0.015502s |
2048px | 0.056007s |
4096px | 0.208527s |
8192px | 0.86661s |
just in case anyone wants to play
source/blender/python/intern/bpy_rna_array.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index 4cc3c4c0fae..4a6943fd41f 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -303,6 +303,15 @@ static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop,
/* validate type first because length validation may modify property array length */
+ /* TODO: This needs some actual checking of things. */
+ if (PyObject_CheckBuffer(rvalue)) {
+ Py_buffer buf;
+ if (PyObject_GetBuffer(rvalue, &buf, PyBUF_C_CONTIGUOUS) == 0) {
+ *totitem = buf.len / buf.itemsize;
+ PyBuffer_Release(&buf);
+ return 0;
+ }
+ }
#ifdef USE_MATHUTILS
if (lvalue_dim == 0) { /* only valid for first level array */
@@ -394,6 +403,15 @@ static char *copy_values(
return NULL;
}
+ if (PyObject_CheckBuffer(seq))
+ {
+ Py_buffer buf;
+ if (PyObject_GetBuffer(seq, &buf, PyBUF_C_CONTIGUOUS) == 0) {
+ memcpy(data, buf.buf, min(buf.len, seq_size * sizeof(float)));
+ PyBuffer_Release(&buf);
+ return data;
+ }
+ }
#ifdef USE_MATHUTILS
if (dim == 0) {
also updated benchmark code, cause the one in the opening post was accidentally producing doubles which needed conversion, so that took time/memory as well
import bpy
import numpy as np
import mathutils as ms
from datetime import datetime
def benchmark(size):
img = bpy.data.images.get("output")
if (img == None):
img = bpy.data.images.new("output", width=size, height=size, alpha=False, float_buffer=True)
if (size != img.generated_width):
img.generated_width = size
if (size != img.generated_height):
img.generated_height = size
pixel_data = np.ones(size*size*4, dtype=np.float32)
t0 = datetime.now()
img.pixels = pixel_data
t1 = datetime.now()
meth1 = (t1-t0).total_seconds()
print("|%spx|%ss" % ( size , meth1 ))
benchmark(512)
benchmark(1024)
benchmark(2048)
benchmark(4096)
benchmark(8192)