Code below does what is intended using code from grapics api interop
I’ll proceed with extension improvement…
I have a small problem running the code in vscode jupyter notebook and as a file from vscode… I’ll describe it in the follow up post, after I reduce it to the minimum reproducible.
Runs with no errors if launched as:
python example.py
# example.py
import ctypes
import numpy as np
from PIL import Image
from cuda import cudart
from cuda.cudart import cudaGraphicsRegisterFlags as GLFlags
import numba.cuda as nbcuda
import moderngl as mgl
#####################################################
# add 0.2 to the value
@nbcuda.jit
def shift_02(x):
idx = nbcuda.grid(1)
x[idx] = x[idx] + 0.2
###################################################
# wrap the raw pointer into DeviceNDArray
def gl_NDArray(ptr, shape, dtype=np.float32, strides=None, order="C"):
shape, strides, dtype = nbcuda.api.prepare_shape_strides_dtype(
shape, strides, dtype, order
)
datasize = nbcuda.driver.memory_size_from_info(shape, strides, dtype.itemsize)
ctx = nbcuda.current_context()
c_ptr = ctypes.c_uint64(ptr)
mem = nbcuda.driver.MemoryPointer(ctx, c_ptr, datasize)
return nbcuda.cudadrv.devicearray.DeviceNDArray(shape, strides, dtype, gpu_data=mem)
#####################################
# save fbo image into file
def save_image(fbo, name):
data = fbo.read(components=3)
image = Image.frombytes("RGB", fbo.size, data)
image.save(name)
##################################################################
# these shaders do nothing just passing the data along the pipeline
vert_code = """
#version 330
in vec2 in_vert;
in vec3 in_color;
out vec3 color;
void main() {
gl_Position = vec4(in_vert, 0.0, 1.0);
color = in_color;
}
"""
frag_code = """
#version 330
in vec3 color;
out vec4 fragColor;
void main(){
fragColor = vec4(color, 1.0);
}
"""
ctx = mgl.create_context(standalone=True)
prog = ctx.program(vertex_shader=vert_code, fragment_shader=frag_code)
# vertices for triangle with Red Green and Blue colors
vertices = np.array(
# X Y x y x y
[-0.6, -0.6, 1.0, 0.0, 0.0, 0.6, -0.6, 0.0, 1.0, 0.0, 0.0, 0.6, 0.0, 0.0, 1.0],
dtype="f4",
)
# init VBO, VAO and FBO
vbo = ctx.buffer(vertices)
vao = ctx.simple_vertex_array(prog, vbo, "in_vert", "in_color")
fbo = ctx.framebuffer(color_attachments=[ctx.texture((512, 512), 4)])
fbo.use()
# Get CUDA pointer to VBO
err, gl_resource = cudart.cudaGraphicsGLRegisterBuffer(
vbo.glo, GLFlags.cudaGraphicsRegisterFlagsNone
)
(err,) = cudart.cudaGraphicsMapResources(1, gl_resource, 0)
# get raw pointer to device array
(err, dev_ptr, dev_ptr_size) = cudart.cudaGraphicsResourceGetMappedPointer(gl_resource)
# wrap into DeviceNDArray
vbo_arr = gl_NDArray(dev_ptr, vertices.size)
# rendering
# 1st render as is
ctx.clear()
vao.render(mgl.TRIANGLES)
save_image(fbo, "image1.jpg")
# 2nd render after numba kernel call
ctx.clear()
shift_02[1,2](vbo_arr) # shift coordinates (x,y) of first point
nbcuda.synchronize()
vao.render(mgl.TRIANGLES)
save_image(fbo, "image2.jpg")
# CUDA cleanup
(err,) = cudart.cudaGraphicsUnmapResources(1, gl_resource, 0)
(err,) = cudart.cudaGraphicsUnregisterResource(gl_resource)