def __init__(self, ctx, queue, z_bounds, init_chunk_array_kernel): ''' ''' num_layers = z_bounds[1] - z_bounds[0] self.array_buffer = RenderBuffer(ctx, queue, self.dtype_array.itemsize, 0) # may not grow self.layer_buffer = RenderBuffer(ctx, queue, 2**14, 2**12) self.chunk_buffer = RenderBuffer(ctx, queue, 2**14, 2**12) # The chunks self.data, offset = self.array_buffer.allocate_data(self.dtype_array) self.layers = [ ChunkLayer(*self.layer_buffer.allocate_data(self.dtype_layer)) for i in range(num_layers) ] self.z_bounds = z_bounds self.x_bounds = (2**30, -2**30) self.y_bounds = (2**30, -2**30) self.chunk_layers_ptr = self.layer_buffer._d_buffer.int_ptr self.voxel_data = VoxelData(ctx, queue) self.init_chunk_array_kernel = init_chunk_array_kernel self.ctx = ctx self.queue = queue
def __init__(self, clctx, queue): ''' Constructor ''' self.clctx = clctx self.queue = queue # stores the objects of the scene. (data and ref) self.objects = set() self.lights = set() # stores the (byte)data of the objects self._obj_buffer = RenderBuffer(clctx, queue, 2**16, 2**15) # stores the references on the (byte)data. # these will be raytraced in the render process. self._obj_references = RenderBuffer(clctx, queue, 2**15, 2**14) # couldn't help myself but put this in a buffer... maybe sometimes we need multiple cameras. self._cam_buffer = RenderBuffer(clctx, queue, Camera.dtype.itemsize, Camera.dtype.itemsize) # The lights in the scene. These are referenced by _light_references self._light_buffer = RenderBuffer(clctx, queue, 2**9, 2**7) self._light_references = RenderBuffer(clctx, queue, 2**8, 2**6) # This camera will be passed to the render process self.camera = self.create_camera(position=(-2,-2,30), orientation=(1,0,0,0), bounds=(-2,2,1.5,-1.5), warp=4) self.raytrace_pgrm = build_program(clctx, "raytrace") self.raytrace = self.raytrace_pgrm.raytrace self.raytrace.set_scalar_arg_dtypes([None, None, None, numpy.uint32, None, None, None, None]) self._chunk_array = ChunkArray(self.clctx, self.queue, (0, 1) , self.raytrace_pgrm.init_chunk_array) """self._chunk_array.allocate_layer(0, x_bounds=(0, 2), y_bounds=(0, 2)) self._chunk_array.allocate_layer(1, x_bounds=(0, 2), y_bounds=(0, 2)) self._chunk_array.allocate_chunk(0, 0, 0, level=0) self._chunk_array.allocate_chunk(1, 0, 0, level=1) self._chunk_array.allocate_chunk(0, 0, 1, level=0) self._chunk_array.allocate_chunk(1, 0, 1, level=0) self._chunk_array.allocate_chunk(0, 1, 0, level=0) self._chunk_array.allocate_chunk(1, 1, 0, level=0) self._chunk_array.allocate_chunk(0, 1, 1, level=0) self._chunk_array.allocate_chunk(1, 1, 1, level=0) self._chunk_array.get_layer(0).chunk_offset = 0 chunk = self._chunk_array.get_chunk(0, 0, 0) chunk.voxel_data[:] = numpy.array([(random.randint(0,2), (0,0,0), (-1,-1,-1)) for i in range(32**3)], dtype=VoxelData.test_dtype) chunk = self._chunk_array.get_chunk(1, 0, 0) chunk.voxel_data[:] = numpy.array([(i % 2, (0,0,0), (-1,-1,-1)) for i in range(16**3)], dtype=VoxelData.test_dtype) chunk = self._chunk_array.get_chunk(0, 0, 1) chunk.voxel_data[:] = numpy.array([(random.randint(0,2), (0,0,0), (-1,-1,-1)) for i in range(32**3)], dtype=VoxelData.test_dtype) self._chunk_array.get_chunk(1, 0, 1).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(0, 1, 0).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(1, 1, 0).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(0, 1, 1).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(1, 1, 1).voxel_data[:] = chunk.voxel_data""" self.h_test_buffer = numpy.zeros((32,32,32), dtype=numpy.uint32) self.d_test_buffer = pyopencl.Buffer(clctx, pyopencl.mem_flags.READ_WRITE | pyopencl.mem_flags.COPY_HOST_PTR, hostbuf=self.h_test_buffer)
class Scene(object): ''' Stores a list of render objects and allocates them. ''' reference_t = numpy.dtype([ ('obj_type', numpy.short), ('obj_offset', numpy.uint32) ]) def __init__(self, clctx, queue): ''' Constructor ''' self.clctx = clctx self.queue = queue # stores the objects of the scene. (data and ref) self.objects = set() self.lights = set() # stores the (byte)data of the objects self._obj_buffer = RenderBuffer(clctx, queue, 2**16, 2**15) # stores the references on the (byte)data. # these will be raytraced in the render process. self._obj_references = RenderBuffer(clctx, queue, 2**15, 2**14) # couldn't help myself but put this in a buffer... maybe sometimes we need multiple cameras. self._cam_buffer = RenderBuffer(clctx, queue, Camera.dtype.itemsize, Camera.dtype.itemsize) # The lights in the scene. These are referenced by _light_references self._light_buffer = RenderBuffer(clctx, queue, 2**9, 2**7) self._light_references = RenderBuffer(clctx, queue, 2**8, 2**6) # This camera will be passed to the render process self.camera = self.create_camera(position=(-2,-2,30), orientation=(1,0,0,0), bounds=(-2,2,1.5,-1.5), warp=4) self.raytrace_pgrm = build_program(clctx, "raytrace") self.raytrace = self.raytrace_pgrm.raytrace self.raytrace.set_scalar_arg_dtypes([None, None, None, numpy.uint32, None, None, None, None]) self._chunk_array = ChunkArray(self.clctx, self.queue, (0, 1) , self.raytrace_pgrm.init_chunk_array) """self._chunk_array.allocate_layer(0, x_bounds=(0, 2), y_bounds=(0, 2)) self._chunk_array.allocate_layer(1, x_bounds=(0, 2), y_bounds=(0, 2)) self._chunk_array.allocate_chunk(0, 0, 0, level=0) self._chunk_array.allocate_chunk(1, 0, 0, level=1) self._chunk_array.allocate_chunk(0, 0, 1, level=0) self._chunk_array.allocate_chunk(1, 0, 1, level=0) self._chunk_array.allocate_chunk(0, 1, 0, level=0) self._chunk_array.allocate_chunk(1, 1, 0, level=0) self._chunk_array.allocate_chunk(0, 1, 1, level=0) self._chunk_array.allocate_chunk(1, 1, 1, level=0) self._chunk_array.get_layer(0).chunk_offset = 0 chunk = self._chunk_array.get_chunk(0, 0, 0) chunk.voxel_data[:] = numpy.array([(random.randint(0,2), (0,0,0), (-1,-1,-1)) for i in range(32**3)], dtype=VoxelData.test_dtype) chunk = self._chunk_array.get_chunk(1, 0, 0) chunk.voxel_data[:] = numpy.array([(i % 2, (0,0,0), (-1,-1,-1)) for i in range(16**3)], dtype=VoxelData.test_dtype) chunk = self._chunk_array.get_chunk(0, 0, 1) chunk.voxel_data[:] = numpy.array([(random.randint(0,2), (0,0,0), (-1,-1,-1)) for i in range(32**3)], dtype=VoxelData.test_dtype) self._chunk_array.get_chunk(1, 0, 1).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(0, 1, 0).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(1, 1, 0).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(0, 1, 1).voxel_data[:] = chunk.voxel_data self._chunk_array.get_chunk(1, 1, 1).voxel_data[:] = chunk.voxel_data""" self.h_test_buffer = numpy.zeros((32,32,32), dtype=numpy.uint32) self.d_test_buffer = pyopencl.Buffer(clctx, pyopencl.mem_flags.READ_WRITE | pyopencl.mem_flags.COPY_HOST_PTR, hostbuf=self.h_test_buffer) def _create_buffer_object(self, buff, cls, **kwargs): dtype = cls.dtype data = None if dtype is not None: data, offset = buff.allocate_data(dtype) obj = cls(data) for k,v in kwargs.items(): obj.__setattr__(k, v) return obj, offset def create_reference(self, ref_buffer, obj_type, obj_offset): ref, offset = ref_buffer.allocate_data(self.reference_t) ref['obj_type'] = obj_type ref['obj_offset'] = obj_offset return ref def create_object(self, name, **kwargs): cls = RenderObject._render_object_classes[name] obj, offset = self._create_buffer_object(self._obj_buffer, cls, **kwargs) ref = self.create_reference(self._obj_references, cls.type_id, offset) obj.data_ref = ref self.objects.add(obj) return obj def create_camera(self, **kwargs): cam, offset = self._create_buffer_object(self._cam_buffer, Camera, **kwargs) return cam def create_light(self, name, **kwargs): cls = RenderObject._light_classes[name] light, offset = self._create_buffer_object(self._light_buffer, cls, **kwargs) ref = self.create_reference(self._light_references, cls.type_id, offset) light.data_ref = ref return light def call_test(self): self.raytrace_pgrm.test_kernel(self.queue, (1,), None, self.d_test_buffer) pyopencl.enqueue_copy(self.queue, self.h_test_buffer, self.d_test_buffer) def render(self, img, size): self._obj_buffer.upload_buffer() self._obj_references.upload_buffer() self._cam_buffer.upload_buffer() self._light_buffer.upload_buffer() self._light_references.upload_buffer() """self.raytrace(self.queue, size, None, img, self._cam_buffer._d_buffer, self._obj_references.n_elements, self._obj_references._d_buffer, self._obj_buffer._d_buffer, self._light_references.n_elements, self._light_references._d_buffer, self._light_buffer._d_buffer, self.d_test_buffer)""" self.raytrace(self.queue, size, (16,8), img, self._cam_buffer._d_buffer, self._chunk_array.array_buffer._d_buffer, self._light_references.n_elements, self._light_references._d_buffer, self._light_buffer._d_buffer, self.d_test_buffer, self._chunk_array.voxel_data.level_buffers[0]._d_buffer) pyopencl.enqueue_copy(self.queue, self.h_test_buffer, self.d_test_buffer) #pyopencl.enqueue_copy(self.queue, self._chunk_array.array_buffer._h_buffer, self._chunk_array.array_buffer._d_buffer)
def test_renderbuffer(self): buffer = RenderBuffer(self.ctx, self.queue, 256, 64) b1 = buffer.allocate_array(256, numpy.dtype([("p", numpy.byte)])) b2 = buffer.allocate_array(16, numpy.dtype([("p", numpy.byte)]))
class ChunkArray(object): ''' Stores chunk layers in a array structure. ''' dtype_array = numpy.dtype( [ ('x_bounds', numpy.int32, 2), ('y_bounds', numpy.int32, 2), ('z_bounds', numpy.int32, 2), ('chunk_layers_ptr', numpy.uintp), ('chunks_ptr', numpy.uintp), ('voxel_levels_ptr', numpy.uintp, 6) ] ) dtype_layer = numpy.dtype( [ ('x_bounds', numpy.int32, 2), ('y_bounds', numpy.int32, 2), ('chunk_offset', numpy.uint32) ] ) dtype_chunk = numpy.dtype( [ ('level', numpy.int), ('voxel_offset', numpy.uint32) ] ) def __init__(self, ctx, queue, z_bounds, init_chunk_array_kernel): ''' ''' num_layers = z_bounds[1] - z_bounds[0] self.array_buffer = RenderBuffer(ctx, queue, self.dtype_array.itemsize, 0) # may not grow self.layer_buffer = RenderBuffer(ctx, queue, 2**14, 2**12) self.chunk_buffer = RenderBuffer(ctx, queue, 2**14, 2**12) # The chunks self.data, offset = self.array_buffer.allocate_data(self.dtype_array) self.layers = [ ChunkLayer(*self.layer_buffer.allocate_data(self.dtype_layer)) for i in range(num_layers) ] self.z_bounds = z_bounds self.x_bounds = (2**30, -2**30) self.y_bounds = (2**30, -2**30) self.chunk_layers_ptr = self.layer_buffer._d_buffer.int_ptr self.voxel_data = VoxelData(ctx, queue) self.init_chunk_array_kernel = init_chunk_array_kernel self.ctx = ctx self.queue = queue def get_layer(self, z): if z < self.z_bounds[0] or z >= self.z_bounds[1]: raise IndexError("%d index is out of bounds (layer not found)" % z) return self.layers[z - self.z_bounds[0]] def get_chunk(self, x, y, z): layer = self.get_layer(z) if (x < layer.x_bounds[0] or x >= layer.x_bounds[1] or y < layer.y_bounds[0] or y >= layer.y_bounds[1]): raise IndexError("Layer %d found, but not chunk (%d, %d) in it. " % (z, x, y)) x_offset = x - layer.x_bounds[0] y_offset = y - layer.y_bounds[0] return layer.chunks[x_offset + y_offset*(layer.y_bounds[1]-layer.y_bounds[0])] def get_voxel(self, x, y, z): chunk_x, voxel_x = divmod(x, 32) chunk_y, voxel_y = divmod(y, 32) chunk_z, voxel_z = divmod(z, 32) chunk = self.get_chunk(chunk_x, chunk_y, chunk_z) return chunk.get_voxel((voxel_x, voxel_y, voxel_z)) def allocate_layer(self, z, x_bounds, y_bounds): layer = self.get_layer(z) x_size = x_bounds[1] - x_bounds[0] y_size = y_bounds[1] - y_bounds[0] if x_bounds[0] < self.x_bounds[0]: self.x_bounds[0] = x_bounds[0] if x_bounds[1] > self.x_bounds[1]: self.x_bounds[1] = x_bounds[1] if y_bounds[0] < self.y_bounds[0]: self.y_bounds[0] = y_bounds[0] if y_bounds[1] > self.y_bounds[1]: self.y_bounds[1] = y_bounds[1] layer.x_bounds = x_bounds layer.y_bounds = y_bounds layer.chunks = [ Chunk(*self.chunk_buffer.allocate_data(self.dtype_chunk)) for i in range(x_size*y_size) ] layer.chunk_offset = layer.chunks[0].offset / self.dtype_chunk.itemsize def allocate_chunk(self, x, y, z, level): chunk = self.get_chunk(x, y, z) chunk.level = level data, offset = self.voxel_data.allocate_buffer(level) chunk.voxel_offset = offset / self.voxel_data.test_dtype.itemsize chunk.voxel_data = data def upload_buffers(self): self.array_buffer.upload_buffer() self.layer_buffer.upload_buffer() self.chunk_buffer.upload_buffer() self.voxel_data.upload_buffers() self.init_chunk_array_kernel(self.queue, (1,), None, self.array_buffer._d_buffer, self.layer_buffer._d_buffer, self.chunk_buffer._d_buffer, *[ self.voxel_data.level_buffers[i]._d_buffer for i in range(self.voxel_data.num_levels) ]) self.array_buffer.download_buffer() @render_property("x_bounds") def x_bounds(self): "x_min, x_max" @render_property("y_bounds") def y_bounds(self): "y_min, y_max" @render_property("z_bounds") def z_bounds(self): "z_min, z_max" @render_property("chunk_layers_ptr", None) def chunk_layers_ptr(self): "chunk_layer_t*" @render_property("chunks_ptr", None) def chunks_ptr(self): "chunk_t*" @render_property("voxel_levels_ptr") def voxel_levels_ptr(self): "voxel_t* [6]"