parent
3444349242
commit
0df47e8325
3 changed files with 0 additions and 350 deletions
@ -1,111 +0,0 @@ |
||||
#include <assert.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS |
||||
#ifdef __APPLE__ |
||||
#include <OpenCL/cl.h> |
||||
#else |
||||
#include <CL/cl.h> |
||||
#endif |
||||
|
||||
#include "selfdrive/common/clutil.h" |
||||
#include "selfdrive/modeld/transforms/transform.h" |
||||
|
||||
typedef struct { |
||||
int disable_model; |
||||
Transform transform; |
||||
|
||||
int in_width; |
||||
int in_height; |
||||
int out_width; |
||||
int out_height; |
||||
|
||||
cl_context context; |
||||
cl_command_queue command_queue; |
||||
cl_device_id device_id; |
||||
|
||||
size_t in_yuv_size; |
||||
cl_mem in_yuv_cl; |
||||
|
||||
cl_mem out_y_cl, out_u_cl, out_v_cl; |
||||
} VisionTest; |
||||
|
||||
void initialize_opencl(VisionTest* visiontest) { |
||||
// init cl
|
||||
cl_device_id device_id = cl_get_device_id(CL_DEVICE_TYPE_CPU); |
||||
visiontest->context = CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err)); |
||||
visiontest->device_id = device_id; |
||||
} |
||||
|
||||
VisionTest* visiontest_create(int temporal_model, int disable_model, |
||||
int input_width, int input_height, |
||||
int model_input_width, int model_input_height) { |
||||
VisionTest* const vt = calloc(1, sizeof(*vt)); |
||||
assert(vt); |
||||
|
||||
vt->disable_model = disable_model; |
||||
vt->in_width = input_width; |
||||
vt->in_height = input_height; |
||||
vt->out_width = model_input_width; |
||||
vt->out_height = model_input_height; |
||||
|
||||
initialize_opencl(vt); |
||||
|
||||
transform_init(&vt->transform, vt->context, vt->device_id); |
||||
|
||||
|
||||
assert((vt->in_width%2) == 0 && (vt->in_height%2) == 0); |
||||
vt->in_yuv_size = vt->in_width*vt->in_height*3/2; |
||||
vt->in_yuv_cl = CL_CHECK_ERR(clCreateBuffer(vt->context, CL_MEM_READ_WRITE, |
||||
vt->in_yuv_size, NULL, &err)); |
||||
vt->out_y_cl = CL_CHECK_ERR(clCreateBuffer(vt->context, CL_MEM_READ_WRITE, |
||||
vt->out_width*vt->out_width, NULL, &err)); |
||||
vt->out_u_cl = CL_CHECK_ERR(clCreateBuffer(vt->context, CL_MEM_READ_WRITE, |
||||
vt->out_width*vt->out_width/4, NULL, &err)); |
||||
vt->out_v_cl = CL_CHECK_ERR(clCreateBuffer(vt->context, CL_MEM_READ_WRITE, |
||||
vt->out_width*vt->out_width/4, NULL, &err)); |
||||
vt->command_queue = CL_CHECK_ERR(clCreateCommandQueue(vt->context, vt->device_id, 0, &err)); |
||||
return vt; |
||||
} |
||||
|
||||
void visiontest_destroy(VisionTest* vt) { |
||||
transform_destroy(&vt->transform); |
||||
|
||||
CL_CHECK(clReleaseMemObject(vt->in_yuv_cl)); |
||||
CL_CHECK(clReleaseMemObject(vt->out_y_cl)); |
||||
CL_CHECK(clReleaseMemObject(vt->out_u_cl)); |
||||
CL_CHECK(clReleaseMemObject(vt->out_v_cl)); |
||||
CL_CHECK(clReleaseCommandQueue(vt->command_queue)); |
||||
CL_CHECK(clReleaseContext(vt->context)); |
||||
|
||||
free(vt); |
||||
} |
||||
|
||||
void visiontest_transform(VisionTest* vt, const uint8_t* yuv_data, |
||||
uint8_t* out_y, uint8_t* out_u, uint8_t* out_v, |
||||
const float* transform) { |
||||
CL_CHECK(clEnqueueWriteBuffer(vt->command_queue, vt->in_yuv_cl, CL_FALSE, |
||||
0, vt->in_yuv_size, yuv_data, 0, NULL, NULL)); |
||||
|
||||
mat3 transform_m = *(const mat3*)transform; |
||||
|
||||
transform_queue(&vt->transform, vt->command_queue, |
||||
vt->in_yuv_cl, vt->in_width, vt->in_height, |
||||
vt->out_y_cl, vt->out_u_cl, vt->out_v_cl, |
||||
vt->out_width, vt->out_height, |
||||
transform_m); |
||||
|
||||
CL_CHECK(clEnqueueReadBuffer(vt->command_queue, vt->out_y_cl, CL_FALSE, |
||||
0, vt->out_width*vt->out_height, out_y, |
||||
0, NULL, NULL)); |
||||
CL_CHECK(clEnqueueReadBuffer(vt->command_queue, vt->out_u_cl, CL_FALSE, |
||||
0, vt->out_width*vt->out_height/4, out_u, |
||||
0, NULL, NULL)); |
||||
CL_CHECK(clEnqueueReadBuffer(vt->command_queue, vt->out_v_cl, CL_FALSE, |
||||
0, vt->out_width*vt->out_height/4, out_v, |
||||
0, NULL, NULL)); |
||||
|
||||
clFinish(vt->command_queue); |
||||
} |
||||
|
@ -1,104 +0,0 @@ |
||||
CC:=clang
|
||||
CXX:=clang++
|
||||
OPT_FLAGS:=-O2 -g -ggdb3
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Linux) |
||||
SHARED_FLAGS=-Wl,--whole-archive $^ -Wl,--no-whole-archive
|
||||
endif |
||||
ifeq ($(UNAME_S),Darwin) |
||||
SHARED_FLAGS=-Wl,-force_load $^
|
||||
endif |
||||
|
||||
PHONELIBS := ../../third_party
|
||||
BASEDIR := ../..
|
||||
|
||||
WARN_FLAGS = -Werror=implicit-function-declaration \
|
||||
-Werror=incompatible-pointer-types \
|
||||
-Werror=int-conversion \
|
||||
-Werror=return-type \
|
||||
-Werror=format-extra-args
|
||||
|
||||
CFLAGS = -std=gnu11 -g -fPIC $(OPT_FLAGS) $(WARN_FLAGS)
|
||||
CXXFLAGS = -std=c++1z -fPIC $(OPT_FLAGS) $(WARN_FLAGS)
|
||||
|
||||
EIGEN_FLAGS = -I$(PHONELIBS)/eigen
|
||||
|
||||
CEREAL_LIBS = $(BASEDIR)/cereal/libmessaging.a
|
||||
|
||||
OPENCV_LIBS = -lopencv_video -lopencv_core -lopencv_imgproc
|
||||
|
||||
ifeq ($(UNAME_S),Darwin) |
||||
VT_LDFLAGS += $(PHONELIBS)/capnp-c/mac/lib/libcapnp_c.a \
|
||||
$(PHONELIBS)/zmq/mac/lib/libzmq.a \
|
||||
-framework OpenCL
|
||||
|
||||
OPENCV_LIBS += -L/usr/local/opt/opencv@2/lib
|
||||
OPENCV_FLAGS += -I/usr/local/opt/opencv@2/include
|
||||
|
||||
else |
||||
VT_LDFLAGS += $(CEREAL_LIBS) \
|
||||
-L/system/vendor/lib64 \
|
||||
-L$(BASEDIR)/external/zmq/lib/ \
|
||||
-l:libzmq.a \
|
||||
-lOpenCL
|
||||
endif |
||||
|
||||
.PHONY: all visiontest clean test |
||||
all: visiontest |
||||
|
||||
libvisiontest_inputs := visiontest.c \
|
||||
transforms/transform.cc \
|
||||
transforms/loadyuv.cc \
|
||||
../common/clutil.cc \
|
||||
$(BASEDIR)/selfdrive/common/util.c \
|
||||
$(CEREAL_OBJS)
|
||||
|
||||
visiontest: libvisiontest.so |
||||
all-tests := $(addsuffix .test, $(basename $(wildcard test_*)))
|
||||
|
||||
%.o: %.cc |
||||
@echo "[ CXX ] $@"
|
||||
$(CXX) $(CXXFLAGS) -MMD \
|
||||
-I. -I.. -I../.. \
|
||||
-Wall \
|
||||
-I$(BASEDIR)/ -I$(BASEDIR)/selfdrive -I$(BASEDIR)/selfdrive/common \
|
||||
$(EIGEN_FLAGS) \
|
||||
$(OPENCV_FLAGS) \
|
||||
$(CEREAL_CXXFLAGS) \
|
||||
-c -o '$@' '$<'
|
||||
|
||||
%.o: %.c |
||||
@echo "[ CXX ] $@"
|
||||
$(CC) $(CFLAGS) -MMD \
|
||||
-I. -I.. -I../.. \
|
||||
-Wall \
|
||||
-I$(BASEDIR)/ -I$(BASEDIR)/selfdrive -I$(BASEDIR)/selfdrive/common \
|
||||
$(CEREAL_CFLAGS) \
|
||||
-c -o '$@' '$<'
|
||||
|
||||
libvisiontest.so: $(libvisiontest_inputs) |
||||
$(eval $@_TMP := $(shell mktemp))
|
||||
$(CC) -std=gnu11 -shared -fPIC -O2 -g \
|
||||
-Werror=implicit-function-declaration -Werror=incompatible-pointer-types \
|
||||
-Werror=int-conversion -Wno-pointer-to-int-cast \
|
||||
-I. \
|
||||
$^ -o $($@_TMP) \
|
||||
-I$(PHONELIBS)/opencl/include \
|
||||
-I$(BASEDIR)/selfdrive/common \
|
||||
$(CEREAL_CXXFLAGS) \
|
||||
$(CEREAL_CFLAGS) \
|
||||
-I$(BASEDIR)/external/zmq/include \
|
||||
-I$(BASEDIR)/ -I$(BASEDIR)/selfdrive \
|
||||
-lstdc++ \
|
||||
$(VT_LDFLAGS) \
|
||||
-lm -lpthread
|
||||
mv $($@_TMP) $@
|
||||
|
||||
test : $(all-tests) |
||||
|
||||
test_%.test : test_% |
||||
@./'$<' || echo FAIL
|
||||
|
||||
clean: |
||||
rm -rf *.o *.so *.a
|
@ -1,135 +0,0 @@ |
||||
import os |
||||
import subprocess |
||||
from cffi import FFI |
||||
from common.basedir import BASEDIR |
||||
|
||||
# Initialize visiontest. Ignore output. |
||||
_visiond_dir = os.path.dirname(os.path.abspath(__file__)) |
||||
_libvisiontest = "libvisiontest.so" |
||||
try: # because this crashes sometimes when running pipeline |
||||
subprocess.check_output(["make", "-C", _visiond_dir, "-f", |
||||
os.path.join(_visiond_dir, "visiontest.mk"), |
||||
_libvisiontest]) |
||||
except Exception: |
||||
pass |
||||
|
||||
|
||||
class VisionTest(): |
||||
"""A version of the vision model that can be run on a desktop. |
||||
|
||||
WARNING: This class is not thread safe. VisionTest objects cannot be |
||||
created or used on multiple threads simultaneously. |
||||
""" |
||||
|
||||
ffi = FFI() |
||||
ffi.cdef(""" |
||||
typedef unsigned char uint8_t; |
||||
|
||||
struct VisionTest; |
||||
typedef struct VisionTest VisionTest; |
||||
|
||||
VisionTest* visiontest_create(int temporal_model, int disable_model, |
||||
int input_width, int input_height, |
||||
int model_input_width, int model_input_height); |
||||
void visiontest_destroy(VisionTest* visiontest); |
||||
|
||||
void visiontest_transform(VisionTest* vt, const uint8_t* yuv_data, |
||||
uint8_t* out_y, uint8_t* out_u, uint8_t* out_v, |
||||
const float* transform); |
||||
""") |
||||
|
||||
clib = ffi.dlopen(os.path.join(_visiond_dir, _libvisiontest)) |
||||
|
||||
def __init__(self, input_size, model_input_size, model): |
||||
"""Create a wrapper around visiond for off-device python code. |
||||
|
||||
Inputs: |
||||
input_size: The size of YUV images passed to transform. |
||||
model_input_size: The size of YUV images passed to the model. |
||||
model: The name of the model to use. "temporal", "yuv", or None to disable the |
||||
model (used to disable OpenCL). |
||||
""" |
||||
self._input_size = input_size |
||||
self._model_input_size = model_input_size |
||||
|
||||
if model is None: |
||||
disable_model = 1 |
||||
temporal_model = 0 |
||||
elif model == "yuv": |
||||
disable_model = 0 |
||||
temporal_model = 0 |
||||
elif model == "temporal": |
||||
disable_model = 0 |
||||
temporal_model = 1 |
||||
else: |
||||
raise ValueError(f"Bad model name: {model}") |
||||
|
||||
prevdir = os.getcwd() |
||||
os.chdir(_visiond_dir) # tmp hack to find kernels |
||||
os.environ['BASEDIR'] = BASEDIR |
||||
self._visiontest_c = self.clib.visiontest_create( |
||||
temporal_model, disable_model, self._input_size[0], self._input_size[1], |
||||
self._model_input_size[0], self._model_input_size[1]) |
||||
os.chdir(prevdir) |
||||
|
||||
@property |
||||
def input_size(self): |
||||
return self._input_size |
||||
|
||||
@property |
||||
def model_input_size(self): |
||||
return self._model_input_size |
||||
|
||||
def transform(self, yuv_data, transform): |
||||
y_len = self.model_input_size[0] * self.model_input_size[1] |
||||
t_y_ptr = bytearray(y_len) |
||||
t_u_ptr = bytearray(y_len // 4) |
||||
t_v_ptr = bytearray(y_len // 4) |
||||
|
||||
self.transform_output_buffer(yuv_data, t_y_ptr, t_u_ptr, t_v_ptr, |
||||
transform) |
||||
|
||||
return t_y_ptr, t_u_ptr, t_v_ptr |
||||
|
||||
def transform_contiguous(self, yuv_data, transform): |
||||
y_ol = self.model_input_size[0] * self.model_input_size[1] |
||||
uv_ol = y_ol // 4 |
||||
result = bytearray(y_ol * 3 // 2) |
||||
result_view = memoryview(result) |
||||
t_y_ptr = result_view[:y_ol] |
||||
t_u_ptr = result_view[y_ol:y_ol + uv_ol] |
||||
t_v_ptr = result_view[y_ol + uv_ol:] |
||||
|
||||
self.transform_output_buffer(yuv_data, t_y_ptr, t_u_ptr, t_v_ptr, |
||||
transform) |
||||
return result |
||||
|
||||
def transform_output_buffer(self, yuv_data, y_out, u_out, v_out, |
||||
transform): |
||||
assert len(yuv_data) == self.input_size[0] * self.input_size[1] * 3 / 2 |
||||
|
||||
cast = self.ffi.cast |
||||
from_buffer = self.ffi.from_buffer |
||||
yuv_ptr = cast("unsigned char*", from_buffer(yuv_data)) |
||||
transform_ptr = self.ffi.new("float[]", transform) |
||||
|
||||
y_out_ptr = cast("unsigned char*", from_buffer(y_out)) |
||||
u_out_ptr = cast("unsigned char*", from_buffer(u_out)) |
||||
v_out_ptr = cast("unsigned char*", from_buffer(v_out)) |
||||
|
||||
self.clib.visiontest_transform(self._visiontest_c, yuv_ptr, y_out_ptr, |
||||
u_out_ptr, v_out_ptr, transform_ptr) |
||||
|
||||
def close(self): |
||||
self.clib.visiontest_destroy(self._visiontest_c) |
||||
self._visiontest_c = None |
||||
|
||||
def __enter__(self): |
||||
return self |
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback): |
||||
self.close() |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
VisionTest((560, 304), (320, 160), "temporal") |
Loading…
Reference in new issue