aboutsummaryrefslogtreecommitdiff
path: root/modules/vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'modules/vulkan')
-rw-r--r--modules/vulkan/Makefile.am76
-rw-r--r--modules/vulkan/vk_blender.cpp1537
-rw-r--r--modules/vulkan/vk_blender.h120
-rw-r--r--modules/vulkan/vk_cmdbuf.cpp172
-rw-r--r--modules/vulkan/vk_cmdbuf.h106
-rw-r--r--modules/vulkan/vk_copy_handler.cpp270
-rw-r--r--modules/vulkan/vk_copy_handler.h90
-rw-r--r--modules/vulkan/vk_descriptor.cpp220
-rw-r--r--modules/vulkan/vk_descriptor.h163
-rw-r--r--modules/vulkan/vk_device.cpp471
-rw-r--r--modules/vulkan/vk_device.h120
-rw-r--r--modules/vulkan/vk_geomap_handler.cpp314
-rw-r--r--modules/vulkan/vk_geomap_handler.h78
-rw-r--r--modules/vulkan/vk_handler.cpp60
-rw-r--r--modules/vulkan/vk_handler.h57
-rw-r--r--modules/vulkan/vk_instance.cpp230
-rw-r--r--modules/vulkan/vk_instance.h77
-rw-r--r--modules/vulkan/vk_memory.cpp182
-rw-r--r--modules/vulkan/vk_memory.h134
-rw-r--r--modules/vulkan/vk_pipeline.cpp293
-rw-r--r--modules/vulkan/vk_pipeline.h127
-rw-r--r--modules/vulkan/vk_shader.cpp60
-rw-r--r--modules/vulkan/vk_shader.h71
-rw-r--r--modules/vulkan/vk_stitcher.cpp824
-rw-r--r--modules/vulkan/vk_stitcher.h80
-rw-r--r--modules/vulkan/vk_sync.cpp55
-rw-r--r--modules/vulkan/vk_sync.h56
-rw-r--r--modules/vulkan/vk_video_buf_allocator.cpp164
-rw-r--r--modules/vulkan/vk_video_buf_allocator.h58
-rw-r--r--modules/vulkan/vk_worker.cpp218
-rw-r--r--modules/vulkan/vk_worker.h112
-rw-r--r--modules/vulkan/vulkan_common.cpp77
-rw-r--r--modules/vulkan/vulkan_common.h33
-rw-r--r--modules/vulkan/vulkan_std.h43
34 files changed, 6748 insertions, 0 deletions
diff --git a/modules/vulkan/Makefile.am b/modules/vulkan/Makefile.am
new file mode 100644
index 0000000..22763f0
--- /dev/null
+++ b/modules/vulkan/Makefile.am
@@ -0,0 +1,76 @@
+lib_LTLIBRARIES = libxcam_vulkan.la
+
+XCAM_VK_CXXFLAGS = \
+ $(XCAM_CXXFLAGS) \
+ $(LIBVULKAN_CFLAGS) \
+ -I$(top_srcdir)/xcore \
+ -I$(top_srcdir)/modules \
+ -I$(top_builddir)/shaders/spv \
+ $(NULL)
+
+XCAM_VK_LIBS = \
+ $(LIBVULKAN_LIBS) \
+ $(top_builddir)/xcore/libxcam_core.la \
+ $(NULL)
+
+if HAVE_OPENCV
+XCAM_VK_LIBS += $(top_builddir)/modules/ocv/libxcam_ocv.la
+endif
+
+xcam_vulkan_sources = \
+ vk_cmdbuf.cpp \
+ vk_descriptor.cpp \
+ vk_device.cpp \
+ vk_handler.cpp \
+ vk_instance.cpp \
+ vk_memory.cpp \
+ vk_pipeline.cpp \
+ vk_shader.cpp \
+ vk_sync.cpp \
+ vk_video_buf_allocator.cpp \
+ vk_worker.cpp \
+ vulkan_common.cpp \
+ vk_copy_handler.cpp \
+ vk_geomap_handler.cpp \
+ vk_blender.cpp \
+ vk_stitcher.cpp \
+ $(NULL)
+
+libxcam_vulkan_la_SOURCES = \
+ $(xcam_vulkan_sources) \
+ $(NULL)
+
+libxcam_vulkan_la_CXXFLAGS = \
+ $(XCAM_VK_CXXFLAGS) \
+ $(NULL)
+
+libxcam_vulkan_la_LIBADD = \
+ $(XCAM_VK_LIBS) \
+ $(NULL)
+
+libxcam_vulkan_la_LDFLAGS = \
+ $(XCAM_LT_LDFLAGS) \
+ $(NULL)
+
+libxcam_vulkanincludedir = $(includedir)/xcam/vulkan
+
+nobase_libxcam_vulkaninclude_HEADERS = \
+ vk_cmdbuf.h \
+ vk_descriptor.h \
+ vk_device.h \
+ vk_handler.h \
+ vk_instance.h \
+ vk_memory.h \
+ vk_pipeline.h \
+ vk_shader.h \
+ vk_sync.h \
+ vk_video_buf_allocator.h \
+ vk_worker.h \
+ vulkan_common.h \
+ vk_copy_handler.h \
+ vk_geomap_handler.h \
+ vk_blender.h \
+ vk_stitcher.h \
+ $(NULL)
+
+libxcam_vulkan_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/modules/vulkan/vk_blender.cpp b/modules/vulkan/vk_blender.cpp
new file mode 100644
index 0000000..f880649
--- /dev/null
+++ b/modules/vulkan/vk_blender.cpp
@@ -0,0 +1,1537 @@
+/*
+ * vk_blender.cpp - vulkan blender implementation
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Yinhang Liu <yinhangx.liu@intel.com>
+ */
+
+#include "xcam_utils.h"
+
+#include "vk_device.h"
+#include "vk_worker.h"
+#include "vk_blender.h"
+#include "vk_video_buf_allocator.h"
+
+#define DUMP_BUFFER 0
+
+#define GAUSS_RADIUS 2
+#define GAUSS_DIAMETER ((GAUSS_RADIUS)*2+1)
+
+const float gauss_coeffs[GAUSS_DIAMETER] = {0.152f, 0.222f, 0.252f, 0.222f, 0.152f};
+
+#define GS_SHADER_BINDING_COUNT 4
+#define LAP_SHADER_BINDING_COUNT 6
+#define BLEND_SHADER_BINDING_COUNT 7
+#define RECONSTRUCT_SHADER_BINDING_COUNT 9
+
+#define CHECK_RET(ret, format, ...) \
+ if (!xcam_ret_is_ok (ret)) { \
+ XCAM_LOG_ERROR (format, ## __VA_ARGS__); \
+ }
+
+#define DECLARE_VK_PUSH_CONST(PushConstClass, PushConstsProp) \
+ class PushConstClass : public VKConstRange::VKPushConstArg { \
+ private: PushConstsProp _prop; \
+ public: \
+ PushConstClass (const PushConstsProp &prop) : _prop (prop) {} \
+ bool get_const_data (VkPushConstantRange &range, void *& ptr) { \
+ range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; \
+ range.offset = 0; \
+ range.size = sizeof (_prop); \
+ ptr = &_prop; \
+ return true; } \
+ }
+
+namespace XCam {
+
+#if DUMP_BUFFER
+static void
+dump_vkbuf_with_perfix (const SmartPtr<VKBuffer> &buf, const char *perfix_name)
+{
+ XCAM_ASSERT (buf.ptr ());
+ XCAM_ASSERT (perfix_name);
+
+ const VKBufInfo &info = buf->get_buf_info ();
+ char file_name[XCAM_VK_NAME_LENGTH];
+ snprintf (
+ file_name, XCAM_VK_NAME_LENGTH, "%s-%dx%d.%s",
+ perfix_name, info.width, info.height, xcam_fourcc_to_string (info.format));
+
+ FILE *fp = fopen (file_name, "wb");
+ if (!fp) {
+ XCAM_LOG_ERROR ( "vk-blend open file(%s) failed", file_name);
+ }
+
+ uint8_t *ptr = (uint8_t *)buf->map ();
+ for (uint32_t i = 0; i < info.height * 3 / 2; ++i) {
+ uint8_t *start = ptr + info.aligned_width * i;
+ fwrite (start, info.width, 1, fp);
+ }
+ buf->unmap ();
+ fclose (fp);
+}
+#define dump_vkbuf dump_vkbuf_with_perfix
+
+static void
+dump_level_vkbuf (const SmartPtr<VKBuffer> &buf, const char *name, uint32_t level, uint32_t idx)
+{
+ char file_name[XCAM_VK_NAME_LENGTH];
+ snprintf (file_name, XCAM_VK_NAME_LENGTH, "%s-L%d-Idx%d", name, level, idx);
+
+ dump_vkbuf_with_perfix (buf, file_name);
+}
+#endif
+
+namespace VKBlenderPriv {
+
+enum ShaderID {
+ ShaderGaussScalePyr = 0,
+ ShaderLapTransPyr,
+ ShaderBlendPyr,
+ ShaderReconstructPyr
+};
+
+static const VKShaderInfo shaders_info[] = {
+ VKShaderInfo (
+ "main",
+ std::vector<uint32_t> {
+#include "shader_gauss_scale_pyr.comp.spv"
+ }),
+ VKShaderInfo (
+ "main",
+ std::vector<uint32_t> {
+#include "shader_lap_trans_pyr.comp.spv"
+ }),
+ VKShaderInfo (
+ "main",
+ std::vector<uint32_t> {
+#include "shader_blend_pyr.comp.spv"
+ }),
+ VKShaderInfo (
+ "main",
+ std::vector<uint32_t> {
+#include "shader_reconstruct_pyr.comp.spv"
+ })
+};
+
+struct GaussScalePushConstsProp {
+ uint in_img_width;
+ uint in_img_height;
+ uint in_offset_x;
+ uint out_img_width;
+ uint out_img_height;
+ uint merge_width;
+
+ GaussScalePushConstsProp ()
+ : in_img_width (0)
+ , in_img_height (0)
+ , in_offset_x (0)
+ , out_img_width (0)
+ , out_img_height (0)
+ , merge_width (0)
+ {}
+};
+
+struct LapPushConstsProp {
+ uint in_img_width;
+ uint in_img_height;
+ uint in_offset_x;
+ uint gaussscale_img_width;
+ uint gaussscale_img_height;
+ uint merge_width;
+
+ LapPushConstsProp ()
+ : in_img_width (0)
+ , in_img_height (0)
+ , in_offset_x (0)
+ , gaussscale_img_width (0)
+ , gaussscale_img_height (0)
+ , merge_width (0)
+ {}
+};
+
+struct BlendPushConstsProp {
+ uint in_img_width;
+
+ BlendPushConstsProp ()
+ : in_img_width (0)
+ {}
+};
+
+struct ReconstructPushConstsProp {
+ uint lap_img_width;
+ uint lap_img_height;
+ uint out_img_width;
+ uint out_offset_x;
+ uint prev_blend_img_width;
+ uint prev_blend_img_height;
+
+ ReconstructPushConstsProp ()
+ : lap_img_width (0)
+ , lap_img_height (0)
+ , out_img_width (0)
+ , out_offset_x (0)
+ , prev_blend_img_width (0)
+ , prev_blend_img_height (0)
+ {}
+};
+
+DECLARE_VK_PUSH_CONST (VKGaussScalePushConst, GaussScalePushConstsProp);
+DECLARE_VK_PUSH_CONST (VKLapPushConst, LapPushConstsProp);
+DECLARE_VK_PUSH_CONST (VKBlendPushConst, BlendPushConstsProp);
+DECLARE_VK_PUSH_CONST (VKReconstructPushConst, ReconstructPushConstsProp);
+
+DECLARE_WORK_CALLBACK (CbGaussScalePyr, VKBlender, gauss_scale_done);
+DECLARE_WORK_CALLBACK (CbLapTransPyr, VKBlender, lap_trans_done);
+DECLARE_WORK_CALLBACK (CbBlendPyr, VKBlender, blend_done);
+DECLARE_WORK_CALLBACK (CbReconstructPyr, VKBlender, reconstruct_done);
+
+class BlendArgs
+ : public VKWorker::VKArguments
+{
+public:
+ BlendArgs (uint32_t lv, VKBlender::BufIdx i = VKBlender::BufIdx0);
+
+ uint32_t get_level () {
+ return _level;
+ }
+ VKBlender::BufIdx get_idx () {
+ return _idx;
+ }
+
+private:
+ uint32_t _level;
+ VKBlender::BufIdx _idx;
+};
+
+struct PyrLayer {
+ uint32_t blend_width;
+ uint32_t blend_height;
+
+ SmartPtr<VKBlender::Sync> lap_sync[VKBlender::BufIdxMax];
+ SmartPtr<VKBlender::Sync> blend_sync;
+ SmartPtr<VKBlender::Sync> reconstruct_sync;
+
+ SmartPtr<VKBuffer> gs_buf[VKBlender::BufIdxMax];
+ SmartPtr<VKBuffer> lap_buf[VKBlender::BufIdxMax];
+ SmartPtr<VKBuffer> mask;
+ SmartPtr<VKBuffer> blend_buf;
+ SmartPtr<VKBuffer> reconstruct_buf;
+
+ VKDescriptor::SetBindInfoArray gs_bindings[VKBlender::BufIdxMax];
+ VKDescriptor::SetBindInfoArray lap_bindings[VKBlender::BufIdxMax];
+ VKDescriptor::SetBindInfoArray blend_bindings;
+ VKDescriptor::SetBindInfoArray reconstruct_bindings;
+
+ SmartPtr<VKConstRange::VKPushConstArg> gs_consts[VKBlender::BufIdxMax];
+ SmartPtr<VKConstRange::VKPushConstArg> lap_consts[VKBlender::BufIdxMax];
+ SmartPtr<VKConstRange::VKPushConstArg> blend_consts;
+ SmartPtr<VKConstRange::VKPushConstArg> reconstruct_consts;
+
+ WorkSize gs_global_size[VKBlender::BufIdxMax];
+ WorkSize lap_global_size[VKBlender::BufIdxMax];
+ WorkSize blend_global_size;
+ WorkSize reconstruct_global_size;
+
+ VKWorker *gauss_scale[VKBlender::BufIdxMax];
+ VKWorker *lap_trans[VKBlender::BufIdxMax];
+ VKWorker *blend;
+ VKWorker *reconstruct;
+
+ PyrLayer ();
+};
+
+typedef std::map<ShaderID, SmartPtr<VKWorker>> VKWorkers;
+
+class BlenderImpl {
+public:
+ PyrLayer pyr_layer[XCAM_VK_MAX_LEVEL];
+ uint32_t pyr_layers_num;
+
+private:
+ VKBlender *_blender;
+ VKWorkers _workers;
+
+public:
+ BlenderImpl (VKBlender *blender, uint32_t layers_num)
+ : pyr_layers_num (layers_num)
+ , _blender (blender)
+ {
+ XCAM_ASSERT (layers_num >= 2 && layers_num <= XCAM_VK_MAX_LEVEL);
+ }
+
+ XCamReturn start_gauss_scale (uint32_t level, VKBlender::BufIdx idx);
+ XCamReturn start_lap_trans (uint32_t level, VKBlender::BufIdx idx);
+ XCamReturn start_top_blend ();
+ XCamReturn start_reconstruct (uint32_t level);
+ XCamReturn stop ();
+
+ void init_syncs ();
+ XCamReturn init_layers_bufs (const SmartPtr<ImageHandler::Parameters> &base);
+ XCamReturn bind_io_bufs_to_layer0 (
+ SmartPtr<VideoBuffer> &input0, SmartPtr<VideoBuffer> &input1, SmartPtr<VideoBuffer> &output);
+ XCamReturn bind_io_vkbufs_to_desc ();
+ XCamReturn fix_parameters ();
+ XCamReturn create_workers (const SmartPtr<VKBlender> &blender);
+ XCamReturn redirect_workers ();
+
+private:
+ XCamReturn start_lap_tran (uint32_t level, VKBlender::BufIdx idx);
+
+ XCamReturn layer0_allocate_bufs (SmartPtr<VKDevice> dev);
+ XCamReturn layer0_init_mask (SmartPtr<VKDevice> dev);
+
+ XCamReturn layerx_allocate_bufs (SmartPtr<VKDevice> dev, uint32_t level);
+ XCamReturn allocate_vk_bufs (SmartPtr<VKDevice> dev, uint32_t level);
+ XCamReturn scale_down_mask (SmartPtr<VKDevice> dev, uint32_t level);
+
+ XCamReturn fix_gs_params (uint32_t level, VKBlender::BufIdx idx);
+ XCamReturn fix_lap_trans_params (uint32_t level, VKBlender::BufIdx idx);
+ XCamReturn fix_blend_params ();
+ XCamReturn fix_reconstruct_params (uint32_t level);
+};
+
+BlendArgs::BlendArgs (uint32_t lv, VKBlender::BufIdx i)
+ : _level (lv)
+ , _idx (i)
+{
+ XCAM_ASSERT (lv < XCAM_VK_DEFAULT_LEVEL);
+ XCAM_ASSERT (i < VKBlender::BufIdxMax);
+}
+
+PyrLayer::PyrLayer ()
+ : blend_width (0)
+ , blend_height (0)
+{
+}
+
+void
+BlenderImpl::init_syncs ()
+{
+ for (uint32_t i = 0; i < pyr_layers_num - 1; ++i) {
+ PyrLayer &layer = pyr_layer[i];
+
+ layer.lap_sync[VKBlender::BufIdx0] = new VKBlender::Sync (2);
+ XCAM_ASSERT (layer.lap_sync[VKBlender::BufIdx0].ptr ());
+ layer.lap_sync[VKBlender::BufIdx1] = new VKBlender::Sync (2);
+ XCAM_ASSERT (layer.lap_sync[VKBlender::BufIdx1].ptr ());
+
+ layer.reconstruct_sync = new VKBlender::Sync (3);
+ XCAM_ASSERT (layer.reconstruct_sync.ptr ());
+ }
+
+ pyr_layer[pyr_layers_num - 1].blend_sync = new VKBlender::Sync (2);
+ XCAM_ASSERT (pyr_layer[pyr_layers_num - 1].blend_sync.ptr ());
+}
+
+XCamReturn
+BlenderImpl::bind_io_bufs_to_layer0 (
+ SmartPtr<VideoBuffer> &input0, SmartPtr<VideoBuffer> &input1, SmartPtr<VideoBuffer> &output)
+{
+ XCAM_ASSERT (input0.ptr () && input1.ptr ());
+
+ SmartPtr<VKVideoBuffer> in0_vk = input0.dynamic_cast_ptr<VKVideoBuffer> ();
+ SmartPtr<VKVideoBuffer> in1_vk = input1.dynamic_cast_ptr<VKVideoBuffer> ();
+
+ PyrLayer &layer0 = pyr_layer[0];
+ layer0.gs_buf[VKBlender::BufIdx0] = in0_vk->get_vk_buf ();
+ layer0.gs_buf[VKBlender::BufIdx1] = in1_vk->get_vk_buf ();
+ XCAM_ASSERT (layer0.gs_buf[VKBlender::BufIdx0].ptr () && layer0.gs_buf[VKBlender::BufIdx1].ptr ());
+
+ if (!output.ptr ())
+ return XCAM_RETURN_NO_ERROR;
+
+ SmartPtr<VKVideoBuffer> out_vk = output.dynamic_cast_ptr<VKVideoBuffer> ();
+ XCAM_ASSERT (out_vk.ptr ());
+
+ layer0.reconstruct_buf = out_vk->get_vk_buf ();
+ XCAM_ASSERT (layer0.reconstruct_buf.ptr ());
+ layer0.blend_buf = layer0.reconstruct_buf;
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::bind_io_vkbufs_to_desc ()
+{
+ PyrLayer &layer0 = pyr_layer[0];
+ PyrLayer &layer1 = pyr_layer[1];
+ XCAM_ASSERT (layer0.gs_buf[VKBlender::BufIdx0].ptr () && layer0.gs_buf[VKBlender::BufIdx1].ptr ());
+ XCAM_ASSERT (layer0.reconstruct_buf.ptr ());
+
+ VKDescriptor::SetBindInfoArray &gs_bindings0 = layer1.gs_bindings[VKBlender::BufIdx0];
+ VKDescriptor::SetBindInfoArray &gs_bindings1 = layer1.gs_bindings[VKBlender::BufIdx1];
+ gs_bindings0[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneYIdx);
+ gs_bindings0[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneUVIdx);
+ gs_bindings1[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneYIdx);
+ gs_bindings1[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneUVIdx);
+
+ VKDescriptor::SetBindInfoArray &lap_bindings0 = layer0.lap_bindings[VKBlender::BufIdx0];
+ VKDescriptor::SetBindInfoArray &lap_bindings1 = layer0.lap_bindings[VKBlender::BufIdx1];
+ lap_bindings0[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneYIdx);
+ lap_bindings0[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneUVIdx);
+ lap_bindings1[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneYIdx);
+ lap_bindings1[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneUVIdx);
+
+ layer0.reconstruct_bindings[4].desc = VKBufDesc (layer0.reconstruct_buf, NV12PlaneYIdx);
+ layer0.reconstruct_bindings[5].desc = VKBufDesc (layer0.reconstruct_buf, NV12PlaneUVIdx);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+static void
+convert_to_vkinfo (const VideoBufferInfo &info, VKBufInfo &vk_info)
+{
+ vk_info.format = info.format;
+ vk_info.width = info.width;
+ vk_info.height = info.height;
+ vk_info.aligned_width = info.aligned_width;
+ vk_info.aligned_height = info.aligned_height;
+ vk_info.size = info.size;
+ vk_info.strides[0] = info.strides[0];
+ vk_info.strides[1] = info.strides[1];
+ vk_info.offsets[0] = info.offsets[0];
+ vk_info.offsets[1] = info.offsets[1];
+ vk_info.slice_size[0] = info.strides[0] * info.aligned_height;
+ vk_info.slice_size[1] = info.size - info.offsets[1];
+}
+
+XCamReturn
+BlenderImpl::layer0_allocate_bufs (SmartPtr<VKDevice> dev)
+{
+ if (pyr_layers_num == 1)
+ return XCAM_RETURN_NO_ERROR;
+
+ PyrLayer &layer0 = pyr_layer[0];
+ XCAM_FAIL_RETURN (
+ ERROR, layer0.blend_width && layer0.blend_height, XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid blend size:%dx%d", layer0.blend_width, layer0.blend_height);
+
+ VideoBufferInfo info;
+ info.init (
+ V4L2_PIX_FMT_NV12, layer0.blend_width, layer0.blend_height,
+ XCAM_ALIGN_UP (layer0.blend_width, VK_BLENDER_ALIGN_X),
+ XCAM_ALIGN_UP (layer0.blend_height, VK_BLENDER_ALIGN_X));
+
+ VKBufInfo vk_info;
+ convert_to_vkinfo (info, vk_info);
+
+ for (int idx = 0; idx < VKBlender::BufIdxMax; ++idx) {
+ layer0.lap_buf[idx] = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size);
+ XCAM_ASSERT (layer0.lap_buf[idx].ptr ());
+ layer0.lap_buf[idx]->set_buf_info (vk_info);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::allocate_vk_bufs (SmartPtr<VKDevice> dev, uint32_t level)
+{
+ XCAM_ASSERT (level >= 1 && level < pyr_layers_num);
+
+ PyrLayer &layer = pyr_layer[level];
+ VideoBufferInfo info;
+ info.init (
+ V4L2_PIX_FMT_NV12, layer.blend_width, layer.blend_height,
+ XCAM_ALIGN_UP (layer.blend_width, VK_BLENDER_ALIGN_X),
+ XCAM_ALIGN_UP (layer.blend_height, VK_BLENDER_ALIGN_X));
+
+ VKBufInfo vk_info;
+ convert_to_vkinfo (info, vk_info);
+
+ bool top_layer = (level == pyr_layers_num - 1);
+ for (int idx = 0; idx < VKBlender::BufIdxMax; ++idx) {
+ layer.gs_buf[idx] = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size);
+ XCAM_ASSERT (layer.gs_buf[idx].ptr ());
+ layer.gs_buf[idx]->set_buf_info (vk_info);
+
+ if (top_layer)
+ continue;
+
+ layer.lap_buf[idx] = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size);
+ XCAM_ASSERT (layer.lap_buf[idx].ptr ());
+ layer.lap_buf[idx]->set_buf_info (vk_info);
+ }
+
+ layer.reconstruct_buf = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size);
+ XCAM_ASSERT (layer.reconstruct_buf.ptr ());
+ layer.reconstruct_buf->set_buf_info (vk_info);
+
+ if (top_layer)
+ layer.blend_buf = layer.reconstruct_buf;
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::layer0_init_mask (SmartPtr<VKDevice> dev)
+{
+ PyrLayer &layer = pyr_layer[0];
+ XCAM_ASSERT (layer.blend_width && ((layer.blend_width % VK_BLENDER_ALIGN_X) == 0));
+
+ uint32_t buf_size = layer.blend_width * sizeof (uint8_t);
+ SmartPtr<VKBuffer> buf = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, buf_size);
+ XCAM_ASSERT (buf.ptr ());
+
+ VKBufInfo info;
+ info.width = layer.blend_width;
+ info.height = 1;
+ info.size = buf_size;
+ buf->set_buf_info (info);
+
+ std::vector<float> gauss_table;
+ uint32_t quater = info.width / 4;
+
+ get_gauss_table (quater, (quater + 1) / 4.0f, gauss_table, false);
+ for (uint32_t i = 0; i < gauss_table.size (); ++i) {
+ float value = ((i < quater) ? (128.0f * (2.0f - gauss_table[i])) : (128.0f * gauss_table[i]));
+ value = XCAM_CLAMP (value, 0.0f, 255.0f);
+ gauss_table[i] = value;
+ }
+
+ uint8_t *mask_ptr = (uint8_t *) buf->map (buf_size, 0);
+ XCAM_FAIL_RETURN (ERROR, mask_ptr, XCAM_RETURN_ERROR_PARAM, "vk-blend map range failed");
+
+ uint32_t gauss_start_pos = (info.width - gauss_table.size ()) / 2;
+ uint32_t idx = 0;
+ for (idx = 0; idx < gauss_start_pos; ++idx) {
+ mask_ptr[idx] = 255;
+ }
+ for (uint32_t i = 0; i < gauss_table.size (); ++idx, ++i) {
+ mask_ptr[idx] = (uint8_t) gauss_table[i];
+ }
+ for (; idx < info.width; ++idx) {
+ mask_ptr[idx] = 0;
+ }
+ buf->unmap ();
+
+ layer.mask = buf;
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::scale_down_mask (SmartPtr<VKDevice> dev, uint32_t level)
+{
+ XCAM_ASSERT (level >= 1 && level < pyr_layers_num);
+
+ PyrLayer &layer = pyr_layer[level];
+ PyrLayer &prev_layer = pyr_layer[level - 1];
+
+ XCAM_ASSERT (prev_layer.mask.ptr ());
+ XCAM_ASSERT (layer.blend_width && ((layer.blend_width % VK_BLENDER_ALIGN_X) == 0));
+
+ uint32_t buf_size = layer.blend_width * sizeof (uint8_t);
+ SmartPtr<VKBuffer> buf = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, buf_size);
+ XCAM_ASSERT (buf.ptr ());
+
+ VKBufInfo info;
+ info.width = layer.blend_width;
+ info.height = 1;
+ info.size = buf_size;
+ buf->set_buf_info (info);
+
+ const VKBufInfo prev_info = prev_layer.mask->get_buf_info ();
+ uint8_t *prev_ptr = (uint8_t *) prev_layer.mask->map (prev_info.size, 0);
+ XCAM_FAIL_RETURN (ERROR, prev_ptr, XCAM_RETURN_ERROR_PARAM, "vk-blend map range failed");
+
+ uint8_t *cur_ptr = (uint8_t *) buf->map (info.size, 0);
+ XCAM_FAIL_RETURN (ERROR, cur_ptr, XCAM_RETURN_ERROR_PARAM, "vk-blend map range failed");
+
+ for (uint32_t i = 0; i < info.width; ++i) {
+ int prev_start = i * 2 - 2;
+ float sum = 0.0f;
+
+ for (int j = 0; j < GAUSS_DIAMETER; ++j) {
+ int prev_idx = XCAM_CLAMP (prev_start + j, 0, (int)prev_info.width);
+ sum += prev_ptr[prev_idx] * gauss_coeffs[j];
+ }
+
+ cur_ptr[i] = XCAM_CLAMP (sum, 0.0f, 255.0f);
+ }
+
+ buf->unmap ();
+ prev_layer.mask->unmap ();
+
+ layer.mask = buf;
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::layerx_allocate_bufs (SmartPtr<VKDevice> dev, uint32_t level)
+{
+ XCAM_ASSERT (level >= 1 && level < pyr_layers_num);
+
+ PyrLayer &layer = pyr_layer[level];
+ PyrLayer &prev_layer = pyr_layer[level - 1];
+ XCAM_FAIL_RETURN (
+ ERROR, prev_layer.blend_width && prev_layer.blend_height, XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid blend size:%dx%d", prev_layer.blend_width, prev_layer.blend_height);
+
+ layer.blend_width = XCAM_ALIGN_UP ((prev_layer.blend_width + 1) / 2, VK_BLENDER_ALIGN_X);
+ layer.blend_height = XCAM_ALIGN_UP ((prev_layer.blend_height + 1) / 2, VK_BLENDER_ALIGN_Y);
+
+ XCamReturn ret = allocate_vk_bufs (dev, level);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend build vk buffers failed, level:%d", level);
+
+ ret = scale_down_mask (dev, level);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend scale down mask failed, level:%d", level);
+
+ return ret;
+}
+
+static XCamReturn
+check_desc (
+ const VideoBufferInfo &in0_info, const VideoBufferInfo &in1_info,
+ const Rect &merge0_area, const Rect &merge1_area)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ in0_info.width && in0_info.height && in1_info.width &&
+ in0_info.height == in1_info.height,
+ XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid buffer size: in0:%dx%d in1:%dx%d out:%dx%d",
+ in0_info.width, in0_info.height, in1_info.width, in1_info.height);
+
+ XCAM_FAIL_RETURN (
+ ERROR,
+ merge0_area.width && merge0_area.width == merge1_area.width &&
+ merge0_area.pos_y == 0 && merge1_area.pos_y == 0 &&
+ merge0_area.height == merge1_area.height && merge0_area.height == (int32_t)in0_info.height,
+ XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid merge area: merge0(%d, %d, %d, %d) merge1(%d, %d, %d, %d)",
+ merge0_area.pos_x, merge0_area.pos_y, merge0_area.width, merge0_area.height,
+ merge1_area.pos_x, merge1_area.pos_y, merge1_area.width, merge1_area.height);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::init_layers_bufs (const SmartPtr<ImageHandler::Parameters> &base)
+{
+ XCAM_ASSERT (base.ptr ());
+ SmartPtr<VKBlender::BlenderParam> param = base.dynamic_cast_ptr<VKBlender::BlenderParam> ();
+ XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->in1_buf.ptr ());
+
+ const VideoBufferInfo &in0_info = param->in_buf->get_video_info ();
+ const VideoBufferInfo &in1_info = param->in1_buf->get_video_info ();
+ const Rect merge0_area = _blender->get_input_merge_area (VKBlender::BufIdx0);
+ const Rect merge1_area = _blender->get_input_merge_area (VKBlender::BufIdx1);
+
+ XCamReturn ret = check_desc (in0_info, in1_info, merge0_area, merge1_area);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend check desc failed");
+
+ PyrLayer &layer0 = pyr_layer[0];
+ layer0.blend_width = XCAM_ALIGN_UP (merge0_area.width, VK_BLENDER_ALIGN_X);
+ layer0.blend_height = XCAM_ALIGN_UP (merge0_area.height, VK_BLENDER_ALIGN_Y);
+
+ SmartPtr<VKDevice> dev = _blender->get_vk_device ();
+ XCAM_ASSERT (dev.ptr ());
+
+ ret = bind_io_bufs_to_layer0 (param->in_buf, param->in1_buf, param->out_buf);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend bind bufs to layer0 failed");
+ ret = layer0_allocate_bufs (dev);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend layer0 build buffers failed");
+ ret = layer0_init_mask (dev);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend layer0 init mask failed");
+
+ for (uint32_t level = 1; level < pyr_layers_num; ++level) {
+ layerx_allocate_bufs (dev, level);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-blend build buffers failed, level:%d", level);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+static SmartPtr<VKWorker>
+create_gauss_scale_pyr_shader (const SmartPtr<VKBlender> &blender)
+{
+ SmartPtr<VKDevice> dev = blender->get_vk_device ();
+ XCAM_ASSERT (dev.ptr ());
+
+ GaussScalePushConstsProp prop;
+ VKConstRange::VKPushConstArgs push_consts;
+ push_consts.push_back (new VKGaussScalePushConst (prop));
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < GS_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ SmartPtr<VKWorker> worker = new VKWorker (dev, "VKGaussScaleShader", new CbGaussScalePyr (blender));
+ XCAM_ASSERT (worker.ptr ());
+
+ XCamReturn ret = worker->build (shaders_info[ShaderGaussScalePyr], binding_layout, push_consts);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKGaussScaleShader failed");
+
+ return worker;
+}
+
+static SmartPtr<VKWorker>
+create_lap_trans_pyr_shader (const SmartPtr<VKBlender> &blender)
+{
+ SmartPtr<VKDevice> dev = blender->get_vk_device ();
+ XCAM_ASSERT (dev.ptr ());
+
+ LapPushConstsProp prop;
+ VKConstRange::VKPushConstArgs push_consts;
+ push_consts.push_back (new VKLapPushConst (prop));
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < LAP_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ SmartPtr<VKWorker> worker = new VKWorker (dev, "VKLapTransShader", new CbLapTransPyr (blender));
+ XCAM_ASSERT (worker.ptr ());
+
+ XCamReturn ret = worker->build (shaders_info[ShaderLapTransPyr], binding_layout, push_consts);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKLapTransShader failed");
+
+ return worker;
+}
+
+static SmartPtr<VKWorker>
+create_blend_pyr_shader (const SmartPtr<VKBlender> &blender)
+{
+ SmartPtr<VKDevice> dev = blender->get_vk_device ();
+ XCAM_ASSERT (dev.ptr ());
+
+ BlendPushConstsProp prop;
+ VKConstRange::VKPushConstArgs push_consts;
+ push_consts.push_back (new VKBlendPushConst (prop));
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < BLEND_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ SmartPtr<VKWorker> worker = new VKWorker (dev, "VKBlendPyrShader", new CbBlendPyr (blender));
+ XCAM_ASSERT (worker.ptr ());
+
+ XCamReturn ret = worker->build (shaders_info[ShaderBlendPyr], binding_layout, push_consts);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKBlendPyrShader failed");
+
+ return worker;
+}
+
+static SmartPtr<VKWorker>
+create_reconstruct_pyr_shader (const SmartPtr<VKBlender> &blender)
+{
+ SmartPtr<VKDevice> dev = blender->get_vk_device ();
+ XCAM_ASSERT (dev.ptr ());
+
+ ReconstructPushConstsProp prop;
+ VKConstRange::VKPushConstArgs push_consts;
+ push_consts.push_back (new VKReconstructPushConst (prop));
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < RECONSTRUCT_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ SmartPtr<VKWorker> worker = new VKWorker (dev, "VKReconstructShader", new CbReconstructPyr (blender));
+ XCAM_ASSERT (worker.ptr ());
+
+ XCamReturn ret = worker->build (shaders_info[ShaderReconstructPyr], binding_layout, push_consts);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKReconstructShader failed");
+
+ return worker;
+}
+
+XCamReturn
+BlenderImpl::create_workers (const SmartPtr<VKBlender> &blender)
+{
+ XCAM_ASSERT (blender.ptr ());
+
+ VKWorkers::iterator i = _workers.find (ShaderGaussScalePyr);
+ if (i == _workers.end ()) {
+ SmartPtr<VKWorker> gauss_scale = create_gauss_scale_pyr_shader (blender);
+ XCAM_ASSERT (gauss_scale.ptr ());
+ _workers.insert (std::make_pair (ShaderGaussScalePyr, gauss_scale));
+ }
+
+ i = _workers.find (ShaderLapTransPyr);
+ if (i == _workers.end ()) {
+ SmartPtr<VKWorker> lap_trans = create_lap_trans_pyr_shader (blender);
+ XCAM_ASSERT (lap_trans.ptr ());
+ _workers.insert (std::make_pair (ShaderLapTransPyr, lap_trans));
+ }
+
+ i = _workers.find (ShaderBlendPyr);
+ if (i == _workers.end ()) {
+ SmartPtr<VKWorker> blend = create_blend_pyr_shader (blender);
+ XCAM_ASSERT (blend.ptr ());
+ _workers.insert (std::make_pair (ShaderBlendPyr, blend));
+ }
+
+ i = _workers.find (ShaderReconstructPyr);
+ if (i == _workers.end ()) {
+ SmartPtr<VKWorker> reconstruct = create_reconstruct_pyr_shader (blender);
+ XCAM_ASSERT (reconstruct.ptr ());
+ _workers.insert (std::make_pair (ShaderReconstructPyr, reconstruct));
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::redirect_workers ()
+{
+ VKWorkers::iterator i = _workers.find (ShaderGaussScalePyr);
+ XCAM_ASSERT (i != _workers.end ());
+ SmartPtr<VKWorker> gauss_scale = i->second;
+
+ i = _workers.find (ShaderLapTransPyr);
+ XCAM_ASSERT (i != _workers.end ());
+ SmartPtr<VKWorker> lap_trans = i->second;
+
+ i = _workers.find (ShaderBlendPyr);
+ XCAM_ASSERT (i != _workers.end ());
+ SmartPtr<VKWorker> top_blend = i->second;
+
+ i = _workers.find (ShaderReconstructPyr);
+ XCAM_ASSERT (i != _workers.end ());
+ SmartPtr<VKWorker> reconstruct = i->second;
+
+ XCAM_ASSERT (gauss_scale.ptr () && lap_trans.ptr () && reconstruct.ptr () && top_blend.ptr ());
+ for (uint32_t i = 0; i < pyr_layers_num - 1; ++i) {
+ PyrLayer &layer_next = pyr_layer[i + 1];
+ layer_next.gauss_scale[VKBlender::BufIdx0] = gauss_scale.ptr ();
+ layer_next.gauss_scale[VKBlender::BufIdx1] = gauss_scale.ptr ();
+
+ PyrLayer &layer = pyr_layer[i];
+ layer.lap_trans[VKBlender::BufIdx0] = lap_trans.ptr ();
+ layer.lap_trans[VKBlender::BufIdx1] = lap_trans.ptr ();
+ layer.reconstruct = reconstruct.ptr ();
+ }
+
+ PyrLayer &top_layer = pyr_layer[pyr_layers_num - 1];
+ top_layer.blend = top_blend.ptr ();
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::fix_parameters ()
+{
+ for (uint32_t i = 0; i < pyr_layers_num - 1; ++i) {
+ fix_gs_params (i + 1, VKBlender::BufIdx0);
+ fix_gs_params (i + 1, VKBlender::BufIdx1);
+
+ fix_lap_trans_params (i, VKBlender::BufIdx0);
+ fix_lap_trans_params (i, VKBlender::BufIdx1);
+
+ fix_reconstruct_params (i);
+ }
+
+ fix_blend_params ();
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::fix_gs_params (uint32_t level, VKBlender::BufIdx idx)
+{
+ XCAM_ASSERT (level >= 1);
+
+ uint32_t level_in = level - 1;
+ PyrLayer &layer_in = pyr_layer[level_in];
+ PyrLayer &layer_out = pyr_layer[level];
+ XCAM_ASSERT (layer_out.gs_buf[idx].ptr () && (layer_in.gs_buf[idx].ptr () || level == 1));
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < GS_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ VKDescriptor::SetBindInfoArray bindings (GS_SHADER_BINDING_COUNT);
+ bindings[0].layout = binding_layout[0];
+ bindings[1].layout = binding_layout[1];
+ if (layer_in.gs_buf[idx].ptr ()) {
+ bindings[0].desc = VKBufDesc (layer_in.gs_buf[idx], NV12PlaneYIdx);
+ bindings[1].desc = VKBufDesc (layer_in.gs_buf[idx], NV12PlaneUVIdx);
+ }
+ bindings[2].layout = binding_layout[2];
+ bindings[2].desc = VKBufDesc (layer_out.gs_buf[idx], NV12PlaneYIdx);
+ bindings[3].layout = binding_layout[3];
+ bindings[3].desc = VKBufDesc (layer_out.gs_buf[idx], NV12PlaneUVIdx);
+ layer_out.gs_bindings[idx] = bindings;
+
+ const VKBufInfo in_info = layer_in.gs_buf[idx]->get_buf_info ();
+ const VKBufInfo out_info = layer_out.gs_buf[idx]->get_buf_info ();
+
+ size_t unit_bytes = sizeof (uint32_t);
+ GaussScalePushConstsProp prop;
+ prop.in_img_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes;
+ prop.in_img_height = in_info.height;
+ prop.out_img_width = XCAM_ALIGN_UP (out_info.width, unit_bytes) / unit_bytes;
+ prop.out_img_height = out_info.height;
+ if (level == 1) {
+ const Rect area = _blender->get_input_merge_area (idx);
+ prop.in_offset_x = XCAM_ALIGN_UP (area.pos_x, unit_bytes) / unit_bytes;
+ prop.merge_width = XCAM_ALIGN_UP (area.width, unit_bytes) / unit_bytes;
+ } else {
+ prop.in_offset_x = 0;
+ prop.merge_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes;
+ }
+ layer_out.gs_consts[idx] = new VKGaussScalePushConst (prop);
+
+ layer_out.gs_global_size[idx] = WorkSize (
+ XCAM_ALIGN_UP (prop.out_img_width, 8) / 8,
+ XCAM_ALIGN_UP (out_info.height, 16) / 16);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::fix_lap_trans_params (uint32_t level, VKBlender::BufIdx idx)
+{
+ XCAM_ASSERT (level < pyr_layers_num - 1);
+
+ PyrLayer &layer = pyr_layer[level];
+ PyrLayer &layer_next = pyr_layer[level + 1];
+ XCAM_ASSERT ((layer.gs_buf[idx].ptr () || level == 0) && layer_next.gs_buf[idx].ptr ());
+ XCAM_ASSERT (layer.lap_buf[idx].ptr ());
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < LAP_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ VKDescriptor::SetBindInfoArray bindings (LAP_SHADER_BINDING_COUNT);
+ bindings[0].layout = binding_layout[0];
+ bindings[1].layout = binding_layout[1];
+ if (layer.gs_buf[idx].ptr ()) {
+ bindings[0].desc = VKBufDesc (layer.gs_buf[idx], NV12PlaneYIdx);
+ bindings[1].desc = VKBufDesc (layer.gs_buf[idx], NV12PlaneUVIdx);
+ }
+ bindings[2].layout = binding_layout[2];
+ bindings[2].desc = VKBufDesc (layer_next.gs_buf[idx], NV12PlaneYIdx);
+ bindings[3].layout = binding_layout[3];
+ bindings[3].desc = VKBufDesc (layer_next.gs_buf[idx], NV12PlaneUVIdx);
+ bindings[4].layout = binding_layout[4];
+ bindings[4].desc = VKBufDesc (layer.lap_buf[idx], NV12PlaneYIdx);
+ bindings[5].layout = binding_layout[5];
+ bindings[5].desc = VKBufDesc (layer.lap_buf[idx], NV12PlaneUVIdx);
+ layer.lap_bindings[idx] = bindings;
+
+ const VKBufInfo in_info = layer.gs_buf[idx]->get_buf_info ();
+ const VKBufInfo gs_info = layer_next.gs_buf[idx]->get_buf_info ();
+
+ size_t unit_bytes = sizeof (uint32_t) * 2;
+ LapPushConstsProp prop;
+ prop.in_img_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes;
+ prop.in_img_height = in_info.height;
+ prop.gaussscale_img_width = XCAM_ALIGN_UP (gs_info.width, sizeof (uint32_t)) / sizeof (uint32_t);
+ prop.gaussscale_img_height = gs_info.height;
+ if (level == 0) {
+ const Rect area = _blender->get_input_merge_area (idx);
+ prop.in_offset_x = XCAM_ALIGN_UP (area.pos_x, unit_bytes) / unit_bytes;
+ prop.merge_width = XCAM_ALIGN_UP (area.width, unit_bytes) / unit_bytes;
+ } else {
+ prop.in_offset_x = 0;
+ prop.merge_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes;
+ }
+ layer.lap_consts[idx] = new VKLapPushConst (prop);
+
+ layer.lap_global_size[idx] = WorkSize (
+ XCAM_ALIGN_UP (prop.merge_width, 8) / 8,
+ XCAM_ALIGN_UP (in_info.height, 32) / 32);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::fix_blend_params ()
+{
+ PyrLayer &top_layer = pyr_layer[pyr_layers_num - 1];
+ XCAM_ASSERT (top_layer.gs_buf[VKBlender::BufIdx0].ptr () && top_layer.gs_buf[VKBlender::BufIdx1].ptr ());
+ XCAM_ASSERT (top_layer.mask.ptr ());
+ XCAM_ASSERT (top_layer.blend_buf.ptr ());
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < BLEND_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ VKDescriptor::SetBindInfoArray bindings (BLEND_SHADER_BINDING_COUNT);
+ bindings[0].layout = binding_layout[0];
+ bindings[0].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx0], NV12PlaneYIdx);
+ bindings[1].layout = binding_layout[1];
+ bindings[1].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx0], NV12PlaneUVIdx);
+ bindings[2].layout = binding_layout[2];
+ bindings[2].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx1], NV12PlaneYIdx);
+ bindings[3].layout = binding_layout[3];
+ bindings[3].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx1], NV12PlaneUVIdx);
+ bindings[4].layout = binding_layout[4];
+ bindings[4].desc = VKBufDesc (top_layer.blend_buf, NV12PlaneYIdx);
+ bindings[5].layout = binding_layout[5];
+ bindings[5].desc = VKBufDesc (top_layer.blend_buf, NV12PlaneUVIdx);
+ bindings[6].layout = binding_layout[6];
+ bindings[6].desc = VKBufDesc (top_layer.mask);
+ top_layer.blend_bindings = bindings;
+
+ const VKBufInfo in0_info = top_layer.gs_buf[VKBlender::BufIdx0]->get_buf_info ();
+ size_t unit_bytes = sizeof (uint32_t) * 2;
+ BlendPushConstsProp prop;
+ prop.in_img_width = XCAM_ALIGN_UP (in0_info.width, unit_bytes) / unit_bytes;
+ top_layer.blend_consts = new VKBlendPushConst (prop);
+
+ top_layer.blend_global_size = WorkSize (
+ XCAM_ALIGN_UP (prop.in_img_width, 8) / 8,
+ XCAM_ALIGN_UP (in0_info.height, 16) / 16);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::fix_reconstruct_params (uint32_t level)
+{
+ XCAM_ASSERT (level < pyr_layers_num - 1);
+
+ PyrLayer &layer = pyr_layer[level];
+ PyrLayer &prev_layer = pyr_layer[level + 1];
+
+ XCAM_ASSERT (layer.lap_buf[VKBlender::BufIdx0].ptr ());
+ XCAM_ASSERT (layer.lap_buf[VKBlender::BufIdx1].ptr ());
+ XCAM_ASSERT (prev_layer.reconstruct_buf.ptr () && (layer.reconstruct_buf.ptr () || level == 0));
+ XCAM_ASSERT (layer.mask.ptr ());
+
+ VKDescriptor::BindingArray binding_layout;
+ binding_layout.clear ();
+ for (int i = 0; i < RECONSTRUCT_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ binding_layout.push_back (binding);
+ }
+
+ VKDescriptor::SetBindInfoArray bindings (RECONSTRUCT_SHADER_BINDING_COUNT);
+ bindings[0].layout = binding_layout[0];
+ bindings[0].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx0], NV12PlaneYIdx);
+ bindings[1].layout = binding_layout[1];
+ bindings[1].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx0], NV12PlaneUVIdx);
+ bindings[2].layout = binding_layout[2];
+ bindings[2].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx1], NV12PlaneYIdx);
+ bindings[3].layout = binding_layout[3];
+ bindings[3].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx1], NV12PlaneUVIdx);
+ bindings[4].layout = binding_layout[4];
+ bindings[5].layout = binding_layout[5];
+ if (layer.reconstruct_buf.ptr ()) {
+ bindings[4].desc = VKBufDesc (layer.reconstruct_buf, NV12PlaneYIdx);
+ bindings[5].desc = VKBufDesc (layer.reconstruct_buf, NV12PlaneUVIdx);
+ }
+ bindings[6].layout = binding_layout[6];
+ bindings[6].desc = VKBufDesc (prev_layer.reconstruct_buf, NV12PlaneYIdx);
+ bindings[7].layout = binding_layout[7];
+ bindings[7].desc = VKBufDesc (prev_layer.reconstruct_buf, NV12PlaneUVIdx);
+ bindings[8].layout = binding_layout[8];
+ bindings[8].desc = VKBufDesc (layer.mask);
+ layer.reconstruct_bindings = bindings;
+
+ const VKBufInfo lap0_info = layer.lap_buf[VKBlender::BufIdx0]->get_buf_info ();
+ const VKBufInfo prev_recons_info = prev_layer.reconstruct_buf->get_buf_info ();
+
+ size_t unit_bytes = sizeof (uint32_t) * 2;
+ ReconstructPushConstsProp prop;
+ prop.lap_img_width = XCAM_ALIGN_UP (lap0_info.width, unit_bytes) / unit_bytes;
+ prop.lap_img_height = lap0_info.height;
+ prop.prev_blend_img_width = XCAM_ALIGN_UP (prev_recons_info.width, sizeof (uint32_t)) / sizeof (uint32_t);
+ prop.prev_blend_img_height = prev_recons_info.height;
+ if (level == 0) {
+ const VideoBufferInfo info = _blender->get_out_video_info ();
+ prop.out_img_width = XCAM_ALIGN_UP (info.width, unit_bytes) / unit_bytes;
+
+ const Rect area = _blender->get_merge_window ();
+ prop.out_offset_x = XCAM_ALIGN_UP (area.pos_x, unit_bytes) / unit_bytes;
+ } else {
+ const VKBufInfo info = layer.reconstruct_buf->get_buf_info ();
+ prop.out_img_width = XCAM_ALIGN_UP (info.width, unit_bytes) / unit_bytes;
+ prop.out_offset_x = 0;
+ }
+ layer.reconstruct_consts = new VKReconstructPushConst (prop);
+
+ layer.reconstruct_global_size = WorkSize (
+ XCAM_ALIGN_UP (prop.lap_img_width, 8) / 8,
+ XCAM_ALIGN_UP (lap0_info.height, 32) / 32);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::start_gauss_scale (uint32_t level, VKBlender::BufIdx idx)
+{
+ XCAM_ASSERT (level >= 1 && level < pyr_layers_num);
+
+ PyrLayer &layer = pyr_layer[level];
+ layer.gauss_scale[idx]->set_global_size (layer.gs_global_size[idx]);
+
+ SmartPtr<BlendArgs> args = new BlendArgs (level, idx);
+ args->set_bindings (layer.gs_bindings[idx]);
+ args->add_push_const (layer.gs_consts[idx]);
+
+ return layer.gauss_scale[idx]->work (args);
+}
+
+XCamReturn
+BlenderImpl::start_lap_tran (uint32_t level, VKBlender::BufIdx idx)
+{
+ PyrLayer &layer = pyr_layer[level];
+
+ SmartPtr<VKBlender::Sync> &sync = layer.lap_sync[idx];
+ if (!sync->is_synced ())
+ return XCAM_RETURN_NO_ERROR;
+ sync->reset ();
+
+ layer.lap_trans[idx]->set_global_size (layer.lap_global_size[idx]);
+
+ SmartPtr<BlendArgs> args = new BlendArgs (level, idx);
+ args->set_bindings (layer.lap_bindings[idx]);
+ args->add_push_const (layer.lap_consts[idx]);
+
+ return layer.lap_trans[idx]->work (args);
+}
+
+XCamReturn
+BlenderImpl::start_lap_trans (uint32_t level, VKBlender::BufIdx idx)
+{
+ XCAM_ASSERT (level >= 1 && level < pyr_layers_num);
+
+ uint32_t pre_level = level - 1;
+ pyr_layer[pre_level].lap_sync[idx]->increment ();
+
+ XCamReturn ret = start_lap_tran (pre_level, idx);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-blend start lap tran failed, level:%d idx:%d", pre_level, idx);
+
+ if (level == pyr_layers_num - 1)
+ return XCAM_RETURN_NO_ERROR;
+ pyr_layer[level].lap_sync[idx]->increment ();
+
+ ret = start_lap_tran (level, idx);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-blend start lap tran failed, level:%d idx:%d", level, idx);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+BlenderImpl::start_top_blend ()
+{
+ uint32_t level = pyr_layers_num - 1;
+ PyrLayer &layer = pyr_layer[level];
+
+ SmartPtr<VKBlender::Sync> &sync = layer.blend_sync;
+ if (!sync->is_synced ())
+ return XCAM_RETURN_NO_ERROR;
+ sync->reset ();
+
+ SmartPtr<VKWorker::VKArguments> args = new VKWorker::VKArguments;
+ args->set_bindings (layer.blend_bindings);
+ args->add_push_const (layer.blend_consts);
+
+ layer.blend->set_global_size (layer.blend_global_size);
+
+ return layer.blend->work (args);
+}
+
+XCamReturn
+BlenderImpl::start_reconstruct (uint32_t level)
+{
+ XCAM_ASSERT (level < pyr_layers_num - 1);
+ PyrLayer &layer = pyr_layer[level];
+
+ SmartPtr<VKBlender::Sync> &sync = layer.reconstruct_sync;
+ if (!sync->is_synced ())
+ return XCAM_RETURN_NO_ERROR;
+ sync->reset ();
+
+ SmartPtr<BlendArgs> args = new BlendArgs (level);
+ args->set_bindings (layer.reconstruct_bindings);
+ args->add_push_const (layer.reconstruct_consts);
+
+ layer.reconstruct->set_global_size (layer.reconstruct_global_size);
+
+ return layer.reconstruct->work (args);
+}
+
+XCamReturn
+BlenderImpl::stop ()
+{
+ for (uint32_t lv = 0; lv < pyr_layers_num; ++lv) {
+ pyr_layer[lv].gs_buf[VKBlender::BufIdx0].release ();
+ pyr_layer[lv].gs_buf[VKBlender::BufIdx1].release ();
+ pyr_layer[lv].lap_buf[VKBlender::BufIdx0].release ();
+ pyr_layer[lv].lap_buf[VKBlender::BufIdx1].release ();
+ pyr_layer[lv].reconstruct_buf.release ();
+ pyr_layer[lv].blend_buf.release ();
+
+ pyr_layer[lv].gs_consts[VKBlender::BufIdx0].release ();
+ pyr_layer[lv].gs_consts[VKBlender::BufIdx1].release ();
+ pyr_layer[lv].lap_consts[VKBlender::BufIdx0].release ();
+ pyr_layer[lv].lap_consts[VKBlender::BufIdx1].release ();
+ pyr_layer[lv].reconstruct_consts.release ();
+ pyr_layer[lv].blend_consts.release ();
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+}
+
+VKBlender::VKBlender (const SmartPtr<VKDevice> dev, const char *name)
+ : VKHandler (dev, name)
+ , Blender (VK_BLENDER_ALIGN_X, VK_BLENDER_ALIGN_Y)
+{
+ SmartPtr<VKBlenderPriv::BlenderImpl> impl =
+ new VKBlenderPriv::BlenderImpl (this, XCAM_VK_DEFAULT_LEVEL);
+ XCAM_ASSERT (impl.ptr ());
+
+ _impl = impl;
+}
+
+VKBlender::~VKBlender ()
+{
+}
+
+XCamReturn
+VKBlender::blend (
+ const SmartPtr<VideoBuffer> &in0, const SmartPtr<VideoBuffer> &in1, SmartPtr<VideoBuffer> &out_buf)
+{
+ XCAM_ASSERT (in0.ptr () && in1.ptr ());
+
+ SmartPtr<BlenderParam> param = new BlenderParam (in0, in1, out_buf);
+ XCAM_ASSERT (param.ptr ());
+
+ XCamReturn ret = execute_buffer (param, true);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend execute buffer failed");
+
+ finish ();
+ if (!out_buf.ptr ()) {
+ out_buf = param->out_buf;
+ }
+
+ return ret;
+}
+
+static XCamReturn
+check_merge_area (const SmartPtr<VKBlender> &blender)
+{
+ Rect in0_area, in1_area, out_area;
+
+ in0_area = blender->get_input_merge_area (VKBlender::BufIdx0);
+ XCAM_FAIL_RETURN (
+ ERROR,
+ in0_area.pos_y == 0 && in0_area.width && in0_area.height &&
+ in0_area.pos_x % VK_BLENDER_ALIGN_X == 0 &&
+ in0_area.width % VK_BLENDER_ALIGN_X == 0 &&
+ in0_area.height % VK_BLENDER_ALIGN_Y == 0,
+ XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid input0 merge area, pos_x:%d, pos_y:%d, width:%d, height:%d",
+ in0_area.pos_x, in0_area.pos_y, in0_area.width, in0_area.height);
+
+ in1_area = blender->get_input_merge_area (VKBlender::BufIdx1);
+ XCAM_FAIL_RETURN (
+ ERROR,
+ in1_area.pos_y == 0 && in1_area.width && in1_area.height &&
+ in1_area.pos_x % VK_BLENDER_ALIGN_X == 0 &&
+ in1_area.width % VK_BLENDER_ALIGN_X == 0 &&
+ in1_area.height % VK_BLENDER_ALIGN_Y == 0,
+ XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid input1 merge area, pos_x:%d, pos_y:%d, width:%d, height:%d",
+ in1_area.pos_x, in1_area.pos_y, in1_area.width, in1_area.height);
+
+ out_area = blender->get_merge_window ();
+ XCAM_FAIL_RETURN (
+ ERROR,
+ out_area.pos_y == 0 && out_area.width && out_area.height &&
+ out_area.pos_x % VK_BLENDER_ALIGN_X == 0 &&
+ out_area.width % VK_BLENDER_ALIGN_X == 0 &&
+ out_area.height % VK_BLENDER_ALIGN_Y == 0,
+ XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid output merge area, pos_x:%d, pos_y:%d, width:%d, height:%d",
+ out_area.pos_x, out_area.pos_y, out_area.width, out_area.height);
+
+ XCAM_FAIL_RETURN (
+ ERROR,
+ in0_area.width == in1_area.width && in0_area.height == in1_area.height &&
+ in0_area.width == out_area.width && in0_area.height == out_area.height,
+ XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid input or output overlap area, input0:%dx%d, input1:%dx%d, output:%dx%d",
+ in0_area.width, in0_area.height, in1_area.width, in1_area.height, out_area.width, out_area.height);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKBlender::set_output_info (const SmartPtr<ImageHandler::Parameters> &param)
+{
+ const VideoBufferInfo &in0_info = param->in_buf->get_video_info ();
+ XCAM_FAIL_RETURN (
+ ERROR, in0_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM,
+ "vk-blend only support NV12 format, but input format is %s",
+ xcam_fourcc_to_string (in0_info.format));
+
+ uint32_t out_width, out_height;
+ get_output_size (out_width, out_height);
+ XCAM_FAIL_RETURN (
+ ERROR, out_width && out_height, XCAM_RETURN_ERROR_PARAM,
+ "vk-blend invalid output size:%dx%d", out_width, out_height);
+
+ VideoBufferInfo out_info;
+ out_info.init (
+ in0_info.format, out_width, out_height,
+ XCAM_ALIGN_UP (out_width, VK_BLENDER_ALIGN_X),
+ XCAM_ALIGN_UP (out_height, VK_BLENDER_ALIGN_Y));
+ set_out_video_info (out_info);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKBlender::configure_resource (const SmartPtr<Parameters> &param)
+{
+ XCAM_ASSERT (param.ptr ());
+ XCAM_ASSERT (_impl->pyr_layers_num <= XCAM_VK_MAX_LEVEL);
+
+ SmartPtr<BlenderParam> blend_param = param.dynamic_cast_ptr<BlenderParam> ();
+ XCAM_ASSERT (blend_param.ptr () && blend_param->in_buf.ptr () && blend_param->in1_buf.ptr ());
+
+ XCamReturn ret = set_output_info (param);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend set output video info failed");
+
+ ret = check_merge_area (this);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend check merge area failed");
+
+ _impl->init_syncs ();
+
+ ret = _impl->init_layers_bufs (param);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend init buffers failed");
+
+ ret = _impl->fix_parameters ();
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend fix parameters failed");
+
+ ret = _impl->create_workers (this);
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend create workers failed");
+
+ ret = _impl->redirect_workers ();
+ XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend redirect workers failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKBlender::start_work (const SmartPtr<ImageHandler::Parameters> &param)
+{
+ SmartPtr<VKBlender::BlenderParam> blend_param = param.dynamic_cast_ptr<BlenderParam> ();
+ XCAM_ASSERT (blend_param.ptr ());
+ XCAM_ASSERT (blend_param->in_buf.ptr () && blend_param->in1_buf.ptr () && blend_param->out_buf.ptr ());
+
+#if DUMP_BUFFER
+ SmartPtr<VKVideoBuffer> in0_vk = blend_param->in_buf.dynamic_cast_ptr<VKVideoBuffer> ();
+ SmartPtr<VKVideoBuffer> in1_vk = blend_param->in1_buf.dynamic_cast_ptr<VKVideoBuffer> ();
+ XCAM_ASSERT (in0_vk.ptr () && in1_vk.ptr ());
+ dump_level_vkbuf (in0_vk->get_vk_buf (), "blend-in", 0, VKBlender::BufIdx0);
+ dump_level_vkbuf (in1_vk->get_vk_buf (), "blend-in", 0, VKBlender::BufIdx1);
+#endif
+
+ _impl->bind_io_bufs_to_layer0 (blend_param->in_buf, blend_param->in1_buf, blend_param->out_buf);
+ _impl->bind_io_vkbufs_to_desc ();
+
+ _impl->pyr_layer[0].lap_sync[BufIdx0]->increment ();
+ _impl->pyr_layer[0].lap_sync[BufIdx1]->increment ();
+
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ ret = _impl->start_gauss_scale (1, BufIdx0);
+ CHECK_RET (ret, "vk-blend start gauss scale failed, level:1 index:0\n");
+
+ ret = _impl->start_gauss_scale (1, BufIdx1);
+ CHECK_RET (ret, "vk-blend start gauss scale failed, level:1 index:1\n");
+
+ execute_done (param, ret);
+
+ return ret;
+}
+
+void
+VKBlender::gauss_scale_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error)
+{
+ if (!xcam_ret_is_ok (error)) {
+ XCAM_LOG_ERROR ("vk-blend gauss scale failed");
+ return ;
+ }
+
+ SmartPtr<VKBlenderPriv::BlendArgs> args = base.dynamic_cast_ptr<VKBlenderPriv::BlendArgs> ();
+ XCAM_ASSERT (args.ptr ());
+ uint32_t level = args->get_level ();
+ uint32_t next_level = level + 1;
+ BufIdx idx = args->get_idx ();
+
+ SmartPtr<VKWorker> gs_worker = worker.dynamic_cast_ptr<VKWorker> ();
+ XCAM_ASSERT (gs_worker.ptr ());
+ gs_worker->wait_fence ();
+
+#if DUMP_BUFFER
+ dump_level_vkbuf (_impl->pyr_layer[level].gs_buf[idx], "gauss-scale", level, idx);
+#endif
+
+ XCamReturn ret = _impl->start_lap_trans (level, idx);
+ CHECK_RET (ret, "vk-blend execute laplace transformation failed, level:%d idx:%d", level, idx);
+
+ if (next_level == _impl->pyr_layers_num) {
+ _impl->pyr_layer[level].blend_sync->increment ();
+
+ ret = _impl->start_top_blend ();
+ CHECK_RET (ret, "vk-blend execute top blend failed, level:%d idx:%d", level, idx);
+ } else {
+ ret = _impl->start_gauss_scale (next_level, idx);
+ CHECK_RET (ret, "vk-blend execute gauss scale failed, level:%d idx:%d", next_level, idx);
+ }
+}
+
+void
+VKBlender::lap_trans_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error)
+{
+ XCAM_UNUSED (base);
+ if (!xcam_ret_is_ok (error)) {
+ XCAM_LOG_ERROR ("vk-blend laplace transformation failed");
+ return ;
+ }
+
+ SmartPtr<VKBlenderPriv::BlendArgs> args = base.dynamic_cast_ptr<VKBlenderPriv::BlendArgs> ();
+ XCAM_ASSERT (args.ptr ());
+ uint32_t level = args->get_level ();
+
+ SmartPtr<VKWorker> laptrans_worker = worker.dynamic_cast_ptr<VKWorker> ();
+ XCAM_ASSERT (laptrans_worker.ptr ());
+ laptrans_worker->wait_fence ();
+
+#if DUMP_BUFFER
+ BufIdx idx = args->get_idx ();
+ dump_level_vkbuf (_impl->pyr_layer[level].lap_buf[idx], "lap", level, idx);
+#endif
+
+ _impl->pyr_layer[level].reconstruct_sync->increment ();
+
+ XCamReturn ret = _impl->start_reconstruct (level);
+ CHECK_RET (ret, "vk-blend execute reconstruct failed, level:%d", level);
+}
+
+void
+VKBlender::blend_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error)
+{
+ XCAM_UNUSED (base);
+ if (!xcam_ret_is_ok (error)) {
+ XCAM_LOG_ERROR ("vk-blend blend failed");
+ return ;
+ }
+
+ SmartPtr<VKWorker> blend_worker = worker.dynamic_cast_ptr<VKWorker> ();
+ XCAM_ASSERT (blend_worker.ptr ());
+ blend_worker->wait_fence ();
+
+#if DUMP_BUFFER
+ dump_vkbuf (_impl->pyr_layer[_impl->pyr_layers_num - 1].blend_buf, "blend-top");
+#endif
+
+ uint32_t pre_level = _impl->pyr_layers_num - 2;
+ _impl->pyr_layer[pre_level].reconstruct_sync->increment ();
+
+ XCamReturn ret = _impl->start_reconstruct (pre_level);
+ CHECK_RET (ret, "vk-blend execute reconstruct failed, level:%d", pre_level);
+}
+
+void
+VKBlender::reconstruct_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error)
+{
+ XCAM_UNUSED (base);
+ if (!xcam_ret_is_ok (error)) {
+ XCAM_LOG_ERROR ("vk-blend reconstruct failed");
+ return ;
+ }
+
+ SmartPtr<VKBlenderPriv::BlendArgs> args = base.dynamic_cast_ptr<VKBlenderPriv::BlendArgs> ();
+ XCAM_ASSERT (args.ptr ());
+ uint32_t level = args->get_level ();
+
+ SmartPtr<VKWorker> reconstruct_worker = worker.dynamic_cast_ptr<VKWorker> ();
+ XCAM_ASSERT (reconstruct_worker.ptr ());
+ reconstruct_worker->wait_fence ();
+
+#if DUMP_BUFFER
+ BufIdx idx = args->get_idx ();
+ dump_level_vkbuf (_impl->pyr_layer[level].reconstruct_buf, "reconstruct", level, idx);
+#endif
+
+ if (level == 0) {
+ return;
+ }
+
+ uint32_t pre_level = level - 1;
+ _impl->pyr_layer[pre_level].reconstruct_sync->increment ();
+
+ XCamReturn ret = _impl->start_reconstruct (pre_level);
+ CHECK_RET (ret, "vk-blend execute reconstruct failed, level:%d", pre_level);
+}
+
+SmartPtr<VKHandler>
+create_vk_blender (const SmartPtr<VKDevice> &dev)
+{
+ SmartPtr<VKBlender> blender = new VKBlender (dev);
+ XCAM_ASSERT (blender.ptr ());
+
+ return blender;
+}
+
+SmartPtr<Blender>
+Blender::create_vk_blender (const SmartPtr<VKDevice> &dev)
+{
+ SmartPtr<VKHandler> handler = XCam::create_vk_blender (dev);
+ return handler.dynamic_cast_ptr<Blender> ();
+}
+
+}
diff --git a/modules/vulkan/vk_blender.h b/modules/vulkan/vk_blender.h
new file mode 100644
index 0000000..223b48f
--- /dev/null
+++ b/modules/vulkan/vk_blender.h
@@ -0,0 +1,120 @@
+/*
+ * vk_blender.h - vulkan blender class
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Yinhang Liu <yinhangx.liu@intel.com>
+ */
+
+#ifndef XCAM_VK_BLENDER_H
+#define XCAM_VK_BLENDER_H
+
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_handler.h>
+#include <interface/blender.h>
+
+#define VK_BLENDER_ALIGN_X 8
+#define VK_BLENDER_ALIGN_Y 4
+
+#define XCAM_VK_MAX_LEVEL 4
+#define XCAM_VK_DEFAULT_LEVEL 2
+
+namespace XCam {
+
+namespace VKBlenderPriv {
+class BlenderImpl;
+}
+
+class VKBlender
+ : public VKHandler, public Blender
+{
+ friend class VKBlenderPriv::BlenderImpl;
+ friend SmartPtr<VKHandler> create_vk_blender (const SmartPtr<VKDevice> &dev);
+
+public:
+ struct BlenderParam : ImageHandler::Parameters {
+ SmartPtr<VideoBuffer> in1_buf;
+
+ BlenderParam (
+ const SmartPtr<VideoBuffer> &in0,
+ const SmartPtr<VideoBuffer> &in1,
+ const SmartPtr<VideoBuffer> &out)
+ : Parameters (in0, out)
+ , in1_buf (in1)
+ {}
+ };
+
+ class Sync
+ {
+ public:
+ Sync (uint32_t threshold)
+ : _count (0), _threshold (threshold)
+ {}
+
+ void increment () {
+ ++_count;
+ }
+ void reset () {
+ _count = 0;
+ }
+ bool is_synced () {
+ return (_threshold == _count);
+ }
+
+ private:
+ uint32_t _count;
+ const uint32_t _threshold;
+ };
+
+ enum BufIdx {
+ BufIdx0 = 0,
+ BufIdx1,
+ BufIdxMax
+ };
+
+public:
+ ~VKBlender ();
+
+ void gauss_scale_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error);
+ void lap_trans_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error);
+ void blend_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error);
+ void reconstruct_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error);
+
+protected:
+ explicit VKBlender (const SmartPtr<VKDevice> dev, const char *name = "VKBlender");
+
+ // derived from Blender interface
+ XCamReturn blend (
+ const SmartPtr<VideoBuffer> &in0, const SmartPtr<VideoBuffer> &in1, SmartPtr<VideoBuffer> &out);
+
+ // derived from VKHandler
+ XCamReturn configure_resource (const SmartPtr<Parameters> &param);
+ XCamReturn start_work (const SmartPtr<Parameters> &param);
+
+ XCamReturn set_output_info (const SmartPtr<ImageHandler::Parameters> &param);
+
+private:
+ SmartPtr<VKBlenderPriv::BlenderImpl> _impl;
+};
+
+extern SmartPtr<VKHandler> create_vk_blender (const SmartPtr<VKDevice> &dev);
+
+}
+
+#endif // XCAM_VK_BLENDER_H
diff --git a/modules/vulkan/vk_cmdbuf.cpp b/modules/vulkan/vk_cmdbuf.cpp
new file mode 100644
index 0000000..1bc33be
--- /dev/null
+++ b/modules/vulkan/vk_cmdbuf.cpp
@@ -0,0 +1,172 @@
+/*
+ * vk_cmdbuf.cpp - Vulkan command buffer
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_cmdbuf.h"
+#include "vulkan_common.h"
+#include "vk_pipeline.h"
+
+namespace XCam {
+
+VKCmdBuf::Pool::Pool (const SmartPtr<VKDevice> dev, VkCommandPool id)
+ : _pool_id (id)
+ , _dev (dev)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id));
+}
+
+VKCmdBuf::Pool::~Pool ()
+{
+ if (XCAM_IS_VALID_VK_ID (_pool_id))
+ _dev->destroy_cmd_pool (_pool_id);
+}
+
+SmartPtr<VKCmdBuf>
+VKCmdBuf::Pool::allocate_buffer ()
+{
+ //VkCommandBufferAllocateInfo info {};
+ VkCommandBuffer cmd_buf_id = _dev->allocate_cmd_buffer (_pool_id);
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (cmd_buf_id), NULL,
+ "VKCmdBuf allocate cmd buffer failed");
+ return new VKCmdBuf (this, cmd_buf_id);
+}
+
+void
+VKCmdBuf::Pool::free_buffer (VkCommandBuffer buf_id)
+{
+ XCAM_ASSERT (_dev.ptr ());
+ _dev->free_cmd_buffer (_pool_id, buf_id);
+}
+
+SmartPtr<VKCmdBuf::Pool>
+VKCmdBuf::create_pool (const SmartPtr<VKDevice> dev, VkFlags queue_flag)
+{
+ VkCommandPool pool_id = dev->create_cmd_pool (queue_flag);
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (pool_id), NULL,
+ "VKCmdBuf create_pool failed");
+ SmartPtr<VKCmdBuf::Pool> pool = new VKCmdBuf::Pool (dev, pool_id);
+ return pool;
+}
+
+SmartPtr<VKCmdBuf>
+VKCmdBuf::create_command_buffer (
+ const SmartPtr<VKDevice> dev,
+ const SmartPtr<VKCmdBuf::Pool> pool)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, dev.ptr (), NULL,
+ "VKCmdBuf create command buffer failed");
+
+ SmartPtr<VKCmdBuf::Pool> cmdbuf_pool = pool;
+ if (!pool.ptr()) {
+ cmdbuf_pool = create_pool (dev, VK_QUEUE_COMPUTE_BIT);
+ }
+
+ XCAM_FAIL_RETURN (
+ ERROR, cmdbuf_pool.ptr (), NULL,
+ "VKCmdBuf create command pool failed");
+
+ return cmdbuf_pool->allocate_buffer ();
+}
+
+VKCmdBuf::VKCmdBuf (const SmartPtr<VKCmdBuf::Pool> pool, VkCommandBuffer buf_id)
+ : _cmd_buf_id (buf_id)
+ , _pool (pool)
+{
+}
+
+VKCmdBuf::~VKCmdBuf ()
+{
+ if (_pool.ptr () && XCAM_IS_VALID_VK_ID (_cmd_buf_id))
+ _pool->free_buffer (_cmd_buf_id);
+}
+
+VKCmdBuf::DispatchParam::DispatchParam (const SmartPtr<VKPipeline> &p, uint32_t x, uint32_t y, uint32_t z)
+ : _group_size (x, y, z)
+ , _pipeline (p)
+{
+}
+
+VKCmdBuf::DispatchParam::~DispatchParam ()
+{
+}
+
+bool
+VKCmdBuf::DispatchParam::update_push_consts (VKConstRange::VKPushConstArgs & push_consts)
+{
+ _push_consts = push_consts;
+ return true;
+}
+
+XCamReturn
+VKCmdBuf::DispatchParam::fill_cmd_buf (VKCmdBuf &buf)
+{
+ XCamReturn ret = _pipeline->bind_by (buf);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret),
+ ret, "VKCmdBuf DispatchParam fill command buffer failed when binding pipeline");
+
+ for (size_t i = 0; i < _push_consts.size (); ++i) {
+ XCAM_RETURN_CHECK (
+ ERROR, _pipeline->push_consts_by (buf, _push_consts[i]),
+ "VKCmdBuf DispatchParam fill command buffer failed when push consts (:%d)", i);
+ }
+ return buf.dispatch (_group_size);
+}
+
+XCamReturn
+VKCmdBuf::record (const SmartPtr<DispatchParam> param)
+{
+ VkCommandBufferBeginInfo buf_begin_info = {};
+ buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ buf_begin_info.pInheritanceInfo = NULL;
+
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_cmd_buf_id));
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkBeginCommandBuffer (_cmd_buf_id, &buf_begin_info),
+ XCAM_RETURN_ERROR_VULKAN, "VKCmdBuf begin command buffer failed");
+
+ XCamReturn ret = param->fill_cmd_buf (*this);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret),
+ ret, "VKCmdBuf dispatch params failed");
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkEndCommandBuffer (_cmd_buf_id),
+ XCAM_RETURN_ERROR_VULKAN, "VKCmdBuf begin command buffer failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKCmdBuf::dispatch (const GroupSize &group)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, group.x * group.y * group.z > 0,
+ XCAM_RETURN_ERROR_VULKAN, "VKCmdBuf dispatch params failed");
+
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_cmd_buf_id));
+ vkCmdDispatch (_cmd_buf_id, group.x, group.y, group.z);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+}
diff --git a/modules/vulkan/vk_cmdbuf.h b/modules/vulkan/vk_cmdbuf.h
new file mode 100644
index 0000000..458bea3
--- /dev/null
+++ b/modules/vulkan/vk_cmdbuf.h
@@ -0,0 +1,106 @@
+/*
+ * vk_cmdbuf.h - Vulkan command buffer
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_CMD_BUF_H
+#define XCAM_VK_CMD_BUF_H
+
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_descriptor.h>
+#include <vulkan/vk_device.h>
+
+namespace XCam {
+
+class VKCmdBuf
+{
+public:
+ struct GroupSize {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+ GroupSize (uint32_t x_, uint32_t y_, uint32_t z_)
+ : x (x_)
+ , y (y_)
+ , z (z_)
+ {}
+ };
+
+ class DispatchParam {
+ friend class VKCmdBuf;
+ public:
+ DispatchParam (const SmartPtr<VKPipeline> &p, uint32_t x, uint32_t y = 1, uint32_t z = 1);
+ virtual ~DispatchParam ();
+ bool update_push_consts (VKConstRange::VKPushConstArgs & push_consts);
+ protected:
+ virtual XCamReturn fill_cmd_buf (VKCmdBuf &buf);
+ XCAM_DEAD_COPY (DispatchParam);
+
+ protected:
+ GroupSize _group_size;
+ const SmartPtr<VKPipeline> _pipeline;
+ VKConstRange::VKPushConstArgs _push_consts;
+ };
+
+ class Pool
+ : public RefObj
+ {
+ friend class VKCmdBuf;
+ public:
+ ~Pool ();
+ SmartPtr<VKCmdBuf> allocate_buffer ();
+ void free_buffer (VkCommandBuffer buf_id);
+
+ private:
+ explicit Pool (const SmartPtr<VKDevice> dev, VkCommandPool id);
+ XCAM_DEAD_COPY (Pool);
+ private:
+ VkCommandPool _pool_id;
+ SmartPtr<VKDevice> _dev;
+ };
+
+public:
+ static SmartPtr<VKCmdBuf>
+ create_command_buffer (const SmartPtr<VKDevice> dev, const SmartPtr<Pool> pool = NULL);
+ static SmartPtr<Pool> create_pool (const SmartPtr<VKDevice> dev, VkFlags queue_flag);
+ virtual ~VKCmdBuf ();
+
+ VkCommandBuffer get_cmd_buf_id () const {
+ return _cmd_buf_id;
+ }
+
+ XCamReturn record (const SmartPtr<DispatchParam> param);
+
+ // for fill_cmd_buf
+ XCamReturn dispatch (const GroupSize &group);
+
+protected:
+ explicit VKCmdBuf (const SmartPtr<Pool> pool, VkCommandBuffer buf_id);
+
+private:
+ XCAM_DEAD_COPY (VKCmdBuf);
+
+protected:
+ VkCommandBuffer _cmd_buf_id;
+
+ SmartPtr<Pool> _pool;
+};
+
+}
+
+#endif //XCAM_VK_CMD_BUF_H
diff --git a/modules/vulkan/vk_copy_handler.cpp b/modules/vulkan/vk_copy_handler.cpp
new file mode 100644
index 0000000..4a89446
--- /dev/null
+++ b/modules/vulkan/vk_copy_handler.cpp
@@ -0,0 +1,270 @@
+/*
+ * vk_copy_handler.cpp - vulkan copy handler
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include <vulkan/vulkan_std.h>
+#include "vk_copy_handler.h"
+#include "vk_video_buf_allocator.h"
+#include "vk_shader.h"
+#include "vk_memory.h"
+#include "vk_worker.h"
+#include "vk_device.h"
+
+#define COPY_SHADER_BINDING_COUNT 2
+#define INVALID_INDEX (uint32_t)(-1)
+
+namespace XCam {
+
+namespace {
+
+DECLARE_WORK_CALLBACK (CbCopyShader, VKCopyHandler, copy_done);
+
+class CopyArgs
+ : public VKWorker::VKArguments
+{
+public:
+ explicit CopyArgs (const SmartPtr<ImageHandler::Parameters> &param)
+ : _param (param)
+ {
+ XCAM_ASSERT (param.ptr ());
+ }
+ const SmartPtr<ImageHandler::Parameters> &get_param () const {
+ return _param;
+ }
+
+private:
+ SmartPtr<ImageHandler::Parameters> _param;
+};
+
+class VKCopyPushConst
+ : public VKConstRange::VKPushConstArg
+{
+public:
+ VKCopyPushConst (const VKCopyHandler::PushConstsProp &prop)
+ : _prop (prop)
+ {}
+
+ bool get_const_data (VkPushConstantRange &range, void *& ptr) {
+ range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+ range.offset = 0;
+ range.size = sizeof (_prop);
+ ptr = &_prop;
+ return true;
+ }
+
+private:
+ VKCopyHandler::PushConstsProp _prop;
+};
+
+};
+
+static const VKShaderInfo copy_shader_info (
+ "main",
+std::vector<uint32_t> {
+#include "shader_copy.comp.spv"
+});
+
+#if 0
+VKCopyArguments::VKCopyArguments (const SmartPtr<VKBuffer> in, SmartPtr<VKBuffer> out)
+ : _in_buf (in)
+ , _out_buf (out)
+{
+ XCAM_ASSERT (in.ptr());
+ XCAM_ASSERT (out.ptr());
+}
+
+XCamReturn
+VKCopyArguments::prepare_bindings (VKDescriptor::SetBindInfoArray &binding_array)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, _in_buf.ptr () && _out_buf.ptr (), XCAM_RETURN_ERROR_PARAM,
+ "VKCopyArguments input or output buffer is empty.");
+
+ binding_array.resize (2);
+ binding_array[0].layout = new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0);
+ binding_array[0].desc = VKBufDesc (_in_buf);
+
+ binding_array[0].layout = new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
+ binding_array[0].desc = VKBufDesc (_out_buf);
+ return XCAM_RETURN_NO_ERROR;
+}
+#endif
+
+VKCopyHandler::PushConstsProp::PushConstsProp ()
+ : in_img_width (0)
+ , in_x_offset (0)
+ , out_img_width (0)
+ , out_x_offset (0)
+ , copy_width (0)
+{
+}
+
+VKCopyHandler::VKCopyHandler (const SmartPtr<VKDevice> &dev, const char* name)
+ : VKHandler (dev, name)
+ , _index (INVALID_INDEX)
+{
+}
+
+bool
+VKCopyHandler::set_copy_area (uint32_t idx, const Rect &in_area, const Rect &out_area)
+{
+ XCAM_FAIL_RETURN (
+ ERROR,
+ idx != INVALID_INDEX &&
+ in_area.width && in_area.height &&
+ in_area.width == out_area.width && in_area.height == out_area.height,
+ false,
+ "VKCopyHandler(%s): set copy area(idx:%d) failed, input size:%dx%d output size:%dx%d",
+ XCAM_STR (get_name ()), idx, in_area.width, in_area.height, out_area.width, out_area.height);
+
+ _index = idx;
+ _in_area = in_area;
+ _out_area = out_area;
+
+ XCAM_LOG_DEBUG ("VKCopyHandler: copy area(idx:%d) input area(%d, %d, %d, %d) output area(%d, %d, %d, %d)",
+ idx,
+ in_area.pos_x, in_area.pos_y, in_area.width, in_area.height,
+ out_area.pos_x, out_area.pos_y, out_area.width, out_area.height);
+
+ return true;
+}
+
+#define UNIT_BYTES (4*sizeof(uint32_t))
+
+XCamReturn
+VKCopyHandler::configure_resource (const SmartPtr<ImageHandler::Parameters> &param)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ XCAM_ASSERT (param.ptr ());
+ XCAM_ASSERT (!_worker.ptr ());
+
+ XCAM_FAIL_RETURN (
+ ERROR, param->in_buf.ptr (), XCAM_RETURN_ERROR_VULKAN,
+ "VKCopyHandler(%s) param.in_buf is empty.", XCAM_STR (get_name ()));
+ XCAM_FAIL_RETURN (
+ ERROR, _index != INVALID_INDEX, XCAM_RETURN_ERROR_PARAM,
+ "VKCopyHandler(%s) invalid copy area, need set copy area first", XCAM_STR (get_name ()));
+
+ VideoBufferInfo in_info = param->in_buf->get_video_info ();
+ VideoBufferInfo out_info;
+ if (param->out_buf.ptr ())
+ out_info = param->out_buf->get_video_info ();
+ else
+ out_info = get_out_video_info ();
+ XCAM_FAIL_RETURN (
+ ERROR, out_info.is_valid (), XCAM_RETURN_ERROR_PARAM,
+ "VKCopyHandler(%s) invalid out info.", XCAM_STR (get_name ()));
+
+ _image_prop.in_img_width = in_info.aligned_width / UNIT_BYTES;
+ _image_prop.in_x_offset = _in_area.pos_x / UNIT_BYTES;
+ _image_prop.out_img_width = out_info.aligned_width / UNIT_BYTES;
+ _image_prop.out_x_offset = _out_area.pos_x / UNIT_BYTES;
+ _image_prop.copy_width = _in_area.width / UNIT_BYTES;
+ WorkSize global_size (
+ XCAM_ALIGN_UP (_image_prop.copy_width, 8 ) / 8,
+ XCAM_ALIGN_UP (_in_area.height * 3 / 2, 8 ) / 8);
+
+ _binding_layout.clear ();
+ for (int i = 0; i < COPY_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ _binding_layout.push_back (binding);
+ }
+
+ if (!_worker.ptr ()) {
+ _worker = new VKWorker(get_vk_device(), "CbCopyShader", new CbCopyShader (this));
+ XCAM_ASSERT (_worker.ptr());
+
+ _worker->set_global_size (global_size);
+
+ VKConstRange::VKPushConstArgs push_consts;
+ push_consts.push_back (new VKCopyPushConst (_image_prop));
+ ret = _worker->build (copy_shader_info, _binding_layout, push_consts);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_VULKAN,
+ "VKCopyHandler(%s) build copy shader failed.", XCAM_STR (get_name ()));
+ }
+
+ return ret;
+}
+
+XCamReturn
+VKCopyHandler::start_work (const SmartPtr<ImageHandler::Parameters> &param)
+{
+ XCAM_ASSERT (_binding_layout.size () == COPY_SHADER_BINDING_COUNT);
+ SmartPtr<VKVideoBuffer> in_vk = param->in_buf.dynamic_cast_ptr<VKVideoBuffer> ();
+ SmartPtr<VKVideoBuffer> out_vk = param->out_buf.dynamic_cast_ptr<VKVideoBuffer> ();
+
+ XCAM_FAIL_RETURN (
+ ERROR, in_vk.ptr () && out_vk.ptr(), XCAM_RETURN_ERROR_VULKAN,
+ "VKCopyHandler(%s) param.in_buf or param.out_buf is not vk buf.", XCAM_STR (get_name ()));
+
+ VKDescriptor::SetBindInfoArray bindings (_binding_layout.size ());
+ bindings[0].layout = _binding_layout[0];
+ bindings[0].desc = VKBufDesc (in_vk->get_vk_buf ());
+ bindings[1].layout = _binding_layout[1];
+ bindings[1].desc = VKBufDesc (out_vk->get_vk_buf ());
+
+ SmartPtr<CopyArgs> args = new CopyArgs (param);
+ args->set_bindings (bindings);
+ args->add_push_const (new VKCopyPushConst (_image_prop));
+ return _worker->work (args);
+}
+
+void
+VKCopyHandler::copy_done (
+ const SmartPtr<Worker> &worker,
+ const SmartPtr<Worker::Arguments> &base,
+ const XCamReturn error)
+{
+ if (!xcam_ret_is_ok (error)) {
+ XCAM_LOG_ERROR ("VKCopyHandler(%s) copy failed.", XCAM_STR (get_name ()));
+ }
+
+ SmartPtr<VKWorker> vk_worker = worker.dynamic_cast_ptr<VKWorker> ();
+ XCAM_ASSERT (vk_worker.ptr ());
+ vk_worker->wait_fence ();
+
+ SmartPtr<CopyArgs> args = base.dynamic_cast_ptr<CopyArgs> ();
+ XCAM_ASSERT (args.ptr ());
+ const SmartPtr<ImageHandler::Parameters> param = args->get_param ();
+ XCAM_ASSERT (param.ptr ());
+
+ execute_done (param, error);
+}
+
+XCamReturn
+VKCopyHandler::copy (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf)
+{
+ SmartPtr<ImageHandler::Parameters> param = new ImageHandler::Parameters (in_buf, out_buf);
+ XCAM_ASSERT (param.ptr ());
+
+ XCamReturn ret = execute_buffer (param, false);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "VKCopyHandler(%s) copy failed", XCAM_STR (get_name ()));
+
+ if (!out_buf.ptr ()) {
+ out_buf = param->out_buf;
+ }
+
+ return ret;
+}
+
+};
diff --git a/modules/vulkan/vk_copy_handler.h b/modules/vulkan/vk_copy_handler.h
new file mode 100644
index 0000000..8c71bae
--- /dev/null
+++ b/modules/vulkan/vk_copy_handler.h
@@ -0,0 +1,90 @@
+/*
+ * vk_copy_handler.h - vulkan copy handler
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_COPY_HANDLER_H
+#define XCAM_VK_COPY_HANDLER_H
+
+#include <xcam_utils.h>
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_worker.h>
+#include <vulkan/vk_handler.h>
+#include <vulkan/vk_descriptor.h>
+
+namespace XCam {
+
+#if 0
+class VKCopyArguments
+ : public VKWorker::VKArguments
+{
+public:
+ explicit VKCopyArguments (const SmartPtr<VKBuffer> in, SmartPtr<VKBuffer> out);
+
+private:
+ virtual XCamReturn prepare_bindings (VKDescriptor::SetBindInfoArray &binding_array);
+private:
+ SmartPtr<VKBuffer> _in_buf;
+ SmartPtr<VKBuffer> _out_buf;
+};
+#endif
+
+class VKCopyHandler
+ : public VKHandler
+{
+public:
+ struct PushConstsProp {
+ uint in_img_width;
+ uint in_x_offset;
+ uint out_img_width;
+ uint out_x_offset;
+ uint copy_width;
+
+ PushConstsProp ();
+ };
+
+public:
+ explicit VKCopyHandler (const SmartPtr<VKDevice> &dev, const char* name = "vk-copy-handler");
+
+ bool set_copy_area (uint32_t idx, const Rect &in_area, const Rect &out_area);
+ uint32_t get_index () {
+ return _index;
+ }
+
+ XCamReturn copy (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf);
+ void copy_done (
+ const SmartPtr<Worker> &worker,
+ const SmartPtr<Worker::Arguments> &base,
+ const XCamReturn error);
+
+private:
+ virtual XCamReturn configure_resource (const SmartPtr<Parameters> &param);
+ virtual XCamReturn start_work (const SmartPtr<Parameters> &param);
+
+private:
+ SmartPtr<VKWorker> _worker;
+ PushConstsProp _image_prop;
+ VKDescriptor::BindingArray _binding_layout;
+
+ uint32_t _index;
+ Rect _in_area;
+ Rect _out_area;
+};
+
+}
+#endif //XCAM_VK_COPY_HANDLER_H
diff --git a/modules/vulkan/vk_descriptor.cpp b/modules/vulkan/vk_descriptor.cpp
new file mode 100644
index 0000000..888d3d6
--- /dev/null
+++ b/modules/vulkan/vk_descriptor.cpp
@@ -0,0 +1,220 @@
+/*
+ * vk_descriptor.cpp - Vulkan descriptor
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_descriptor.h"
+#include "vk_device.h"
+
+namespace XCam {
+
+namespace VKDescriptor {
+
+SetLayoutBinding::SetLayoutBinding (
+ VkDescriptorType type, VkShaderStageFlags stage, uint32_t idx, uint32_t count)
+{
+ xcam_mem_clear (_binding);
+ _binding.binding = idx;
+ _binding.descriptorType = type;
+ _binding.descriptorCount = count;
+ _binding.stageFlags = stage;
+ _binding.pImmutableSamplers = NULL;
+}
+
+SetLayoutBinding::~SetLayoutBinding ()
+{
+}
+
+VkBindingArray
+get_vk_layoutbindings (const BindingArray &array)
+{
+ VkBindingArray ret;
+ ret.reserve (array.size ());
+ for (size_t i = 0; i < array.size (); ++i) {
+ ret.push_back(array[i]->get_vk_binding ());
+ }
+ return ret;
+}
+
+Pool::Pool (const SmartPtr<VKDevice> dev)
+ : _pool_id (VK_NULL_HANDLE)
+ , _set_size (0)
+ , _dev (dev)
+{}
+
+Pool::~Pool ()
+{
+ if (XCAM_IS_VALID_VK_ID (_pool_id)) {
+ _dev->destroy_desc_pool (_pool_id);
+ }
+}
+
+void
+Pool::add_binding (const SmartPtr<SetLayoutBinding> &bind)
+{
+ VkDescriptorSetLayoutBinding vk_binding = bind->get_vk_binding ();
+ Pool::TypeTable::iterator i = _types.find (vk_binding.descriptorType);
+ if (i == _types.end ())
+ _types.insert (i, Pool::TypeTable::value_type (vk_binding.descriptorType, vk_binding.descriptorCount));
+ else
+ i->second += vk_binding.descriptorCount;
+}
+
+bool
+Pool::add_set_bindings (const BindingArray &binds)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, !XCAM_IS_VALID_VK_ID (_pool_id), false,
+ "vk desriptor pool was inited, cannot add new binding.");
+
+ for (BindingArray::const_iterator i = binds.begin (); i != binds.end (); ++i) {
+ add_binding (*i);
+ }
+ ++_set_size;
+
+ return true;
+}
+
+XCamReturn
+Pool::create ()
+{
+ XCAM_FAIL_RETURN (
+ ERROR, !_types.empty (), XCAM_RETURN_ERROR_PARAM,
+ "vk desriptor pool cannot create since no types added.");
+
+ XCAM_FAIL_RETURN (
+ ERROR, _dev.ptr (), XCAM_RETURN_ERROR_PARAM,
+ "vk desriptor pool cannot create, device is null");
+
+ std::vector<VkDescriptorPoolSize> pool_sizes;
+ pool_sizes.reserve (_types.size ());
+ for (Pool::TypeTable::iterator i = _types.begin (); i != _types.end(); ++i) {
+ VkDescriptorPoolSize new_size = {};
+ new_size.type = i->first;
+ new_size.descriptorCount = i->second;
+ pool_sizes.push_back (new_size);
+ }
+
+ XCAM_ASSERT (_set_size);
+ VkDescriptorPoolCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ create_info.maxSets = _set_size;
+ create_info.poolSizeCount = pool_sizes.size ();
+ create_info.pPoolSizes = pool_sizes.data ();
+
+ _pool_id = _dev->create_desc_pool (create_info);
+
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (_pool_id), XCAM_RETURN_ERROR_VULKAN,
+ "vk desriptor pool create pool_id failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+SmartPtr<Set>
+Pool::allocate_set (const SetBindInfoArray &bind_array, VkDescriptorSetLayout layout)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (_pool_id), NULL,
+ "vk desriptor pool allocate set failed, pool was not ready");
+
+#if 0
+ XCAM_FAIL_RETURN (
+ ERROR, bind_array.size () == bufs.size (), NULL,
+ "vk desriptor pool allocate set failed, bindings and bufs sizes are not matched");
+#endif
+
+ XCAM_FAIL_RETURN (
+ ERROR, _set_size > 0, NULL,
+ "vk desriptor pool allocate set failed, bindings and bufs sizes are not matched");
+
+ //TODO remove binds types from _types
+
+ VkDescriptorSetAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ alloc_info.descriptorPool = _pool_id;
+ alloc_info.pSetLayouts = &layout;
+ alloc_info.descriptorSetCount = 1;
+
+ VkDescriptorSet desc_set_id = _dev->allocate_desc_set (alloc_info);
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (desc_set_id) > 0, NULL,
+ "vk desriptor pool allocate set failed");
+ SmartPtr<Set> new_set = new Set (desc_set_id, this);
+
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (new_set->update_set (bind_array)), NULL,
+ "vk descriptor pool update set failed");
+
+ --_set_size;
+ return new_set;
+}
+
+void
+Pool::destroy_desc_set (VkDescriptorSet set_id)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_pool_id));
+ if (xcam_ret_is_ok (_dev->free_desc_set (set_id, _pool_id)))
+ ++_set_size;
+}
+
+Set::Set (VkDescriptorSet set_id, const SmartPtr<Pool> pool)
+ : _set_id (set_id)
+ , _pool (pool)
+{
+}
+
+Set::~Set ()
+{
+ if (XCAM_IS_VALID_VK_ID (_set_id)) {
+ _pool->destroy_desc_set (_set_id);
+ }
+}
+
+XCamReturn
+Set::update_set (const SetBindInfoArray &bind_array)
+{
+ std::vector<VkWriteDescriptorSet> write_desc_info (bind_array.size ());
+ for (uint32_t i = 0; i < bind_array.size (); ++i) {
+ const SetBindInfo &bind_info = bind_array[i];
+ SmartPtr<SetLayoutBinding> bind = bind_info.layout;
+ XCAM_ASSERT (bind.ptr () && bind_info.desc.buf.ptr ());
+
+ VkWriteDescriptorSet &info = write_desc_info[i];
+ xcam_mem_clear (info);
+ info.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ info.dstSet = _set_id;
+ info.dstBinding = bind->get_index ();
+ info.descriptorCount = 1;
+ info.descriptorType = bind->get_desc_type();
+ info.pBufferInfo = &bind_info.desc.desc_info;
+ }
+ SmartPtr<VKDevice> dev = _pool->get_device ();
+ XCAM_ASSERT (dev.ptr ());
+ XCamReturn ret = dev->update_desc_set (write_desc_info);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk descriptor pool update set failed");
+
+ _bind_array = bind_array;
+ return ret;
+}
+
+}
+
+}
diff --git a/modules/vulkan/vk_descriptor.h b/modules/vulkan/vk_descriptor.h
new file mode 100644
index 0000000..63eff6a
--- /dev/null
+++ b/modules/vulkan/vk_descriptor.h
@@ -0,0 +1,163 @@
+/*
+ * vk_descriptor.h - Vulkan descriptor
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_DESCRIPTOR_H
+#define XCAM_VK_DESCRIPTOR_H
+
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_memory.h>
+#include <map>
+
+namespace XCam {
+
+class VKDevice;
+
+namespace VKDescriptor {
+
+class SetLayoutBinding
+{
+public:
+ virtual ~SetLayoutBinding ();
+ const VkDescriptorSetLayoutBinding &get_vk_binding () const {
+ return _binding;
+ }
+ VkDescriptorType get_desc_type () const {
+ return _binding.descriptorType;
+ }
+ uint32_t get_index () const {
+ return _binding.binding;
+ }
+
+protected:
+ explicit SetLayoutBinding (
+ VkDescriptorType type, VkShaderStageFlags stage, uint32_t idx, uint32_t count);
+
+private:
+ XCAM_DEAD_COPY (SetLayoutBinding);
+protected:
+ VkDescriptorSetLayoutBinding _binding;
+};
+
+template <VkShaderStageFlags stage>
+class LayoutBinding
+ : public SetLayoutBinding
+{
+public:
+ explicit LayoutBinding (VkDescriptorType type, uint32_t idx)
+ : SetLayoutBinding (type, stage, idx, 1)
+ {}
+};
+
+typedef LayoutBinding<VK_SHADER_STAGE_COMPUTE_BIT> ComputeLayoutBinding;
+typedef LayoutBinding<VK_SHADER_STAGE_VERTEX_BIT> VetexLayoutBinding;
+typedef LayoutBinding<VK_SHADER_STAGE_FRAGMENT_BIT> FragmentLayoutBinding;
+
+typedef std::vector<SmartPtr<SetLayoutBinding>> BindingArray;
+
+typedef std::vector<VkDescriptorSetLayoutBinding> VkBindingArray;
+
+VkBindingArray get_vk_layoutbindings (const BindingArray &array);
+
+struct SetBindInfo {
+ SmartPtr<SetLayoutBinding> layout;
+ VKBufDesc desc;
+};
+
+typedef std::vector<SetBindInfo> SetBindInfoArray;
+
+class Pool;
+class Set {
+public:
+ explicit Set (VkDescriptorSet set_id, const SmartPtr<Pool> pool);
+ ~Set ();
+ XCamReturn update_set (const SetBindInfoArray &bind_array);
+ VkDescriptorSet get_set_id () const {
+ return _set_id;
+ }
+
+private:
+ XCAM_DEAD_COPY (Set);
+
+ VkDescriptorSet _set_id;
+ SetBindInfoArray _bind_array;
+ SmartPtr<Pool> _pool;
+};
+
+class Pool
+ : public RefObj
+{
+ friend class Set;
+public:
+ explicit Pool (const SmartPtr<VKDevice> dev);
+ ~Pool ();
+ bool add_set_bindings (const BindingArray &binds);
+ XCamReturn create ();
+ const SmartPtr<VKDevice> &get_device() const {
+ return _dev;
+ }
+
+ SmartPtr<Set> allocate_set (
+ const SetBindInfoArray &bind_array, VkDescriptorSetLayout layout);
+
+private:
+ XCAM_DEAD_COPY (Pool);
+ void add_binding (const SmartPtr<SetLayoutBinding> &bind);
+ void destroy_desc_set (VkDescriptorSet set_id);
+
+private:
+ typedef std::map<VkDescriptorType, uint32_t> TypeTable;
+
+ VkDescriptorPool _pool_id;
+ uint32_t _set_size;
+ TypeTable _types;
+ const SmartPtr<VKDevice> _dev;
+};
+
+}
+
+namespace VKConstRange {
+
+class VKPushConstArg {
+public:
+ virtual ~VKPushConstArg () {}
+ virtual bool get_const_data (VkPushConstantRange &range, void *& ptr) = 0;
+};
+
+typedef std::vector<SmartPtr<VKPushConstArg>> VKPushConstArgs;
+
+typedef std::vector<VkPushConstantRange> VKConstantArray;
+
+template <VkShaderStageFlags stage>
+VkPushConstantRange
+get_constants (uint32_t size, uint32_t offset)
+{
+ VkPushConstantRange range = {};
+ range.stageFlags = stage;
+ range.offset = offset;
+ range.size = size;
+ return range;
+}
+
+#define get_compute_consts get_constants<VK_SHADER_STAGE_COMPUTE_BIT>
+}
+
+}
+
+#endif //XCAM_VK_DESCRIPTOR_H
diff --git a/modules/vulkan/vk_device.cpp b/modules/vulkan/vk_device.cpp
new file mode 100644
index 0000000..bf5e68e
--- /dev/null
+++ b/modules/vulkan/vk_device.cpp
@@ -0,0 +1,471 @@
+/*
+ * vk_device.cpp - vulkan device
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vulkan_common.h"
+#include "vk_device.h"
+#include "vk_shader.h"
+#include "vk_instance.h"
+#include "vk_sync.h"
+#include "vk_cmdbuf.h"
+#include "file_handle.h"
+
+namespace XCam {
+
+SmartPtr<VKDevice> VKDevice::_default_dev;
+Mutex VKDevice::_default_mutex;
+
+VKDevice::~VKDevice ()
+{
+ if (_dev_id)
+ vkDestroyDevice (_dev_id, _allocator.ptr ());
+}
+
+VKDevice::VKDevice (VkDevice id, const SmartPtr<VKInstance> &instance)
+ : _dev_id (id)
+ , _instance (instance)
+{
+ XCAM_ASSERT (instance.ptr ());
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id));
+ _allocator = instance->get_allocator ();
+}
+
+SmartPtr<VKDevice>
+VKDevice::default_device ()
+{
+ SmartLock lock (_default_mutex);
+ if (!_default_dev.ptr()) {
+ _default_dev = create_device ();
+ }
+ XCAM_FAIL_RETURN (
+ ERROR, _default_dev.ptr (), NULL,
+ "VKDevice prepare default device failed.");
+ return _default_dev;
+}
+
+SmartPtr<VKDevice>
+VKDevice::create_device ()
+{
+ SmartPtr<VKInstance> instance = VKInstance::get_instance ();
+ XCAM_FAIL_RETURN (
+ ERROR, instance.ptr (), NULL,
+ "vk create device failed");
+
+ VkPhysicalDevice phy_dev = instance->get_physical_dev ();
+ uint32_t compute_idx = instance->get_compute_queue_family_idx ();
+ SmartPtr<VkAllocationCallbacks> allocator = instance->get_allocator ();
+
+ float priority = 1.0f; //TODO, queue priority change?
+ VkDeviceQueueCreateInfo dev_queue_info = {};
+ dev_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ dev_queue_info.queueFamilyIndex = compute_idx; // default use compute idx
+ dev_queue_info.queueCount = 1;
+ dev_queue_info.pQueuePriorities = &priority;
+
+ VkDeviceCreateInfo dev_create_info = {};
+ dev_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ //TODO, add graphics queue info
+ dev_create_info.queueCreateInfoCount = 1;
+ dev_create_info.pQueueCreateInfos = &dev_queue_info;
+
+ VkDevice dev_id = 0;
+ XCAM_VK_CHECK_RETURN (
+ ERROR,
+ vkCreateDevice (phy_dev, &dev_create_info, allocator.ptr (), &dev_id),
+ NULL, "create vk device failed");
+
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (dev_id));
+ SmartPtr<VKDevice> device = new VKDevice (dev_id, instance);
+ XCAM_ASSERT (device.ptr ());
+
+ XCamReturn ret = device->prepare_compute_queue ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), NULL,
+ "VKDevice prepare compute queue failed.");
+
+ return device;
+}
+
+XCamReturn
+VKDevice::prepare_compute_queue ()
+{
+ uint32_t compute_idx = _instance->get_compute_queue_family_idx ();
+ vkGetDeviceQueue (_dev_id, compute_idx, 0, &_compute_queue);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+SmartPtr<VKShader>
+VKDevice::create_shader (const char *file_name)
+{
+ FileHandle file (file_name, "rb");
+ XCAM_FAIL_RETURN (
+ ERROR, file.is_valid (), NULL,
+ "VKDevice load shader failed when opend shader file:%s.",
+ XCAM_STR (file_name));
+
+ size_t file_size;
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (file.get_file_size (file_size)) || file_size == 0, NULL,
+ "VKDevice load shader failed when read shader file:%s.",
+ XCAM_STR (file_name));
+ std::vector<uint32_t> content (XCAM_ALIGN_UP (file_size, 4) / 4, 0);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (file.read_file ((void *)content.data (), file_size)), NULL,
+ "VKDevice load shader failed when read shader file:%s.",
+ XCAM_STR (file_name));
+ file.close ();
+
+ SmartPtr<VKShader> shader = create_shader (content);
+ if (shader.ptr ())
+ shader->set_name (file_name);
+ return shader;
+}
+
+SmartPtr<VKShader>
+VKDevice::create_shader (const std::vector<uint32_t> &binary)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (_dev_id), NULL,
+ "VKDevice load shader failed with error of null device ready.");
+ XCAM_FAIL_RETURN (
+ ERROR, binary.size () > 5, NULL,
+ "VKDevice load shader failed since binary is corrupt.");
+
+ VkShaderModule shader_id;
+ VkShaderModuleCreateInfo module_create_info = {};
+ module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ module_create_info.pNext = NULL;
+ module_create_info.codeSize = binary.size() * sizeof (binary[0]);
+ module_create_info.pCode = binary.data();
+ module_create_info.flags = 0;
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkCreateShaderModule (_dev_id, &module_create_info, NULL, &shader_id),
+ NULL, "VKDevice create shader module failed.");
+
+ XCAM_IS_VALID_VK_ID (shader_id);
+ return new VKShader (this, shader_id);
+}
+
+void
+VKDevice::destroy_shader_id (VkShaderModule shader)
+{
+ if (XCAM_IS_VALID_VK_ID(_dev_id) && XCAM_IS_VALID_VK_ID (shader))
+ vkDestroyShaderModule (_dev_id, shader, _allocator.ptr());
+}
+
+VkDeviceMemory
+VKDevice::allocate_mem_id (VkDeviceSize size, VkMemoryPropertyFlags memory_prop)
+{
+ VkDeviceMemory mem_id;
+ VkMemoryAllocateInfo mem_alloc_info = {};
+ mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ mem_alloc_info.allocationSize = size;
+ mem_alloc_info.memoryTypeIndex = _instance->get_mem_type_index (memory_prop);
+
+ XCAM_FAIL_RETURN (
+ ERROR, mem_alloc_info.memoryTypeIndex != (uint32_t)(-1), VK_NULL_HANDLE,
+ "VKDevice create mem id failed, can NOT find memory type:0x%08x.", (uint32_t)memory_prop);
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkAllocateMemory (_dev_id, &mem_alloc_info, _allocator.ptr (), &mem_id),
+ VK_NULL_HANDLE, "create vk buffer failed in allocating memory");
+ return mem_id;
+}
+
+void
+VKDevice::free_mem_id (VkDeviceMemory mem)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (mem));
+
+ vkFreeMemory (_dev_id, mem, _allocator.ptr ());
+}
+
+XCamReturn
+VKDevice::map_mem (VkDeviceMemory mem, VkDeviceSize size, VkDeviceSize offset, void *&ptr)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (mem));
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkMapMemory (_dev_id, mem, offset, size, 0, &ptr), XCAM_RETURN_ERROR_VULKAN,
+ "vk device map mem failed. size:%lld", size);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+void
+VKDevice::unmap_mem (VkDeviceMemory mem)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (mem));
+ vkUnmapMemory (_dev_id, mem);
+}
+
+VkBuffer
+VKDevice::create_buf_id (VkBufferUsageFlags usage, uint32_t size)
+{
+ VkBufferCreateInfo buf_create_info = {};
+ buf_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buf_create_info.size = size;
+ buf_create_info.usage = usage;
+ buf_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+ VkBuffer buf_id;
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkCreateBuffer (_dev_id, &buf_create_info, _allocator.ptr (), &buf_id),
+ VK_NULL_HANDLE, "create vk buffer failed");
+
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf_id));
+ return buf_id;
+}
+
+void
+VKDevice::destroy_buf_id (VkBuffer buf)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf));
+
+ vkDestroyBuffer (_dev_id, buf, _allocator.ptr ());
+}
+
+XCamReturn
+VKDevice::bind_buffer (VkBuffer buf, VkDeviceMemory mem, VkDeviceSize offset)
+{
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkBindBufferMemory (_dev_id, buf, mem, offset),
+ XCAM_RETURN_ERROR_VULKAN, "vkdevice bind buffer to mem failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+VkDescriptorPool
+VKDevice::create_desc_pool (const VkDescriptorPoolCreateInfo &info)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+
+ VkDescriptorPool pool_id;
+ XCAM_VK_CHECK_RETURN (
+ ERROR,
+ vkCreateDescriptorPool (_dev_id, &info, _allocator.ptr (), &pool_id),
+ VK_NULL_HANDLE,
+ "vkdevice create desriptor pool failed");
+ return pool_id;
+}
+
+void
+VKDevice::destroy_desc_pool (VkDescriptorPool pool)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool));
+ vkDestroyDescriptorPool (_dev_id, pool, _allocator.ptr ());
+}
+
+VkDescriptorSet
+VKDevice::allocate_desc_set (const VkDescriptorSetAllocateInfo &info)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+
+ VkDescriptorSet set_id;
+ XCAM_VK_CHECK_RETURN (
+ ERROR,
+ vkAllocateDescriptorSets (_dev_id, &info, &set_id),
+ VK_NULL_HANDLE,
+ "vkdevice create desriptor set failed");
+ return set_id;
+
+}
+
+XCamReturn
+VKDevice::free_desc_set (VkDescriptorSet set, VkDescriptorPool pool)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (set));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool));
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR,
+ vkFreeDescriptorSets (_dev_id, pool, 1, &set),
+ XCAM_RETURN_ERROR_VULKAN,
+ "vkdevice free desriptor set from pool failed");
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKDevice::update_desc_set (const std::vector<VkWriteDescriptorSet> &sets)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ vkUpdateDescriptorSets (_dev_id, sets.size (), sets.data (), 0, NULL);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+VkCommandPool
+VKDevice::create_cmd_pool (VkFlags queue_flag)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (_instance.ptr ());
+ VkCommandPool pool_id = VK_NULL_HANDLE;
+
+ VkCommandPoolCreateInfo create_pool_info = {};
+ create_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ create_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+
+ if (queue_flag == VK_QUEUE_COMPUTE_BIT)
+ create_pool_info.queueFamilyIndex = _instance->get_compute_queue_family_idx ();
+ else if (queue_flag == VK_QUEUE_GRAPHICS_BIT)
+ create_pool_info.queueFamilyIndex = _instance->get_graphics_queue_family_idx ();
+ else {
+ XCAM_LOG_WARNING ("VKDevice create command pool failed, queue_flag(%d) not supported.", queue_flag);
+ return VK_NULL_HANDLE;
+ }
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkCreateCommandPool (_dev_id, &create_pool_info, _allocator.ptr (), &pool_id),
+ VK_NULL_HANDLE, "VKDevice create command pool failed.");
+ return pool_id;
+}
+
+void
+VKDevice::destroy_cmd_pool (VkCommandPool pool)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool));
+ vkDestroyCommandPool (_dev_id, pool, _allocator.ptr ());
+}
+
+VkCommandBuffer
+VKDevice::allocate_cmd_buffer (VkCommandPool pool)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool));
+
+ VkCommandBufferAllocateInfo allocate_info = {};
+ allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocate_info.commandPool = pool;
+ allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ allocate_info.commandBufferCount = 1;
+
+ VkCommandBuffer buf_id = VK_NULL_HANDLE;
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkAllocateCommandBuffers (_dev_id, &allocate_info, &buf_id),
+ VK_NULL_HANDLE, "VKDevice create command buffers failed.");
+ return buf_id;
+}
+
+void
+VKDevice::free_cmd_buffer (VkCommandPool pool, VkCommandBuffer buf)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf));
+
+ vkFreeCommandBuffers (_dev_id, pool, 1, &buf);
+}
+
+SmartPtr<VKFence>
+VKDevice::create_fence (VkFenceCreateFlags flags)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+
+ VkFenceCreateInfo fence_info = {};
+ fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_info.flags = flags;
+
+ VkFence fence_id = VK_NULL_HANDLE;
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkCreateFence (_dev_id, &fence_info, _allocator.ptr (), &fence_id),
+ NULL, "VKDevice create fence failed.");
+ return new VKFence (this, fence_id);
+}
+
+void
+VKDevice::destroy_fence (VkFence fence)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (fence));
+
+ vkDestroyFence (_dev_id, fence, _allocator.ptr ());
+}
+
+XCamReturn
+VKDevice::reset_fence (VkFence fence)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (fence));
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkResetFences (_dev_id, 1, &fence),
+ XCAM_RETURN_ERROR_VULKAN, "VKDevice reset fence failed.");
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKDevice::wait_for_fence (VkFence fence, uint64_t timeout)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (fence));
+
+ VkResult ret = vkWaitForFences (_dev_id, 1, &fence, VK_TRUE, timeout);
+ if (ret == VK_TIMEOUT) {
+ XCAM_LOG_DEBUG ("VKDevice wait for fence timeout");
+ return XCAM_RETURN_ERROR_TIMEOUT;
+ }
+
+ XCAM_FAIL_RETURN (
+ ERROR, ret == VK_SUCCESS,
+ XCAM_RETURN_ERROR_VULKAN, "VKDevice wait for fence failed.");
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKDevice::compute_queue_submit (const SmartPtr<VKCmdBuf> cmd_buf, const SmartPtr<VKFence> fence)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, cmd_buf.ptr (),
+ XCAM_RETURN_ERROR_PARAM, "VKDevice compute queue submit failed, cmd_buf is empty.");
+
+ VkCommandBuffer buf_id = cmd_buf->get_cmd_buf_id ();
+ VkSubmitInfo submit_info = {};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = &buf_id;
+
+ VkFence fence_id = VK_NULL_HANDLE;
+ if (fence.ptr ())
+ fence_id = fence->get_fence_id ();
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkQueueSubmit (_compute_queue, 1, &submit_info, fence_id),
+ XCAM_RETURN_ERROR_VULKAN, "VKDevice compute queue submit failed.");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKDevice::compute_queue_wait_idle ()
+{
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (_compute_queue),
+ XCAM_RETURN_ERROR_PARAM, "VKDevice compute queue wait idle failed, queue_id is null");
+
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkQueueWaitIdle (_compute_queue),
+ XCAM_RETURN_ERROR_VULKAN, "VKDevice compute queue wait idle failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+}
diff --git a/modules/vulkan/vk_device.h b/modules/vulkan/vk_device.h
new file mode 100644
index 0000000..27a07a1
--- /dev/null
+++ b/modules/vulkan/vk_device.h
@@ -0,0 +1,120 @@
+/*
+ * vk_device.h - vulkan device
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_DEVICE_H
+#define XCAM_VK_DEVICE_H
+
+#include <vulkan/vulkan_std.h>
+#include <xcam_mutex.h>
+
+namespace XCam {
+
+class VKPipeline;
+class VKShader;
+class VKFence;
+class VKCmdBuf;
+class VKInstance;
+class VKMemory;
+class VKBuffer;
+
+namespace VKDescriptor {
+class Pool;
+class Set;
+};
+
+class VKDevice
+ : public RefObj
+{
+ friend class VKFence;
+ friend class VKShader;
+ friend class VKPipeline;
+ friend class VKCmdBuf;
+ friend class VKDescriptor::Pool;
+ friend class VKDescriptor::Set;
+ friend class VKMemory;
+ friend class VKBuffer;
+public:
+ ~VKDevice ();
+ static SmartPtr<VKDevice> default_device ();
+ static SmartPtr<VKDevice> create_device ();
+
+ VkDevice get_dev_id () const {
+ return _dev_id;
+ }
+ SmartPtr<VkAllocationCallbacks>
+ get_allocation_cb () const {
+ return _allocator;
+ }
+
+ SmartPtr<VKShader> create_shader (const char *file_name);
+ SmartPtr<VKShader> create_shader (const std::vector<uint32_t> &binary);
+ //SmartPtr<VKPipeline> create_pipeline (const SmartPtr<VKShader> shader);
+ SmartPtr<VKFence> create_fence (VkFenceCreateFlags flags = VK_FENCE_CREATE_SIGNALED_BIT);
+ XCamReturn compute_queue_submit (const SmartPtr<VKCmdBuf> cmd_buf, const SmartPtr<VKFence> fence);
+ XCamReturn compute_queue_wait_idle ();
+
+protected:
+ void destroy_shader_id (VkShaderModule shader);
+ VkDeviceMemory allocate_mem_id (VkDeviceSize size, VkMemoryPropertyFlags memory_prop);
+ void free_mem_id (VkDeviceMemory mem);
+ XCamReturn map_mem (VkDeviceMemory mem, VkDeviceSize size, VkDeviceSize offset, void *&ptr);
+ void unmap_mem (VkDeviceMemory mem);
+ VkBuffer create_buf_id (VkBufferUsageFlags usage, uint32_t size);
+ void destroy_buf_id (VkBuffer buf);
+ XCamReturn bind_buffer (VkBuffer buf, VkDeviceMemory mem, VkDeviceSize offset = 0);
+
+ VkDescriptorPool create_desc_pool (const VkDescriptorPoolCreateInfo &info);
+ void destroy_desc_pool (VkDescriptorPool pool);
+
+ VkDescriptorSet allocate_desc_set (const VkDescriptorSetAllocateInfo &info);
+ XCamReturn free_desc_set (VkDescriptorSet set, VkDescriptorPool pool);
+
+ XCamReturn update_desc_set (const std::vector<VkWriteDescriptorSet> &sets);
+ VkCommandPool create_cmd_pool (VkFlags queue_flag = VK_QUEUE_COMPUTE_BIT);
+ void destroy_cmd_pool (VkCommandPool pool);
+
+ VkCommandBuffer allocate_cmd_buffer (VkCommandPool pool);
+ void free_cmd_buffer (VkCommandPool pool, VkCommandBuffer buf);
+
+ void destroy_fence (VkFence fence);
+ XCamReturn reset_fence (VkFence fence);
+ XCamReturn wait_for_fence (VkFence fence, uint64_t timeout);
+
+protected:
+ explicit VKDevice (VkDevice id, const SmartPtr<VKInstance> &instance);
+ XCamReturn prepare_compute_queue ();
+ //SmartPtr<VKLayout> create_desc_set_layout ();
+
+private:
+ XCAM_DEAD_COPY (VKDevice);
+
+private:
+ static SmartPtr<VKDevice> _default_dev;
+ static Mutex _default_mutex;
+
+ VkDevice _dev_id;
+ VkQueue _compute_queue;
+ SmartPtr<VkAllocationCallbacks> _allocator;
+ SmartPtr<VKInstance> _instance;
+};
+
+}
+
+#endif //XCAM_VK_DEVICE_H
diff --git a/modules/vulkan/vk_geomap_handler.cpp b/modules/vulkan/vk_geomap_handler.cpp
new file mode 100644
index 0000000..4b65a44
--- /dev/null
+++ b/modules/vulkan/vk_geomap_handler.cpp
@@ -0,0 +1,314 @@
+/*
+ * vk_geomap_handler.cpp - vulkan geometry map handler implementation
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Yinhang Liu <yinhangx.liu@intel.com>
+ */
+
+#include "vk_geomap_handler.h"
+#include "vk_video_buf_allocator.h"
+#include "vk_device.h"
+
+#define GEOMAP_SHADER_BINDING_COUNT 5
+
+#define XCAM_VK_GEOMAP_ALIGN_X 4
+#define XCAM_VK_GEOMAP_ALIGN_Y 2
+
+namespace XCam {
+
+namespace {
+
+DECLARE_WORK_CALLBACK (CbGeoMapShader, VKGeoMapHandler, geomap_done);
+
+class GeoMapArgs
+ : public VKWorker::VKArguments
+{
+public:
+ explicit GeoMapArgs (const SmartPtr<ImageHandler::Parameters> &param)
+ : _param (param)
+ {
+ XCAM_ASSERT (param.ptr ());
+ }
+ const SmartPtr<ImageHandler::Parameters> &get_param () const {
+ return _param;
+ }
+
+private:
+ SmartPtr<ImageHandler::Parameters> _param;
+};
+
+class VKGeoMapPushConst
+ : public VKConstRange::VKPushConstArg
+{
+public:
+ VKGeoMapPushConst (const VKGeoMapHandler::PushConstsProp &prop)
+ : _prop (prop)
+ {}
+
+ bool get_const_data (VkPushConstantRange &range, void *& ptr) {
+ range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+ range.offset = 0;
+ range.size = sizeof (_prop);
+ ptr = &_prop;
+ return true;
+ }
+
+private:
+ VKGeoMapHandler::PushConstsProp _prop;
+};
+
+static const VKShaderInfo geomap_shader_info (
+ "main",
+std::vector<uint32_t> {
+#include "shader_geomap.comp.spv"
+});
+
+}
+
+VKGeoMapHandler::PushConstsProp::PushConstsProp ()
+ : in_img_width (0)
+ , in_img_height (0)
+ , out_img_width (0)
+ , out_img_height (0)
+ , lut_width (0)
+ , lut_height (0)
+{
+ xcam_mem_clear (lut_step);
+ xcam_mem_clear (lut_std_step);
+}
+
+VKGeoMapHandler::VKGeoMapHandler (const SmartPtr<VKDevice> &dev, const char* name)
+ : VKHandler (dev, name)
+{
+}
+
+bool
+VKGeoMapHandler::set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, data && width && height, false,
+ "VKGeoMapHandler(%s) set look up table failed, data ptr:%p, width:%d, height:%d",
+ XCAM_STR (get_name ()), data, width, height);
+ XCAM_ASSERT (!_lut_buf.ptr ());
+
+ _lut_width = width;
+ _lut_height = height;
+
+ uint32_t lut_size = width * height * 2 * sizeof (float);
+ SmartPtr<VKBuffer> buf = VKBuffer::create_buffer (
+ get_vk_device (), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, lut_size);
+ XCAM_ASSERT (buf.ptr ());
+
+ float *ptr = (float *) buf->map (lut_size, 0);
+ XCAM_FAIL_RETURN (ERROR, ptr, false, "VKGeoMapHandler(%s) map range failed", XCAM_STR (get_name ()));
+ for (uint32_t i = 0; i < height; ++i) {
+ float *ret = &ptr[i * width * 2];
+ const PointFloat2 *line = &data[i * width];
+
+ for (uint32_t j = 0; j < width; ++j) {
+ ret[j * 2] = line[j].x;
+ ret[j * 2 + 1] = line[j].y;
+ }
+ }
+ buf->unmap ();
+ _lut_buf = buf;
+
+ return true;
+}
+
+bool
+VKGeoMapHandler::init_factors ()
+{
+ XCAM_ASSERT (_lut_width && _lut_height);
+
+ float factor_x, factor_y;
+ get_factors (factor_x, factor_y);
+
+ if (!XCAM_DOUBLE_EQUAL_AROUND (factor_x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (factor_y, 0.0f))
+ return true;
+
+ return auto_calculate_factors (_lut_width, _lut_height);
+}
+
+#define UNIT_BYTES (sizeof (uint32_t))
+
+XCamReturn
+VKGeoMapHandler::configure_resource (const SmartPtr<ImageHandler::Parameters> &param)
+{
+ XCAM_ASSERT (param.ptr () && param->in_buf.ptr ());
+ XCAM_FAIL_RETURN (
+ ERROR, _lut_buf.ptr (), XCAM_RETURN_ERROR_PARAM,
+ "VKGeoMapHandler(%s) configure resource failed, look up table is empty", XCAM_STR (get_name ()));
+
+ const VideoBufferInfo &in_info = param->in_buf->get_video_info ();
+ XCAM_FAIL_RETURN (
+ ERROR, in_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM,
+ "VKGeoMapHandler(%s) only support NV12 format, but input format is %s",
+ XCAM_STR (get_name ()), xcam_fourcc_to_string (in_info.format));
+
+ uint32_t out_width, out_height;
+ get_output_size (out_width, out_height);
+ VideoBufferInfo out_info;
+ out_info.init (
+ in_info.format, out_width, out_height,
+ XCAM_ALIGN_UP (out_width, XCAM_VK_GEOMAP_ALIGN_X),
+ XCAM_ALIGN_UP (out_height, XCAM_VK_GEOMAP_ALIGN_Y));
+ set_out_video_info (out_info);
+
+ init_factors ();
+
+ float factor_x, factor_y;
+ get_factors (factor_x, factor_y);
+ XCAM_FAIL_RETURN (
+ ERROR,
+ !XCAM_DOUBLE_EQUAL_AROUND (factor_x, 0.0f) &&
+ !XCAM_DOUBLE_EQUAL_AROUND (factor_y, 0.0f),
+ XCAM_RETURN_ERROR_PARAM,
+ "VKGeoMapHandler(%s) invalid standard factors: x:%f, y:%f",
+ XCAM_STR (get_name ()), factor_x, factor_y);
+
+ _image_prop.in_img_width = in_info.aligned_width / UNIT_BYTES;
+ _image_prop.in_img_height = in_info.aligned_height;
+ _image_prop.out_img_width = out_info.aligned_width / UNIT_BYTES;
+ _image_prop.out_img_height = out_info.aligned_height;
+ _image_prop.lut_width = _lut_width;
+ _image_prop.lut_height = _lut_height;
+ _image_prop.lut_std_step[0] = 1.0f / factor_x;
+ _image_prop.lut_std_step[1] = 1.0f / factor_y;
+
+ WorkSize global_size (
+ XCAM_ALIGN_UP (_image_prop.out_img_width, 8) / 8,
+ XCAM_ALIGN_UP (_image_prop.out_img_height, 16) / 16);
+
+ _binding_layout.clear ();
+ for (int i = 0; i < GEOMAP_SHADER_BINDING_COUNT; ++i) {
+ SmartPtr<VKDescriptor::SetLayoutBinding> binding =
+ new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i);
+ _binding_layout.push_back (binding);
+ }
+
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ if (!_worker.ptr ()) {
+ _worker = new VKWorker (get_vk_device(), "CbGeoMapShader", new CbGeoMapShader (this));
+ XCAM_ASSERT (_worker.ptr ());
+
+ _worker->set_global_size (global_size);
+
+ VKConstRange::VKPushConstArgs push_consts;
+ push_consts.push_back (new VKGeoMapPushConst (_image_prop));
+ ret = _worker->build (geomap_shader_info, _binding_layout, push_consts);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_VULKAN,
+ "VKGeoMapHandler(%s) build geomap shader failed.", XCAM_STR (get_name ()));
+ }
+
+ return ret;
+}
+
+XCamReturn
+VKGeoMapHandler::start_work (const SmartPtr<ImageHandler::Parameters> &param)
+{
+ XCAM_ASSERT (_lut_buf.ptr ());
+ XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->out_buf.ptr ());
+ XCAM_ASSERT (_binding_layout.size () == GEOMAP_SHADER_BINDING_COUNT);
+
+ SmartPtr<VKVideoBuffer> in_vk = param->in_buf.dynamic_cast_ptr<VKVideoBuffer> ();
+ SmartPtr<VKVideoBuffer> out_vk = param->out_buf.dynamic_cast_ptr<VKVideoBuffer> ();
+ XCAM_FAIL_RETURN (
+ ERROR, in_vk.ptr () && out_vk.ptr(), XCAM_RETURN_ERROR_VULKAN,
+ "VKGeoMapHandler(%s) param.in_buf or param.out_buf is not vk buffer", XCAM_STR (get_name ()));
+
+ VKDescriptor::SetBindInfoArray bindings (_binding_layout.size ());
+ bindings[0].layout = _binding_layout[0];
+ bindings[0].desc = VKBufDesc (in_vk->get_vk_buf (), NV12PlaneYIdx);
+ bindings[1].layout = _binding_layout[1];
+ bindings[1].desc = VKBufDesc (in_vk->get_vk_buf (), NV12PlaneUVIdx);
+ bindings[2].layout = _binding_layout[2];
+ bindings[2].desc = VKBufDesc (out_vk->get_vk_buf (), NV12PlaneYIdx);
+ bindings[3].layout = _binding_layout[3];
+ bindings[3].desc = VKBufDesc (out_vk->get_vk_buf (), NV12PlaneUVIdx);
+ bindings[4].layout = _binding_layout[4];
+ bindings[4].desc = VKBufDesc (_lut_buf);
+
+ float factor_x, factor_y;
+ get_factors (factor_x, factor_y);
+ _image_prop.lut_step[0] = 1.0f / factor_x;
+ _image_prop.lut_step[1] = 1.0f / factor_y;
+ _image_prop.lut_step[2] = _image_prop.lut_step[0];
+ _image_prop.lut_step[3] = _image_prop.lut_step[1];
+
+ SmartPtr<GeoMapArgs> args = new GeoMapArgs (param);
+ XCAM_ASSERT (args.ptr ());
+ args->set_bindings (bindings);
+ args->add_push_const (new VKGeoMapPushConst (_image_prop));
+
+ return _worker->work (args);
+}
+
+void
+VKGeoMapHandler::geomap_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error)
+{
+ if (!xcam_ret_is_ok (error)) {
+ XCAM_LOG_ERROR ("VKGeoMapHandler(%s) geometry map failed.", XCAM_STR (get_name ()));
+ }
+
+ SmartPtr<VKWorker> vk_worker = worker.dynamic_cast_ptr<VKWorker> ();
+ XCAM_ASSERT (vk_worker.ptr ());
+ vk_worker->wait_fence ();
+
+ SmartPtr<GeoMapArgs> args = base.dynamic_cast_ptr<GeoMapArgs> ();
+ XCAM_ASSERT (args.ptr ());
+ const SmartPtr<ImageHandler::Parameters> param = args->get_param ();
+ XCAM_ASSERT (param.ptr ());
+
+ execute_done (param, error);
+}
+
+XCamReturn
+VKGeoMapHandler::remap (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf)
+{
+ SmartPtr<ImageHandler::Parameters> param = new ImageHandler::Parameters (in_buf, out_buf);
+ XCAM_ASSERT (param.ptr ());
+
+ XCamReturn ret = execute_buffer (param, false);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "VKGeoMapHandler(%s) remap failed", XCAM_STR (get_name ()));
+
+ if (!out_buf.ptr ()) {
+ out_buf = param->out_buf;
+ }
+
+ return ret;
+}
+
+SmartPtr<VKHandler> create_vk_geo_mapper (const SmartPtr<VKDevice> &dev, const char* name)
+{
+ SmartPtr<VKHandler> mapper = new VKGeoMapHandler (dev, name);
+ XCAM_ASSERT (mapper.ptr ());
+
+ return mapper;
+}
+
+SmartPtr<GeoMapper>
+GeoMapper::create_vk_geo_mapper (const SmartPtr<VKDevice> &dev, const char* name)
+{
+ SmartPtr<VKHandler> handler = XCam::create_vk_geo_mapper (dev, name);
+ return handler.dynamic_cast_ptr<GeoMapper> ();
+}
+
+};
diff --git a/modules/vulkan/vk_geomap_handler.h b/modules/vulkan/vk_geomap_handler.h
new file mode 100644
index 0000000..bf8d4d3
--- /dev/null
+++ b/modules/vulkan/vk_geomap_handler.h
@@ -0,0 +1,78 @@
+/*
+ * vk_geomap_handler.h - vulkan geometry map handler class
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Yinhang Liu <yinhangx.liu@intel.com>
+ */
+
+#ifndef XCAM_VK_GEOMAP_HANDLER_H
+#define XCAM_VK_GEOMAP_HANDLER_H
+
+#include <xcam_utils.h>
+#include <interface/geo_mapper.h>
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_worker.h>
+#include <vulkan/vk_handler.h>
+
+namespace XCam {
+
+class VKGeoMapHandler
+ : public VKHandler, public GeoMapper
+{
+public:
+ struct PushConstsProp {
+ uint in_img_width;
+ uint in_img_height;
+ uint out_img_width;
+ uint out_img_height;
+ uint lut_width;
+ uint lut_height;
+ float lut_step[4];
+ float lut_std_step[2];
+
+ PushConstsProp ();
+ };
+
+public:
+ explicit VKGeoMapHandler (const SmartPtr<VKDevice> &dev, const char* name = "vk-geomap-handler");
+
+ bool set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height);
+
+ XCamReturn remap (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf);
+ void geomap_done (
+ const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error);
+
+private:
+ virtual XCamReturn configure_resource (const SmartPtr<Parameters> &param);
+ virtual XCamReturn start_work (const SmartPtr<Parameters> &param);
+
+private:
+ virtual bool init_factors ();
+
+private:
+ SmartPtr<VKWorker> _worker;
+ PushConstsProp _image_prop;
+ VKDescriptor::BindingArray _binding_layout;
+
+ SmartPtr<VKBuffer> _lut_buf;
+ uint32_t _lut_width;
+ uint32_t _lut_height;
+};
+
+extern SmartPtr<VKHandler> create_vk_geo_mapper (const SmartPtr<VKDevice> &dev, const char* name);
+
+}
+#endif // XCAM_VK_GEOMAP_HANDLER_H
diff --git a/modules/vulkan/vk_handler.cpp b/modules/vulkan/vk_handler.cpp
new file mode 100644
index 0000000..6aa1a83
--- /dev/null
+++ b/modules/vulkan/vk_handler.cpp
@@ -0,0 +1,60 @@
+/*
+ * vk_handler.cpp - vulkan image handler class
+ *
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_handler.h"
+#include "vk_device.h"
+#include "vk_video_buf_allocator.h"
+
+namespace XCam {
+
+VKHandler::VKHandler (const SmartPtr<VKDevice> &dev, const char* name)
+ : ImageHandler (name)
+ , _device (dev)
+{
+}
+
+VKHandler::~VKHandler ()
+{
+}
+
+
+XCamReturn
+VKHandler::finish ()
+{
+ if (_device.ptr ())
+ _device->compute_queue_wait_idle ();
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKHandler::terminate ()
+{
+ finish ();
+ return ImageHandler::terminate ();
+}
+
+SmartPtr<BufferPool>
+VKHandler::create_allocator ()
+{
+ return new VKVideoBufAllocator (_device);
+}
+
+}
diff --git a/modules/vulkan/vk_handler.h b/modules/vulkan/vk_handler.h
new file mode 100644
index 0000000..3d80fa0
--- /dev/null
+++ b/modules/vulkan/vk_handler.h
@@ -0,0 +1,57 @@
+/*
+ * vk_handler.h - vulkan image handler class
+ *
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_HANDLER_H
+#define XCAM_VK_HANDLER_H
+
+#include <vulkan/vulkan_std.h>
+#include <image_handler.h>
+
+namespace XCam {
+
+class VKDevice;
+
+class VKHandler
+ : public ImageHandler
+{
+public:
+ explicit VKHandler (const SmartPtr<VKDevice> &dev, const char* name = "vk-handler");
+ ~VKHandler ();
+ const SmartPtr<VKDevice> &get_vk_device () const {
+ return _device;
+ }
+
+ // derive from ImageHandler
+ virtual XCamReturn finish ();
+ virtual XCamReturn terminate ();
+
+protected:
+ SmartPtr<BufferPool> create_allocator ();
+
+private:
+ XCAM_DEAD_COPY (VKHandler);
+
+protected:
+ SmartPtr<VKDevice> _device;
+};
+
+}
+
+#endif //XCAM_VK_HANDLER_H
diff --git a/modules/vulkan/vk_instance.cpp b/modules/vulkan/vk_instance.cpp
new file mode 100644
index 0000000..81b3e6d
--- /dev/null
+++ b/modules/vulkan/vk_instance.cpp
@@ -0,0 +1,230 @@
+/*
+ * vk_instance.cpp - vulkan instance
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_instance.h"
+#include "vulkan_common.h"
+
+#define APP_NAME "xcam"
+#define ENGINE_NAME "xcam"
+
+#define XCAM_INVALID_VK_QUEUE_IDX UINT32_MAX
+
+namespace XCam {
+
+extern void vk_init_error_string ();
+
+SmartPtr<VKInstance> VKInstance::_instance;
+Mutex VKInstance::_instance_mutex;
+
+VKInstance::~VKInstance ()
+{
+ if (XCAM_IS_VALID_VK_ID (_instance_id))
+ vkDestroyInstance (_instance_id, _allocator.ptr ());
+}
+
+VKInstance::VKInstance (VkInstance id, VkAllocationCallbacks *allocator)
+ : _instance_id (id)
+ , _allocator (allocator)
+ , _physical_device (NULL)
+ , _compute_queue_family_idx (XCAM_INVALID_VK_QUEUE_IDX)
+ , _graphics_queue_family_idx (XCAM_INVALID_VK_QUEUE_IDX)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id));
+ xcam_mem_clear (_device_properties);
+ xcam_mem_clear (_dev_mem_properties);
+}
+
+SmartPtr<VKInstance>
+VKInstance::get_instance ()
+{
+ SmartLock locker (_instance_mutex);
+ if (!_instance.ptr ()) {
+ vk_init_error_string ();
+ _instance = create_instance ();
+ }
+ return _instance;
+}
+
+SmartPtr<VKInstance>
+VKInstance::create_instance ()
+{
+ VkApplicationInfo app_info = {};
+ app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ app_info.pApplicationName = APP_NAME;
+ app_info.applicationVersion = 0;
+ app_info.pEngineName = ENGINE_NAME;
+ app_info.engineVersion = xcam_version ();
+ app_info.apiVersion = VK_API_VERSION_1_0;
+
+ VkInstance id;
+ VkInstanceCreateInfo inst_create_info = {};
+ inst_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ inst_create_info.pApplicationInfo = &app_info;
+ inst_create_info.enabledExtensionCount = 0; // TODO, add extensions
+ XCAM_VK_CHECK_RETURN(
+ ERROR, vkCreateInstance (&inst_create_info, NULL, &id),
+ NULL, "create vk instance failed");
+
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id));
+ SmartPtr<VKInstance> vk_instance = new VKInstance (id, NULL);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (vk_instance->query_physical_info ()), NULL,
+ "vk instance query physical info failed");
+
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (vk_instance->query_queue_info ()), NULL,
+ "vk instance query queue info failed");
+
+ return vk_instance;
+}
+
+static const char *s_device_types[] = {
+ "OTHER_DEVICE",
+ "INTEGRATED_GPU",
+ "DISCRETE_GPU",
+ "VIRTUAL_GPU",
+ "CPU_TYPE",
+};
+
+static const char*
+device_type_to_str(VkPhysicalDeviceType type)
+{
+ size_t number = sizeof (s_device_types) / sizeof (s_device_types[0]);
+ assert (number == 5);
+ if ((size_t)type < number)
+ return s_device_types [type];
+ return "UNKNOWN_TYPE";
+}
+
+XCamReturn
+VKInstance::query_physical_info ()
+{
+#define MAX_DEV_NUM 256
+ VkPhysicalDevice devs[MAX_DEV_NUM];
+ uint32_t dev_num = 0;
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkEnumeratePhysicalDevices (_instance_id, &dev_num, NULL),
+ XCAM_RETURN_ERROR_VULKAN, "enum vk physical devices failed");
+ XCAM_FAIL_RETURN (
+ ERROR, dev_num, XCAM_RETURN_ERROR_VULKAN,
+ "There is NO vk physical devices");
+
+ dev_num = XCAM_MIN (dev_num, MAX_DEV_NUM);
+ vkEnumeratePhysicalDevices (_instance_id, &dev_num, devs);
+
+ VkPhysicalDevice gpu_dev[VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE] = {};
+
+ VkPhysicalDeviceProperties dev_prop;
+ for (uint32_t i = 0; i < dev_num; ++i) {
+ vkGetPhysicalDeviceProperties (devs[i], &dev_prop);
+
+ if (dev_prop.deviceType < VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE ||
+ dev_prop.deviceType > VK_PHYSICAL_DEVICE_TYPE_END_RANGE) {
+ continue;
+ }
+ if (gpu_dev[dev_prop.deviceType]) {
+ XCAM_LOG_WARNING (
+ "double vk physical dev, type:%d, name:%s",
+ dev_prop.deviceType, dev_prop.deviceName);
+ continue;
+ }
+ gpu_dev[dev_prop.deviceType] = devs[i];
+#if 0
+ printf ("found vk physical dev_id:%d, name:%s, type:%d, API:%d\n",
+ dev_prop.deviceID, dev_prop.deviceName,
+ device_type_to_str (dev_prop.deviceType), dev_prop.apiVersion);
+#endif
+ }
+
+ if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU])
+ _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU];
+ else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU])
+ _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU];
+ else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU])
+ _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU];
+ else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_CPU]) {
+ _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_CPU];
+ XCAM_LOG_WARNING ("vk device select physical CPU, performance may slow down");
+ } else {
+ XCAM_LOG_ERROR ("did NOT find available vk physical device");
+ return XCAM_RETURN_ERROR_VULKAN;
+ }
+
+ vkGetPhysicalDeviceProperties (_physical_device, &dev_prop);
+ XCAM_LOG_INFO ("choose vk physical dev properties dev_id:%d, name:%s, type:%s, API:%d\n",
+ dev_prop.deviceID, dev_prop.deviceName,
+ device_type_to_str (dev_prop.deviceType), dev_prop.apiVersion);
+ _device_properties = dev_prop;
+ vkGetPhysicalDeviceMemoryProperties (_physical_device, &_dev_mem_properties);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKInstance::query_queue_info ()
+{
+ XCAM_ASSERT (_physical_device);
+ // get queue family porperties
+ uint32_t queue_count = 0;
+#define MAX_QUEUE_FAMILY_NUM 256
+ VkQueueFamilyProperties queue_family[MAX_QUEUE_FAMILY_NUM];
+
+ vkGetPhysicalDeviceQueueFamilyProperties (
+ _physical_device, &queue_count, NULL);
+ XCAM_FAIL_RETURN (
+ ERROR, queue_count, XCAM_RETURN_ERROR_VULKAN,
+ "There is NO vk physical devices");
+
+ if (queue_count > MAX_QUEUE_FAMILY_NUM)
+ queue_count = MAX_QUEUE_FAMILY_NUM;
+
+ vkGetPhysicalDeviceQueueFamilyProperties (
+ _physical_device, &queue_count, queue_family);
+
+ for (uint32_t i = 0; i < queue_count; ++i) {
+ if (queue_family[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
+ _compute_queue_family_idx = i;
+ }
+ if (queue_family[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ _graphics_queue_family_idx = i;
+ }
+ }
+
+ XCAM_FAIL_RETURN (
+ ERROR,
+ _compute_queue_family_idx != XCAM_INVALID_VK_QUEUE_IDX &&
+ _graphics_queue_family_idx != XCAM_INVALID_VK_QUEUE_IDX,
+ XCAM_RETURN_ERROR_VULKAN,
+ "There is NO vk compute/graphics queue family");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+uint32_t
+VKInstance::get_mem_type_index (VkMemoryPropertyFlags prop) const
+{
+ for (uint32_t i = 0; i < _dev_mem_properties.memoryTypeCount; ++i) {
+ if (((uint32_t)(_dev_mem_properties.memoryTypes[i].propertyFlags) & prop) == prop)
+ return i;
+ }
+ return (uint32_t)(-1);
+}
+
+}
diff --git a/modules/vulkan/vk_instance.h b/modules/vulkan/vk_instance.h
new file mode 100644
index 0000000..b4b51d4
--- /dev/null
+++ b/modules/vulkan/vk_instance.h
@@ -0,0 +1,77 @@
+/*
+ * vk_instance.h - vulkan instance
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_INSTANCE_H
+#define XCAM_VK_INSTANCE_H
+
+#include <vulkan/vulkan_std.h>
+#include <xcam_mutex.h>
+
+namespace XCam {
+
+class VKInstance
+{
+public:
+ ~VKInstance ();
+ static SmartPtr<VKInstance> get_instance ();
+
+ VkInstance get_id () const {
+ return _instance_id;
+ }
+ VkPhysicalDevice get_physical_dev () const {
+ return _physical_device;
+ }
+ uint32_t get_compute_queue_family_idx () const {
+ return _compute_queue_family_idx;
+ }
+ uint32_t get_graphics_queue_family_idx () const {
+ return _graphics_queue_family_idx;
+ }
+ uint32_t get_mem_type_index (VkMemoryPropertyFlags prop) const;
+
+ SmartPtr<VkAllocationCallbacks> get_allocator () const {
+ return _allocator;
+ }
+
+private:
+ explicit VKInstance (VkInstance id, VkAllocationCallbacks *allocator);
+ static SmartPtr<VKInstance> create_instance ();
+ XCamReturn query_physical_info ();
+ XCamReturn query_queue_info ();
+
+private:
+ XCAM_DEAD_COPY (VKInstance);
+
+private:
+ static SmartPtr<VKInstance> _instance;
+ static Mutex _instance_mutex;
+
+ VkInstance _instance_id;
+ SmartPtr<VkAllocationCallbacks> _allocator;
+ VkPhysicalDevice _physical_device;
+ VkPhysicalDeviceProperties _device_properties;
+ VkPhysicalDeviceMemoryProperties _dev_mem_properties;
+ uint32_t _compute_queue_family_idx;
+ uint32_t _graphics_queue_family_idx;
+};
+
+}
+
+#endif //XCAM_VK_INSTANCE_H
diff --git a/modules/vulkan/vk_memory.cpp b/modules/vulkan/vk_memory.cpp
new file mode 100644
index 0000000..09af690
--- /dev/null
+++ b/modules/vulkan/vk_memory.cpp
@@ -0,0 +1,182 @@
+/*
+ * vk_memory.cpp - Vulkan memory
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_memory.h"
+#include "vk_device.h"
+
+namespace XCam {
+
+VKBufInfo::VKBufInfo ()
+ : format (V4L2_PIX_FMT_NV12)
+ , width (0)
+ , height (0)
+ , aligned_width (0)
+ , aligned_height (0)
+ , size (0)
+{
+ xcam_mem_clear (strides);
+ xcam_mem_clear (offsets);
+ xcam_mem_clear (slice_size);
+}
+
+VKMemory::VKMemory (
+ const SmartPtr<VKDevice> dev,
+ VkDeviceMemory id,
+ uint32_t size,
+ VkMemoryPropertyFlags mem_prop)
+ : _dev (dev)
+ , _mem_id (id)
+ , _mem_prop (mem_prop)
+ , _size (size)
+ , _mapped_ptr (NULL)
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id));
+}
+
+VKMemory::~VKMemory ()
+{
+ if (XCAM_IS_VALID_VK_ID (_mem_id) && _dev.ptr ()) {
+ _dev->free_mem_id (_mem_id);
+ }
+}
+
+void *
+VKMemory::map (VkDeviceSize size, VkDeviceSize offset)
+{
+ if (_mapped_ptr)
+ return _mapped_ptr;
+
+ XCAM_FAIL_RETURN (
+ ERROR,
+ xcam_ret_is_ok (_dev->map_mem (_mem_id, size, offset, _mapped_ptr)), NULL,
+ "VK memory map failed");
+
+ return _mapped_ptr;
+}
+
+void
+VKMemory::unmap ()
+{
+ if (_mapped_ptr) {
+ _dev->unmap_mem (_mem_id);
+ _mapped_ptr = NULL;
+ }
+}
+
+VKBuffer::VKBuffer (
+ const SmartPtr<VKDevice> dev,
+ VkBuffer buf_id,
+ VkDeviceMemory mem_id,
+ uint32_t size,
+ VkBufferUsageFlags usage,
+ VkMemoryPropertyFlags prop)
+ : VKMemory (dev, mem_id, size, prop)
+ , _buffer_id (buf_id)
+ , _usage_flags (usage)
+ , _prop_flags (prop)
+{
+}
+
+VKBuffer::~VKBuffer ()
+{
+ if (XCAM_IS_VALID_VK_ID (_buffer_id) && _dev.ptr ()) {
+ _dev->destroy_buf_id (_buffer_id);
+ }
+}
+
+XCamReturn
+VKBuffer::bind ()
+{
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_buffer_id));
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_mem_id));
+
+ return _dev->bind_buffer (_buffer_id, _mem_id, 0);
+}
+
+SmartPtr<VKBuffer>
+VKBuffer::create_buffer (
+ const SmartPtr<VKDevice> dev,
+ VkBufferUsageFlags usage,
+ uint32_t size, void *data,
+ VkMemoryPropertyFlags mem_prop)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, dev.ptr () && size, NULL,
+ "vk create buffer failed because of dev or size errors");
+
+ VkBuffer buf_id = dev->create_buf_id (usage, size);
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (buf_id), NULL,
+ "vk create buffer failed");
+
+ VkDevice dev_id = dev->get_dev_id ();
+ VkMemoryRequirements mem_reqs;
+ vkGetBufferMemoryRequirements (dev_id, buf_id, &mem_reqs);
+ VkDeviceMemory mem_id = dev->allocate_mem_id (mem_reqs.size, mem_prop);
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (mem_id), NULL,
+ "vk create buffer failed in mem allocation");
+
+ // size == mem_reqs.size or size?
+ SmartPtr<VKBuffer> buf = new VKBuffer (dev, buf_id, mem_id, size, usage, mem_prop);
+
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (buf->bind ()), NULL,
+ "vk create bufer failed when bind with memory");
+ if (!data)
+ return buf;
+
+ void *ptr = buf->map ();
+ XCAM_FAIL_RETURN (
+ ERROR, ptr, NULL,
+ "vk create bufer failed when map the buf");
+ memcpy (ptr, data, size);
+ buf->unmap ();
+
+ return buf;
+
+}
+
+VKBufDesc::VKBufDesc ()
+{
+ xcam_mem_clear (desc_info);
+}
+
+VKBufDesc::VKBufDesc (const SmartPtr<VKBuffer> &buffer, NV12PlaneIdx plane)
+ : buf (buffer)
+{
+ xcam_mem_clear (desc_info);
+ const VKBufInfo info = buffer->get_buf_info ();
+
+ desc_info.buffer = buffer->get_buf_id ();
+ desc_info.offset = info.offsets[plane];
+ desc_info.range = info.slice_size[plane];
+}
+
+VKBufDesc::VKBufDesc (const SmartPtr<VKBuffer> &buffer, uint32_t offset, size_t size)
+ : buf (buffer)
+{
+ xcam_mem_clear (desc_info);
+ desc_info.buffer = buffer->get_buf_id ();
+ desc_info.offset = offset;
+ desc_info.range = size;
+}
+
+}
diff --git a/modules/vulkan/vk_memory.h b/modules/vulkan/vk_memory.h
new file mode 100644
index 0000000..3eba942
--- /dev/null
+++ b/modules/vulkan/vk_memory.h
@@ -0,0 +1,134 @@
+/*
+ * vk_memory.h - Vulkan memory
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_MEMORY_H
+#define XCAM_VK_MEMORY_H
+
+#include <vulkan/vulkan_std.h>
+
+#define XCAM_VK_MAX_COMPONENTS 4
+
+namespace XCam {
+
+struct VKBufInfo {
+ uint32_t format;
+ uint32_t width;
+ uint32_t height;
+ uint32_t aligned_width;
+ uint32_t aligned_height;
+ uint32_t size;
+ uint32_t strides[XCAM_VK_MAX_COMPONENTS];
+ uint32_t offsets[XCAM_VK_MAX_COMPONENTS];
+ uint32_t slice_size[XCAM_VK_MAX_COMPONENTS];
+
+ VKBufInfo ();
+ bool operator == (const VKBufInfo &info) const;
+};
+
+class VKDevice;
+
+class VKMemory
+{
+public:
+ virtual ~VKMemory ();
+ void *map (VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0);
+ void unmap ();
+
+protected:
+ explicit VKMemory (
+ const SmartPtr<VKDevice> dev, VkDeviceMemory id,
+ uint32_t size, VkMemoryPropertyFlags mem_prop);
+ VkDeviceMemory get_mem_id () const {
+ return _mem_id;
+ }
+
+private:
+ XCAM_DEAD_COPY (VKMemory);
+
+protected:
+ const SmartPtr<VKDevice> _dev;
+ VkDeviceMemory _mem_id;
+ VkMemoryPropertyFlags _mem_prop;
+ uint32_t _size;
+ void *_mapped_ptr;
+};
+
+class VKBuffer
+ : public VKMemory
+{
+public:
+ ~VKBuffer ();
+
+ // usage can be VK_BUFFER_USAGE_STORAGE_BUFFER_BIT or VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
+ static SmartPtr<VKBuffer>
+ create_buffer (
+ const SmartPtr<VKDevice> dev,
+ VkBufferUsageFlags usage,
+ uint32_t size, void *data = NULL,
+ VkMemoryPropertyFlags mem_prop = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+
+ VkBuffer get_buf_id () const {
+ return _buffer_id;
+ }
+ VkBufferUsageFlags get_usage_flags () const {
+ return _usage_flags;
+ }
+ VkMemoryPropertyFlags get_mem_flags () const {
+ return _prop_flags;
+ }
+
+ void set_buf_info (const VKBufInfo &info) {
+ _buf_info = info;
+ }
+ const VKBufInfo &get_buf_info () const {
+ return _buf_info;
+ }
+
+private:
+ explicit VKBuffer (
+ const SmartPtr<VKDevice> dev, VkBuffer buf_id,
+ VkDeviceMemory mem_id, uint32_t size,
+ VkBufferUsageFlags usage, VkMemoryPropertyFlags prop);
+ XCamReturn bind ();
+
+private:
+ XCAM_DEAD_COPY (VKBuffer);
+
+private:
+ VkBuffer _buffer_id;
+ VkBufferUsageFlags _usage_flags;
+ VkMemoryPropertyFlags _prop_flags;
+ VKBufInfo _buf_info;
+};
+
+struct VKBufDesc {
+ SmartPtr<VKBuffer> buf;
+ VkDescriptorBufferInfo desc_info;
+
+ VKBufDesc ();
+ VKBufDesc (const SmartPtr<VKBuffer> &buffer, NV12PlaneIdx plane);
+ VKBufDesc (const SmartPtr<VKBuffer> &buffer, uint32_t offset = 0, size_t size = VK_WHOLE_SIZE);
+};
+
+typedef std::vector<SmartPtr<VKBuffer>> VKBufferArray;
+
+}
+
+#endif //XCAM_VK_MEMORY_H
diff --git a/modules/vulkan/vk_pipeline.cpp b/modules/vulkan/vk_pipeline.cpp
new file mode 100644
index 0000000..5483582
--- /dev/null
+++ b/modules/vulkan/vk_pipeline.cpp
@@ -0,0 +1,293 @@
+/*
+ * vk_pipeline.cpp - Vulkan pipeline
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_pipeline.h"
+#include "vulkan_common.h"
+#include "vk_cmdbuf.h"
+
+namespace XCam {
+
+VKPipeline::VKPipeline (
+ const SmartPtr<VKDevice> dev,
+ const ShaderVec &shaders,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKConstantArray &consts)
+ : _pipe_id (VK_NULL_HANDLE)
+ , _dev (dev)
+ , _shaders (shaders)
+ , _bindings (bindings)
+ , _push_consts (consts)
+{
+ _allocator = _dev->get_allocation_cb ();
+ xcam_mem_clear (_name);
+}
+
+VKPipeline::~VKPipeline ()
+{
+ if (!_dev.ptr ())
+ return;
+
+ VkDevice dev_id = _dev->get_dev_id ();
+ if (XCAM_IS_VALID_VK_ID (_pipe_id))
+ vkDestroyPipeline (dev_id, _pipe_id, _allocator.ptr ());
+}
+
+void
+VKPipeline::set_desc_pool (const SmartPtr<VKDescriptor::Pool> pool)
+{
+ _pool = pool;
+
+ //TODO, check pool status and allocate set, need or not?
+}
+
+VkDescriptorSetLayout
+VKPipeline::create_desc_set_layout (
+ const VKDescriptor::BindingArray &bindings)
+{
+ VKDescriptor::VkBindingArray array = VKDescriptor::get_vk_layoutbindings (bindings);
+
+ VkDescriptorSetLayoutCreateInfo descriptor_layout = {};
+ descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ descriptor_layout.bindingCount = array.size ();
+ descriptor_layout.pBindings = array.data ();
+
+ VkDescriptorSetLayout layout = NULL;
+ XCAM_VK_CHECK_RETURN (
+ ERROR,
+ vkCreateDescriptorSetLayout (
+ _dev->get_dev_id (), &descriptor_layout, _allocator.ptr (), &layout),
+ NULL, "VkPipeline create descriptor set layout failed");
+
+ return layout;
+}
+
+
+VkPipelineLayout
+VKPipeline::create_pipeline_layout (
+ VkDescriptorSetLayout desc_layout,
+ const VKConstRange::VKConstantArray &consts)
+{
+ VkPipelineLayoutCreateInfo pipe_layout_create_info = {};
+ pipe_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipe_layout_create_info.flags = 0;
+ pipe_layout_create_info.setLayoutCount = 1;
+ pipe_layout_create_info.pSetLayouts = &desc_layout;
+ if (!consts.empty()) {
+ pipe_layout_create_info.pushConstantRangeCount = consts.size ();
+ pipe_layout_create_info.pPushConstantRanges = consts.data ();
+ }
+
+ VkPipelineLayout layout = NULL;
+ XCAM_VK_CHECK_RETURN (
+ ERROR,
+ vkCreatePipelineLayout (
+ _dev->get_dev_id (), &pipe_layout_create_info, NULL, &layout),
+ NULL, "VkPipeline create descriptor set layout failed");
+
+ return layout;
+}
+
+SmartPtr<VKPipeline>
+VKPipeline::create_compute_pipeline (
+ const SmartPtr<VKDevice> dev,
+ const SmartPtr<VKShader> shader,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKConstantArray &consts)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, dev.ptr () && shader.ptr (), NULL,
+ "VKDevice create pipeline with error of null device ready.");
+
+ ShaderVec shaders = {shader};
+ SmartPtr<VKPipeline> pipe = new VKComputePipeline (dev, shaders, bindings, consts);
+
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (pipe->ensure_layouts ()), NULL,
+ "vk pipeline ensure layouts failed");
+
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (pipe->ensure_pipeline ()), NULL,
+ "vk pipeline ensure pipeline failed");
+
+ return pipe;
+}
+
+VKComputePipeline::VKComputePipeline (
+ const SmartPtr<VKDevice> dev,
+ const ShaderVec &shaders,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKConstantArray &consts)
+ : VKPipeline (dev, shaders, bindings, consts)
+ , _pipe_layout (VK_NULL_HANDLE)
+ , _desc_layout (VK_NULL_HANDLE)
+{
+}
+
+VKComputePipeline::~VKComputePipeline ()
+{
+ if (!_dev.ptr ())
+ return;
+
+ VkDevice dev_id = _dev->get_dev_id ();
+ if (XCAM_IS_VALID_VK_ID (_pipe_layout))
+ vkDestroyPipelineLayout (dev_id, _pipe_layout, _allocator.ptr ());
+ if (XCAM_IS_VALID_VK_ID (_desc_layout))
+ vkDestroyDescriptorSetLayout (dev_id, _desc_layout, _allocator.ptr ());
+}
+
+XCamReturn
+VKComputePipeline::ensure_layouts ()
+{
+ if (!XCAM_IS_VALID_VK_ID (_desc_layout)) {
+ _desc_layout = create_desc_set_layout (_bindings);
+ }
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID(_desc_layout), XCAM_RETURN_ERROR_VULKAN,
+ "vk compute pipeline create desc layout failed");
+
+ if (!XCAM_IS_VALID_VK_ID (_pipe_layout)) {
+ _pipe_layout = create_pipeline_layout (_desc_layout, _push_consts);
+ }
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID(_pipe_layout), XCAM_RETURN_ERROR_VULKAN,
+ "vk compute pipeline create pipeline layout failed");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKComputePipeline::ensure_pipeline ()
+{
+ XCAM_FAIL_RETURN (
+ ERROR, XCAM_IS_VALID_VK_ID (_desc_layout) && XCAM_IS_VALID_VK_ID (_pipe_layout),
+ XCAM_RETURN_ERROR_PARAM,
+ "vk compute ensure pipeline failed. need ensure desc_layout and pipe_layout first");
+
+ XCAM_FAIL_RETURN (
+ ERROR, !_shaders.empty (), XCAM_RETURN_ERROR_PARAM,
+ "vk compute ensure pipeline failed, shader was empty");
+
+ VkComputePipelineCreateInfo pipeline_create_info =
+ get_compute_create_info (_shaders[0], _pipe_layout);
+
+ VkPipeline pipe_id;
+ XCAM_VK_CHECK_RETURN (
+ ERROR, vkCreateComputePipelines (
+ _dev->get_dev_id (), 0, 1, &pipeline_create_info, 0, &pipe_id),
+ XCAM_RETURN_ERROR_VULKAN, "VK create compute pipeline failed.");
+
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pipe_id));
+ _pipe_id = pipe_id;
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKComputePipeline::update_bindings (const VKDescriptor::SetBindInfoArray &bind_array)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, _pool.ptr () && XCAM_IS_VALID_VK_ID (_desc_layout), XCAM_RETURN_ERROR_PARAM,
+ "vk compute pipeline update bindins failed, pool was not set or desc_layout not ensured");
+
+ if (_desc_set.ptr ())
+ _desc_set.release ();
+
+ _desc_set = _pool->allocate_set (bind_array, _desc_layout);
+ XCAM_FAIL_RETURN (
+ ERROR, _desc_set.ptr (), XCAM_RETURN_ERROR_UNKNOWN,
+ "vk compute pipeline update bindins failed to allocate desc_set or update bindings");
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKComputePipeline::bind_by (VKCmdBuf &cmd_buf)
+{
+
+ VkCommandBuffer buf_id = cmd_buf.get_cmd_buf_id ();
+ VkPipeline pipe_id = get_pipeline_id ();
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf_id));
+ XCAM_FAIL_RETURN (
+ ERROR,
+ XCAM_IS_VALID_VK_ID (pipe_id) && XCAM_IS_VALID_VK_ID (_pipe_layout) && _desc_set.ptr (),
+ XCAM_RETURN_ERROR_PARAM,
+ "vk compute pipeline bind command buffer failed, please check pipe_id, pipe_layout and desc_layout.");
+
+ // // bind pipeline sets
+ vkCmdBindPipeline (buf_id, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_id);
+
+ // bind descriptor sets
+ VkDescriptorSet desc_set_id = _desc_set->get_set_id ();
+ vkCmdBindDescriptorSets (
+ buf_id, VK_PIPELINE_BIND_POINT_COMPUTE, _pipe_layout,
+ 0, 1, &desc_set_id, 0, NULL);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKComputePipeline::push_consts_by (
+ VKCmdBuf &cmd_buf, const SmartPtr<VKConstRange::VKPushConstArg> &push_const)
+{
+ VkCommandBuffer cmd_buf_id = cmd_buf.get_cmd_buf_id ();
+ XCAM_FAIL_RETURN (
+ ERROR,
+ XCAM_IS_VALID_VK_ID (cmd_buf_id) && XCAM_IS_VALID_VK_ID (_pipe_layout),
+ XCAM_RETURN_ERROR_PARAM,
+ "vk compute pipeline push_consts by cmdbuf failed, please check pipe_layout and cmd_buf_id.");
+
+ XCAM_ASSERT (push_const.ptr ());
+ VkPushConstantRange const_range;
+ xcam_mem_clear (const_range);
+ void *ptr = NULL;
+ push_const->get_const_data (const_range, ptr);
+
+ XCAM_FAIL_RETURN (
+ ERROR,
+ const_range.stageFlags == VK_SHADER_STAGE_COMPUTE_BIT,
+ XCAM_RETURN_ERROR_PARAM,
+ "vk compute pipeline push_consts by cmdbuf failed, please check pipe_layout and cmd_buf_id.");
+
+ vkCmdPushConstants(
+ cmd_buf_id, _pipe_layout, VK_SHADER_STAGE_COMPUTE_BIT, const_range.offset, const_range.size, ptr);
+ return XCAM_RETURN_NO_ERROR;
+}
+
+VkComputePipelineCreateInfo
+VKComputePipeline::get_compute_create_info (
+ const SmartPtr<VKShader> &shader,
+ VkPipelineLayout &layout)
+{
+ VkPipelineShaderStageCreateInfo shader_stage_create_info = {};
+ shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ shader_stage_create_info.flags = 0;
+ shader_stage_create_info.stage = shader->get_shader_stage_flags ();
+ shader_stage_create_info.module = shader->get_shader_id ();
+ shader_stage_create_info.pName = shader->get_func_name ();
+
+ VkComputePipelineCreateInfo pipeline_create_info = { };
+ pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
+ pipeline_create_info.pNext = NULL;
+ pipeline_create_info.flags = 0;
+ pipeline_create_info.stage = shader_stage_create_info;
+ pipeline_create_info.layout = layout;
+
+ return pipeline_create_info;
+}
+
+}
diff --git a/modules/vulkan/vk_pipeline.h b/modules/vulkan/vk_pipeline.h
new file mode 100644
index 0000000..cecb99b
--- /dev/null
+++ b/modules/vulkan/vk_pipeline.h
@@ -0,0 +1,127 @@
+/*
+ * vk_pipeline.h - Vulkan pipeline
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_PIPELINE_H
+#define XCAM_VK_PIPELINE_H
+
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_descriptor.h>
+#include <vulkan/vk_device.h>
+#include <vulkan/vk_shader.h>
+
+namespace XCam {
+
+class VKPipeline
+{
+public:
+ static SmartPtr<VKPipeline>
+ create_compute_pipeline (
+ const SmartPtr<VKDevice> dev,
+ const SmartPtr<VKShader> shader,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKConstantArray &consts);
+
+ virtual ~VKPipeline ();
+
+ VkPipeline get_pipeline_id () const {
+ return _pipe_id;
+ }
+ const char *get_name () const {
+ return _name;
+ }
+ void set_desc_pool (const SmartPtr<VKDescriptor::Pool> pool);
+ //interface
+ virtual XCamReturn update_bindings (const VKDescriptor::SetBindInfoArray &bind_array) = 0;
+
+ // inter-functions, called by VKCmdBuf
+ virtual XCamReturn bind_by (VKCmdBuf &cmd_buf) = 0;
+ virtual XCamReturn push_consts_by (
+ VKCmdBuf &cmd_buf, const SmartPtr<VKConstRange::VKPushConstArg> &push_const) = 0;
+
+protected:
+ explicit VKPipeline (
+ const SmartPtr<VKDevice> dev,
+ const ShaderVec &shaders,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKConstantArray &consts);
+
+ VkDescriptorSetLayout create_desc_set_layout (
+ const VKDescriptor::BindingArray &bindings);
+
+ VkPipelineLayout create_pipeline_layout (
+ VkDescriptorSetLayout desc_layout,
+ const VKConstRange::VKConstantArray &consts);
+
+ // intra virtual functions
+ virtual XCamReturn ensure_layouts () = 0;
+ virtual XCamReturn ensure_pipeline () = 0;
+
+private:
+ XCAM_DEAD_COPY (VKPipeline);
+
+protected:
+ VkPipeline _pipe_id;
+ char _name [XCAM_VK_NAME_LENGTH];
+
+ SmartPtr<VKDevice> _dev;
+ SmartPtr<VkAllocationCallbacks> _allocator;
+ ShaderVec _shaders;
+ VKDescriptor::BindingArray _bindings;
+ VKConstRange::VKConstantArray _push_consts;
+ SmartPtr<VKDescriptor::Pool> _pool;
+};
+
+class VKComputePipeline
+ : public VKPipeline
+{
+ friend class VKPipeline;
+
+public:
+ static VkComputePipelineCreateInfo
+ get_compute_create_info (const SmartPtr<VKShader> &shader, VkPipelineLayout &layout);
+
+ ~VKComputePipeline ();
+
+ //inherit from VKPipeline
+ XCamReturn update_bindings (const VKDescriptor::SetBindInfoArray &bind_array);
+
+protected:
+ explicit VKComputePipeline (
+ const SmartPtr<VKDevice> dev,
+ const ShaderVec &shaders,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKConstantArray &consts);
+
+ //virtual functions from VKPipeline
+ XCamReturn ensure_layouts ();
+ XCamReturn ensure_pipeline ();
+ XCamReturn bind_by (VKCmdBuf &cmd_buf);
+ XCamReturn push_consts_by (
+ VKCmdBuf &cmd_buf, const SmartPtr<VKConstRange::VKPushConstArg> &push_const);
+
+private:
+ VkPipelineLayout _pipe_layout;
+ VkDescriptorSetLayout _desc_layout;
+ SmartPtr<VKDescriptor::Set> _desc_set;
+};
+
+}
+
+#endif //XCAM_VK_PIPELINE_H
diff --git a/modules/vulkan/vk_shader.cpp b/modules/vulkan/vk_shader.cpp
new file mode 100644
index 0000000..96e0427
--- /dev/null
+++ b/modules/vulkan/vk_shader.cpp
@@ -0,0 +1,60 @@
+/*
+ * vk_shader.cpp - vulkan shader module
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_shader.h"
+#include "vk_device.h"
+#include "file_handle.h"
+
+namespace XCam {
+
+VKShader::VKShader (SmartPtr<VKDevice> dev, VkShaderModule id, const char *name)
+ : _device (dev)
+ , _shader_id (id)
+ , _shader_stage (VK_SHADER_STAGE_COMPUTE_BIT)
+{
+ XCAM_IS_VALID_VK_ID (id);
+ xcam_mem_clear (_name);
+ if (name)
+ strncpy (_name, name, XCAM_VK_NAME_LENGTH - 1);
+ strncpy (_func_name, "main", XCAM_VK_NAME_LENGTH - 1);
+}
+
+VKShader::~VKShader ()
+{
+ if (XCAM_IS_VALID_VK_ID (_shader_id))
+ _device->destroy_shader_id (_shader_id);
+}
+
+void
+VKShader::set_func_name (const char *name)
+{
+ XCAM_ASSERT (name);
+ strncpy (_func_name, name, XCAM_VK_NAME_LENGTH - 1);
+}
+
+void
+VKShader::set_name (const char *name)
+{
+ XCAM_ASSERT (name);
+ strncpy (_name, name, XCAM_VK_NAME_LENGTH - 1);
+}
+
+
+}
diff --git a/modules/vulkan/vk_shader.h b/modules/vulkan/vk_shader.h
new file mode 100644
index 0000000..fd243bb
--- /dev/null
+++ b/modules/vulkan/vk_shader.h
@@ -0,0 +1,71 @@
+/*
+ * vk_shader.h - Vulkan shader module
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_SHADER_H
+#define XCAM_VK_SHADER_H
+
+#include <vulkan/vulkan_std.h>
+
+namespace XCam {
+
+class VKDevice;
+
+class VKShader
+{
+ friend class VKDevice;
+public:
+ ~VKShader ();
+
+ VkShaderModule get_shader_id () const {
+ return _shader_id;
+ }
+ VkShaderStageFlagBits get_shader_stage_flags () const {
+ return _shader_stage;
+ }
+ void set_func_name (const char *name);
+ void set_name (const char *name);
+ const char *get_func_name () const {
+ return _func_name;
+ }
+ const char *get_name () const {
+ return _name;
+ }
+
+private:
+ explicit VKShader (SmartPtr<VKDevice> dev, VkShaderModule id, const char *name = "null");
+
+private:
+ XCAM_DEAD_COPY (VKShader);
+
+private:
+ //static ShaderTable _shader_cache;
+ //static Mutex _cache_mutex;
+ SmartPtr<VKDevice> _device;
+ VkShaderModule _shader_id;
+ VkShaderStageFlagBits _shader_stage;
+ char _func_name [XCAM_VK_NAME_LENGTH];
+ char _name [XCAM_VK_NAME_LENGTH];
+};
+
+typedef std::vector<SmartPtr<VKShader>> ShaderVec;
+
+}
+
+#endif //XCAM_VK_SHADER_H
diff --git a/modules/vulkan/vk_stitcher.cpp b/modules/vulkan/vk_stitcher.cpp
new file mode 100644
index 0000000..f074e48
--- /dev/null
+++ b/modules/vulkan/vk_stitcher.cpp
@@ -0,0 +1,824 @@
+/*
+ * vk_stitcher.cpp - Vulkan stitcher implementation
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Yinhang Liu <yinhangx.liu@intel.com>
+ */
+
+#include "surview_fisheye_dewarp.h"
+#include "vk_video_buf_allocator.h"
+#include "vk_geomap_handler.h"
+#include "vk_blender.h"
+#include "vk_copy_handler.h"
+#include "vk_stitcher.h"
+#include "interface/feature_match.h"
+
+#define DUMP_BUFFER 0
+
+#define GEOMAP_POOL_SIZE 1
+
+#define VK_STITCHER_ALIGNMENT_X 16
+#define VK_STITCHER_ALIGNMENT_Y 4
+
+#define MAP_FACTOR_X 16
+#define MAP_FACTOR_Y 16
+
+#define CHECK_RET(ret, format, ...) \
+ if (!xcam_ret_is_ok (ret)) { \
+ XCAM_LOG_ERROR (format, ## __VA_ARGS__); \
+ }
+
+namespace XCam {
+
+#if DUMP_BUFFER
+static void
+dump_buf (const SmartPtr<VideoBuffer> &buf, uint32_t idx, const char *prefix)
+{
+ XCAM_ASSERT (buf.ptr () && prefix);
+
+ char name[256];
+ snprintf (name, 256, "%s-%d", prefix, idx);
+ dump_buf_perfix_path (buf, name);
+}
+#endif
+
+namespace VKSitcherPriv {
+
+DECLARE_HANDLER_CALLBACK (CbGeoMap, VKStitcher, geomap_done);
+
+struct GeoMapParam
+ : ImageHandler::Parameters
+{
+ SmartPtr<VKStitcher::StitcherParam> stitch_param;
+ uint32_t idx;
+
+ GeoMapParam (uint32_t i)
+ : idx (i)
+ {}
+};
+
+struct Factor {
+ float x, y;
+
+ Factor () : x (1.0f), y (1.0f) {}
+ void reset () {
+ x = 1.0f;
+ y = 1.0f;
+ }
+};
+
+struct GeoMapFactors {
+ Factor left;
+ Factor right;
+};
+
+typedef std::vector<SmartPtr<VKCopyHandler>> Copiers;
+
+struct StitcherResource {
+ SmartPtr<VKBlender::Sync> blender_sync[XCAM_STITCH_MAX_CAMERAS];
+ SmartPtr<BufferPool> mapper_pool[XCAM_STITCH_MAX_CAMERAS];
+
+ SmartPtr<GeoMapParam> mapper_param[XCAM_STITCH_MAX_CAMERAS];
+ SmartPtr<VKBlender::BlenderParam> blender_param[XCAM_STITCH_MAX_CAMERAS];
+ SmartPtr<ImageHandler::Parameters> copier_param[XCAM_STITCH_MAX_CAMERAS];
+
+ SmartPtr<VKGeoMapHandler> mapper[XCAM_STITCH_MAX_CAMERAS];
+ SmartPtr<VKBlender> blender[XCAM_STITCH_MAX_CAMERAS];
+ Copiers copiers;
+
+ SmartPtr<FeatureMatch> matcher[XCAM_STITCH_MAX_CAMERAS];
+ GeoMapFactors mapper_factors[XCAM_STITCH_MAX_CAMERAS];
+
+ StitcherResource ();
+};
+
+class StitcherImpl {
+ friend class XCam::VKStitcher;
+
+public:
+ StitcherImpl (VKStitcher *handler)
+ : _stitcher (handler)
+ {}
+
+ XCamReturn init_resource ();
+
+ XCamReturn start_geo_mappers (const SmartPtr<VKStitcher::StitcherParam> &param);
+ XCamReturn start_blenders (const SmartPtr<VKStitcher::StitcherParam> &param, uint32_t idx);
+ XCamReturn start_copier (const SmartPtr<VKStitcher::StitcherParam> &param, uint32_t idx);
+ XCamReturn start_feature_match (
+ const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, uint32_t idx);
+
+ XCamReturn stop ();
+
+private:
+ SmartPtr<VKGeoMapHandler> create_geo_mapper (
+ const SmartPtr<VKDevice> &dev, const Stitcher::RoundViewSlice &view_slice);
+
+ XCamReturn init_geo_mappers (const SmartPtr<VKDevice> &dev);
+ XCamReturn init_blenders (const SmartPtr<VKDevice> &dev);
+ XCamReturn init_copiers (const SmartPtr<VKDevice> &dev);
+ void init_feature_matchers ();
+
+ void calc_geomap_factors (
+ uint32_t idx, const Factor &last_left_factor, const Factor &last_right_factor,
+ Factor &cur_left, Factor &cur_right);
+ bool update_geomap_factors (uint32_t idx);
+ XCamReturn create_geomap_pool (const SmartPtr<VKDevice> &dev, uint32_t idx);
+ XCamReturn set_geomap_table (
+ const SmartPtr<VKGeoMapHandler> &mapper, const CameraInfo &cam_info,
+ const Stitcher::RoundViewSlice &view_slice, const BowlDataConfig &bowl);
+ XCamReturn generate_geomap_table (const SmartPtr<VKGeoMapHandler> &mapper, uint32_t idx);
+
+ void update_blender_sync (uint32_t idx);
+ XCamReturn start_blender (const SmartPtr<VKStitcher::StitcherParam> &param, uint32_t idx);
+
+private:
+ StitcherResource _res;
+ VKStitcher *_stitcher;
+};
+
+StitcherResource::StitcherResource ()
+{
+}
+
+SmartPtr<VKGeoMapHandler>
+StitcherImpl::create_geo_mapper (
+ const SmartPtr<VKDevice> &dev, const Stitcher::RoundViewSlice &view_slice)
+{
+ XCAM_UNUSED (view_slice);
+
+ SmartPtr<VKGeoMapHandler> mapper;
+ if (_stitcher->get_scale_mode () == ScaleSingleConst) {
+ mapper = new VKGeoMapHandler (dev, "sitcher_singleconst_remapper");
+ } else {
+ XCAM_LOG_ERROR (
+ "vk-stitcher(%s) unsupported scale mode:%d",
+ XCAM_STR (_stitcher->get_name ()), _stitcher->get_scale_mode ());
+ }
+ XCAM_ASSERT (mapper.ptr ());
+
+ return mapper;
+}
+
+void
+StitcherImpl::update_blender_sync (uint32_t idx)
+{
+ uint32_t cam_num = _stitcher->get_camera_num ();
+ uint32_t pre_idx = (idx + cam_num - 1) % cam_num;
+
+ _res.blender_sync[pre_idx]->increment ();
+ _res.blender_sync[idx]->increment ();
+}
+
+void
+StitcherImpl::calc_geomap_factors (
+ uint32_t idx, const Factor &last_left_factor, const Factor &last_right_factor,
+ Factor &cur_left, Factor &cur_right)
+{
+ const Factor &fm_left_factor = _res.mapper_factors[idx].left;
+ const Factor &fm_right_factor = _res.mapper_factors[idx].right;
+
+ cur_left.x = last_left_factor.x * fm_left_factor.x;
+ cur_left.y = last_left_factor.y * fm_left_factor.y;
+ cur_right.x = last_right_factor.x * fm_right_factor.x;
+ cur_right.y = last_right_factor.y * fm_right_factor.y;
+
+ _res.mapper_factors[idx].left.reset ();
+ _res.mapper_factors[idx].right.reset ();
+}
+
+bool
+StitcherImpl::update_geomap_factors (uint32_t idx)
+{
+ SmartPtr<VKGeoMapHandler> &mapper = _res.mapper[idx];
+ XCAM_FAIL_RETURN (
+ ERROR, mapper.ptr (), false,
+ "vk-stitcher(%s) geomap handler is empty, idx:%d", XCAM_STR (_stitcher->get_name ()), idx);
+
+ if (_stitcher->get_scale_mode () == ScaleSingleConst) {
+ Factor unify_factor, cur_left, cur_right;
+
+ mapper->get_factors (unify_factor.x, unify_factor.y);
+ if (XCAM_DOUBLE_EQUAL_AROUND (unify_factor.x, 0.0f) ||
+ XCAM_DOUBLE_EQUAL_AROUND (unify_factor.y, 0.0f)) { // not started.
+ return true;
+ }
+
+ calc_geomap_factors (idx, unify_factor, unify_factor, cur_left, cur_right);
+ unify_factor.x = (cur_left.x + cur_right.x) / 2.0f;
+ unify_factor.y = (cur_left.y + cur_right.y) / 2.0f;
+
+ mapper->set_factors (unify_factor.x, unify_factor.y);
+ } else {
+ XCAM_LOG_ERROR (
+ "vk-stitcher(%s) unsupported scale mode:%d",
+ XCAM_STR (_stitcher->get_name ()), _stitcher->get_scale_mode ());
+ return false;
+ }
+
+ return true;
+}
+
+XCamReturn
+StitcherImpl::create_geomap_pool (const SmartPtr<VKDevice> &dev, uint32_t idx)
+{
+ uint32_t output_width, output_height;
+ _res.mapper[idx]->get_output_size (output_width, output_height);
+
+ VideoBufferInfo out_info;
+ out_info.init (
+ V4L2_PIX_FMT_NV12, output_width, output_height,
+ XCAM_ALIGN_UP (output_width, VK_STITCHER_ALIGNMENT_X),
+ XCAM_ALIGN_UP (output_height, VK_STITCHER_ALIGNMENT_Y));
+
+ SmartPtr<BufferPool> pool = create_vk_buffer_pool (dev);
+ XCAM_ASSERT (pool.ptr ());
+ XCAM_FAIL_RETURN (
+ ERROR, pool->set_video_info (out_info) && pool->reserve (GEOMAP_POOL_SIZE),
+ XCAM_RETURN_ERROR_MEM,
+ "vk-stitcher(%s) create buffer pool failed, buffer size:%dx%d, idx:%d",
+ XCAM_STR (_stitcher->get_name ()), out_info.width, out_info.height, idx);
+
+ _res.mapper_pool[idx] = pool;
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::set_geomap_table (
+ const SmartPtr<VKGeoMapHandler> &mapper, const CameraInfo &cam_info,
+ const Stitcher::RoundViewSlice &view_slice, const BowlDataConfig &bowl)
+{
+ PolyFisheyeDewarp fd;
+ fd.set_intrinsic_param (cam_info.calibration.intrinsic);
+ fd.set_extrinsic_param (cam_info.calibration.extrinsic);
+
+ uint32_t table_width, table_height;
+ table_width = view_slice.width / MAP_FACTOR_X;
+ table_height = view_slice.height / MAP_FACTOR_Y;
+
+ SurViewFisheyeDewarp::MapTable map_table (table_width * table_height);
+ fd.fisheye_dewarp (
+ map_table, table_width, table_height,
+ view_slice.width, view_slice.height, bowl);
+
+ bool ret = mapper->set_lookup_table (map_table.data (), table_width, table_height);
+ XCAM_FAIL_RETURN (
+ ERROR, ret, XCAM_RETURN_ERROR_UNKNOWN,
+ "vk-stitcher(%s) set geomap lookup table failed", XCAM_STR (_stitcher->get_name ()));
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::generate_geomap_table (
+ const SmartPtr<VKGeoMapHandler> &mapper, uint32_t idx)
+{
+ CameraInfo cam_info;
+ _stitcher->get_camera_info (idx, cam_info);
+ Stitcher::RoundViewSlice view_slice = _stitcher->get_round_view_slice (idx);
+
+ BowlDataConfig bowl = _stitcher->get_bowl_config ();
+ bowl.angle_start = view_slice.hori_angle_start;
+ bowl.angle_end = format_angle (view_slice.hori_angle_start + view_slice.hori_angle_range);
+ if (bowl.angle_end < bowl.angle_start)
+ bowl.angle_start -= 360.0f;
+
+ XCAM_LOG_DEBUG (
+ "vk-stitcher(%s) camera(idx:%d) info(angle start:%.2f, range:%.2f), bowl info(angle start:%.2f, end:%.2f)",
+ XCAM_STR (_stitcher->get_name ()), idx,
+ view_slice.hori_angle_start, view_slice.hori_angle_range,
+ bowl.angle_start, bowl.angle_end);
+
+ XCamReturn ret = set_geomap_table (mapper, cam_info, view_slice, bowl);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) set geometry map table failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::init_geo_mappers (const SmartPtr<VKDevice> &dev)
+{
+ uint32_t cam_num = _stitcher->get_camera_num ();
+ SmartPtr<ImageHandler::Callback> cb = new CbGeoMap (_stitcher);
+
+ for (uint32_t idx = 0; idx < cam_num; ++idx) {
+ Stitcher::RoundViewSlice view_slice = _stitcher->get_round_view_slice (idx);
+
+ SmartPtr<VKGeoMapHandler> &mapper = _res.mapper[idx];
+ mapper = create_geo_mapper (dev, view_slice);
+ mapper->set_callback (cb);
+ mapper->set_output_size (view_slice.width, view_slice.height);
+
+ create_geomap_pool (dev, idx);
+
+ SmartPtr<GeoMapParam> &mapper_param = _res.mapper_param[idx];
+ mapper_param = new GeoMapParam (idx);
+ XCAM_ASSERT (mapper_param.ptr ());
+
+ mapper_param->out_buf = _res.mapper_pool[idx]->get_buffer ();
+ XCAM_ASSERT (mapper_param->out_buf.ptr ());
+
+ XCamReturn ret = generate_geomap_table (mapper, idx);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) generate geomap table failed", XCAM_STR (_stitcher->get_name ()));
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::init_blenders (const SmartPtr<VKDevice> &dev)
+{
+ uint32_t out_width, out_height;
+ _stitcher->get_output_size (out_width, out_height);
+ uint32_t cam_num = _stitcher->get_camera_num ();
+
+ for (uint32_t idx = 0; idx < cam_num; ++idx) {
+ SmartPtr<VKBlender> &blender = _res.blender[idx];
+ blender = create_vk_blender (dev).dynamic_cast_ptr<VKBlender> ();
+ XCAM_ASSERT (blender.ptr ());
+
+ const Stitcher::ImageOverlapInfo &overlap = _stitcher->get_overlap (idx);
+ blender->set_output_size (out_width, out_height);
+ blender->set_merge_window (overlap.out_area);
+ blender->set_input_valid_area (overlap.left, 0);
+ blender->set_input_valid_area (overlap.right, 1);
+ blender->set_input_merge_area (overlap.left, 0);
+ blender->set_input_merge_area (overlap.right, 1);
+
+ SmartPtr<VKBlender::BlenderParam> &blender_param = _res.blender_param[idx];
+ blender_param = new VKBlender::BlenderParam (NULL, NULL, NULL);
+ XCAM_ASSERT (blender_param.ptr ());
+
+ uint32_t next_idx = (idx + 1) % cam_num;
+ blender_param->in_buf = _res.mapper_param[idx]->out_buf;
+ blender_param->in1_buf = _res.mapper_param[next_idx]->out_buf;
+ XCAM_ASSERT (blender_param->in_buf.ptr () && blender_param->in1_buf.ptr ());
+
+ _res.blender_sync[idx] = new VKBlender::Sync (2);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::init_copiers (const SmartPtr<VKDevice> &dev)
+{
+ uint32_t cam_num = _stitcher->get_camera_num ();
+ for (uint32_t idx = 0; idx < cam_num; ++idx) {
+ SmartPtr<ImageHandler::Parameters> &copier_param = _res.copier_param[idx];
+ copier_param = new ImageHandler::Parameters ();
+ XCAM_ASSERT (copier_param.ptr ());
+
+ copier_param->in_buf = _res.mapper_param[idx]->out_buf;
+ XCAM_ASSERT (copier_param->in_buf.ptr ());
+ }
+
+ Stitcher::CopyAreaArray areas = _stitcher->get_copy_area ();
+ uint32_t size = areas.size ();
+ for (uint32_t idx = 0; idx < size; ++idx) {
+ XCAM_ASSERT (areas[idx].in_idx < size);
+
+ SmartPtr<VKCopyHandler> copier = new VKCopyHandler (dev);
+ XCAM_ASSERT (copier.ptr ());
+ copier->enable_allocator (false);
+ copier->set_copy_area (areas[idx].in_idx, areas[idx].in_area, areas[idx].out_area);
+
+ _res.copiers.push_back (copier);
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+void
+StitcherImpl::init_feature_matchers ()
+{
+#if HAVE_OPENCV
+ FeatureMatchMode fm_mode = _stitcher->get_fm_mode ();
+ if (fm_mode == FMNone)
+ return ;
+
+ uint32_t cam_num = _stitcher->get_camera_num ();
+ for (uint32_t idx = 0; idx < cam_num; ++idx) {
+ SmartPtr<FeatureMatch> &matcher = _res.matcher[idx];
+#ifndef ANDROID
+ if (fm_mode == FMDefault)
+ matcher = FeatureMatch::create_default_feature_match ();
+ else if (fm_mode == FMCluster)
+ matcher = FeatureMatch::create_cluster_feature_match ();
+ else if (fm_mode == FMCapi)
+ matcher = FeatureMatch::create_capi_feature_match ();
+ else {
+ XCAM_LOG_ERROR (
+ "vk-stitcher(%s) unsupported FeatureMatchMode: %d",
+ XCAM_STR (_stitcher->get_name ()), fm_mode);
+ }
+#else
+ matcher = FeatureMatch::create_capi_feature_match ();
+#endif
+ XCAM_ASSERT (matcher.ptr ());
+
+ FMConfig config;
+ config.sitch_min_width = 136;
+ config.min_corners = 4;
+ config.offset_factor = 0.8f;
+ config.delta_mean_offset = 120.0f;
+ config.recur_offset_error = 8.0f;
+ config.max_adjusted_offset = 24.0f;
+ config.max_valid_offset_y = 20.0f;
+ config.max_track_error = 28.0f;
+#ifdef ANDROID
+ config.max_track_error = 3600.0f;
+#endif
+ matcher->set_config (config);
+ matcher->set_fm_index (idx);
+
+ const BowlDataConfig bowl = _stitcher->get_bowl_config ();
+ const Stitcher::ImageOverlapInfo &info = _stitcher->get_overlap (idx);
+ Rect left_ovlap = info.left;
+ Rect right_ovlap = info.right;
+ left_ovlap.pos_y = 0;
+ left_ovlap.height = int32_t (bowl.wall_height / (bowl.wall_height + bowl.ground_length) * left_ovlap.height);
+ right_ovlap.pos_y = 0;
+ right_ovlap.height = left_ovlap.height;
+ matcher->set_crop_rect (left_ovlap, right_ovlap);
+ }
+#else
+ XCAM_LOG_ERROR ("vk-stitcher(%s) feature match is unsupported", XCAM_STR (_stitcher->get_name ()));
+ XCAM_ASSERT (false);
+#endif
+}
+
+XCamReturn
+StitcherImpl::init_resource ()
+{
+ const SmartPtr<VKDevice> &dev = _stitcher->get_vk_device ();
+ XCAM_ASSERT (dev.ptr ());
+
+ XCamReturn ret = init_geo_mappers (dev);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) init dewarps failed", XCAM_STR (_stitcher->get_name ()));
+
+#if HAVE_OPENCV
+ init_feature_matchers ();
+#endif
+
+ ret = init_blenders (dev);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) init blenders failed", XCAM_STR (_stitcher->get_name ()));
+
+ ret = init_copiers (dev);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) init copiers failed", XCAM_STR (_stitcher->get_name ()));
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::start_geo_mappers (const SmartPtr<VKStitcher::StitcherParam> &param)
+{
+ uint32_t cam_num = _stitcher->get_camera_num ();
+
+ for (uint32_t idx = 0; idx < cam_num; ++idx) {
+ if (_stitcher->get_fm_mode ())
+ update_geomap_factors (idx);
+
+ SmartPtr<GeoMapParam> &mapper_param = _res.mapper_param[idx];
+ mapper_param->in_buf = param->in_bufs[idx];
+ mapper_param->stitch_param = param;
+
+ XCamReturn ret = _res.mapper[idx]->execute_buffer (mapper_param, false);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) execute geo mapper failed, idx:%d",
+ XCAM_STR (_stitcher->get_name ()), idx);
+
+#if DUMP_BUFFER
+ dump_buf (mapper_param->out_buf, idx, "stitcher-geomap");
+#endif
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::start_feature_match (
+ const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, uint32_t idx)
+{
+#if HAVE_OPENCV
+ _res.matcher[idx]->reset_offsets ();
+ _res.matcher[idx]->feature_match (left_buf, right_buf);
+
+ Rect left_ovlap, right_ovlap;
+ _res.matcher[idx]->get_crop_rect (left_ovlap, right_ovlap);
+ float left_offsetx = _res.matcher[idx]->get_current_left_offset_x ();
+
+ uint32_t left_idx = idx;
+ Factor left_factor, right_factor;
+ float center_x = (float) _stitcher->get_center (left_idx).slice_center_x;
+ float feature_center_x = (float)left_ovlap.pos_x + (left_ovlap.width / 2.0f);
+ float range = feature_center_x - center_x;
+ XCAM_ASSERT (range > 1.0f);
+ right_factor.x = (range + left_offsetx / 2.0f) / range;
+ right_factor.y = 1.0f;
+ XCAM_ASSERT (right_factor.x > 0.0f && right_factor.x < 2.0f);
+
+ uint32_t right_idx = (idx + 1) % _stitcher->get_camera_num ();
+ center_x = (float) _stitcher->get_center (right_idx).slice_center_x;
+ feature_center_x = (float)right_ovlap.pos_x + (right_ovlap.width / 2.0f);
+ range = center_x - feature_center_x;
+ XCAM_ASSERT (range > 1.0f);
+ left_factor.x = (range + left_offsetx / 2.0f) / range;
+ left_factor.y = 1.0f;
+ XCAM_ASSERT (left_factor.x > 0.0f && left_factor.x < 2.0f);
+
+ _res.mapper_factors[left_idx].right = right_factor;
+ _res.mapper_factors[right_idx].left = left_factor;
+
+ return XCAM_RETURN_NO_ERROR;
+#else
+ XCAM_LOG_ERROR ("vk-stitcher(%s) feature match is unsupported", XCAM_STR (_stitcher->get_name ()));
+ return XCAM_RETURN_ERROR_PARAM;
+#endif
+}
+
+XCamReturn
+StitcherImpl::start_blender (
+ const SmartPtr<VKStitcher::StitcherParam> &param, uint32_t idx)
+{
+ SmartPtr<VKBlender::Sync> &sync = _res.blender_sync[idx];
+ if (!sync->is_synced ())
+ return XCAM_RETURN_NO_ERROR;
+ sync->reset ();
+
+ SmartPtr<VKBlender::BlenderParam> &blend_param = _res.blender_param[idx];
+ blend_param->out_buf = param->out_buf;
+
+ XCamReturn ret = _res.blender[idx]->execute_buffer (blend_param, false);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) execute blender failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx);
+
+#if DUMP_BUFFER
+ dump_buf (param->out_buf, idx, "stitcher-blend");
+#endif
+
+#if HAVE_OPENCV
+ if (_stitcher->get_fm_mode ()) {
+ ret = start_feature_match (blend_param->in_buf, blend_param->in1_buf, idx);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) start feature match failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx);
+ }
+#endif
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::start_blenders (const SmartPtr<VKStitcher::StitcherParam> &param, uint32_t idx)
+{
+ uint32_t cam_num = _stitcher->get_camera_num ();
+ uint32_t pre_idx = (idx + cam_num - 1) % cam_num;
+
+ XCamReturn ret = start_blender (param, pre_idx);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) start blender failed, idx:%d", XCAM_STR (_stitcher->get_name ()), pre_idx);
+
+ ret = start_blender (param, idx);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) start blender failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::start_copier (
+ const SmartPtr<VKStitcher::StitcherParam> &param, uint32_t idx)
+{
+ uint32_t size = _stitcher->get_copy_area ().size ();
+
+ for (uint32_t i = 0; i < size; ++i) {
+ if(_res.copiers[i]->get_index () != idx)
+ continue;
+
+ SmartPtr<ImageHandler::Parameters> &copy_param = _res.copier_param[idx];
+ copy_param->out_buf = param->out_buf;
+
+ XCamReturn ret = _res.copiers[i]->execute_buffer (copy_param, false);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) execute copier failed, i:%d idx:%d",
+ XCAM_STR (_stitcher->get_name ()), i, idx);
+
+#if DUMP_BUFFER
+ dump_buf (copy_param->out_buf, i, "stitcher-copy");
+#endif
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+StitcherImpl::stop ()
+{
+ uint32_t cam_num = _stitcher->get_camera_num ();
+ for (uint32_t i = 0; i < cam_num; ++i) {
+ if (_res.mapper[i].ptr ()) {
+ _res.mapper[i]->terminate ();
+ _res.mapper[i].release ();
+ }
+ if (_res.mapper_pool[i].ptr ()) {
+ _res.mapper_pool[i]->stop ();
+ }
+
+ if (_res.blender[i].ptr ()) {
+ _res.blender[i]->terminate ();
+ _res.blender[i].release ();
+ }
+ }
+
+ for (Copiers::iterator i = _res.copiers.begin (); i != _res.copiers.end (); ++i) {
+ SmartPtr<VKCopyHandler> &copier = *i;
+ if (copier.ptr ()) {
+ copier->terminate ();
+ copier.release ();
+ }
+ }
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+};
+
+VKStitcher::VKStitcher (const SmartPtr<VKDevice> &dev, const char *name)
+ : VKHandler (dev, name)
+ , Stitcher (VK_STITCHER_ALIGNMENT_X, VK_STITCHER_ALIGNMENT_X)
+{
+ SmartPtr<VKSitcherPriv::StitcherImpl> impl = new VKSitcherPriv::StitcherImpl (this);
+ XCAM_ASSERT (impl.ptr ());
+ _impl = impl;
+}
+
+VKStitcher::~VKStitcher ()
+{
+ _impl.release ();
+}
+
+XCamReturn
+VKStitcher::terminate ()
+{
+ _impl->stop ();
+ return VKHandler::terminate ();
+}
+
+XCamReturn
+VKStitcher::stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, !in_bufs.empty (), XCAM_RETURN_ERROR_PARAM,
+ "vk-stitcher(%s) input buffers is empty", XCAM_STR (get_name ()));
+
+ SmartPtr<StitcherParam> param = new StitcherParam ();
+ XCAM_ASSERT (param.ptr ());
+
+ uint32_t buf_num = 0;
+ for (VideoBufferList::const_iterator iter = in_bufs.begin(); iter != in_bufs.end (); ++iter) {
+ XCAM_ASSERT ((*iter).ptr ());
+ param->in_bufs[buf_num++] = *iter;
+ }
+ param->in_buf_num = buf_num;
+ param->out_buf = out_buf;
+
+ XCamReturn ret = execute_buffer (param, false);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) execute buffer failed", XCAM_STR (get_name ()));
+
+ finish ();
+ if (!out_buf.ptr ()) {
+ out_buf = param->out_buf;
+ }
+
+ return ret;
+}
+
+XCamReturn
+VKStitcher::configure_resource (const SmartPtr<Parameters> &param)
+{
+ XCAM_UNUSED (param);
+ XCAM_ASSERT (_impl.ptr ());
+
+ XCamReturn ret = estimate_round_slices ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) estimate round view slices failed", XCAM_STR (get_name ()));
+
+ ret = estimate_coarse_crops ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) estimate coarse crops failed", XCAM_STR (get_name ()));
+
+ ret = mark_centers ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) mark centers failed", XCAM_STR (get_name ()));
+
+ ret = estimate_overlap ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) estimake coarse overlap failed", XCAM_STR (get_name ()));
+
+ ret = update_copy_areas ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) update copy areas failed", XCAM_STR (get_name ()));
+
+ ret = _impl->init_resource ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk-stitcher(%s) initialize private config failed", XCAM_STR (get_name ()));
+
+ VideoBufferInfo out_info;
+ uint32_t out_width, out_height;
+ get_output_size (out_width, out_height);
+ XCAM_FAIL_RETURN (
+ ERROR, out_width && out_height, XCAM_RETURN_ERROR_PARAM,
+ "vk-stitcher(%s) output size was not set", XCAM_STR (get_name ()));
+
+ out_info.init (
+ V4L2_PIX_FMT_NV12, out_width, out_height,
+ XCAM_ALIGN_UP (out_width, VK_STITCHER_ALIGNMENT_X),
+ XCAM_ALIGN_UP (out_height, VK_STITCHER_ALIGNMENT_Y));
+ set_out_video_info (out_info);
+
+ return ret;
+}
+
+XCamReturn
+VKStitcher::start_work (const SmartPtr<Parameters> &base)
+{
+ XCAM_ASSERT (base.ptr ());
+
+ SmartPtr<StitcherParam> param = base.dynamic_cast_ptr<StitcherParam> ();
+ XCAM_ASSERT (param.ptr () && param->in_buf_num > 0);
+
+ XCamReturn ret = _impl->start_geo_mappers (param);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_PARAM,
+ "vk_stitcher(%s) start geometry map failed", XCAM_STR (get_name ()));
+
+ return ret;
+}
+
+void
+VKStitcher::geomap_done (
+ const SmartPtr<ImageHandler> &handler,
+ const SmartPtr<ImageHandler::Parameters> &base, const XCamReturn error)
+{
+ XCAM_UNUSED (handler);
+ XCAM_UNUSED (error);
+
+ SmartPtr<VKSitcherPriv::GeoMapParam> param = base.dynamic_cast_ptr<VKSitcherPriv::GeoMapParam> ();
+ XCAM_ASSERT (param.ptr ());
+ SmartPtr<VKStitcher::StitcherParam> &stitch_param = param->stitch_param;
+ XCAM_ASSERT (stitch_param.ptr ());
+
+ _impl->update_blender_sync (param->idx);
+
+ XCamReturn ret = _impl->start_blenders (stitch_param, param->idx);
+ CHECK_RET (ret, "vk-stitcher(%s) start blenders failed, idx:%d", XCAM_STR (get_name ()), param->idx);
+
+ ret = _impl->start_copier (stitch_param, param->idx);
+ CHECK_RET (ret, "vk-stitcher(%s) start copier failed, idx:%d", XCAM_STR (get_name ()), param->idx);
+}
+
+SmartPtr<Stitcher>
+Stitcher::create_vk_stitcher (const SmartPtr<VKDevice> dev)
+{
+ return new VKStitcher (dev);
+}
+
+}
diff --git a/modules/vulkan/vk_stitcher.h b/modules/vulkan/vk_stitcher.h
new file mode 100644
index 0000000..c59f013
--- /dev/null
+++ b/modules/vulkan/vk_stitcher.h
@@ -0,0 +1,80 @@
+/*
+ * vk_stitcher.h - Vulkan stitcher class
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Yinhang Liu <yinhangx.liu@intel.com>
+ */
+
+#ifndef XCAM_VK_STITCHER_H
+#define XCAM_VK_STITCHER_H
+
+#include <interface/stitcher.h>
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_handler.h>
+
+namespace XCam {
+
+namespace VKSitcherPriv {
+class StitcherImpl;
+class CbGeoMap;
+};
+
+class VKStitcher
+ : public VKHandler
+ , public Stitcher
+{
+ friend class VKSitcherPriv::StitcherImpl;
+ friend class VKSitcherPriv::CbGeoMap;
+
+public:
+ struct StitcherParam
+ : ImageHandler::Parameters
+ {
+ uint32_t in_buf_num;
+ SmartPtr<VideoBuffer> in_bufs[XCAM_STITCH_MAX_CAMERAS];
+
+ StitcherParam ()
+ : Parameters (NULL, NULL)
+ , in_buf_num (0)
+ {}
+ };
+
+public:
+ explicit VKStitcher (const SmartPtr<VKDevice> &dev, const char *name = "VKStitcher");
+ ~VKStitcher ();
+
+ // derived from VKHandler
+ virtual XCamReturn terminate ();
+
+protected:
+ // interface derive from Stitcher
+ XCamReturn stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf);
+
+ // derived from VKHandler
+ XCamReturn configure_resource (const SmartPtr<Parameters> &param);
+ XCamReturn start_work (const SmartPtr<Parameters> &param);
+
+private:
+ void geomap_done (
+ const SmartPtr<ImageHandler> &handler,
+ const SmartPtr<ImageHandler::Parameters> &param, const XCamReturn error);
+
+private:
+ SmartPtr<VKSitcherPriv::StitcherImpl> _impl;
+};
+
+}
+#endif // XCAM_VK_STITCHER_H
diff --git a/modules/vulkan/vk_sync.cpp b/modules/vulkan/vk_sync.cpp
new file mode 100644
index 0000000..f5ea6c6
--- /dev/null
+++ b/modules/vulkan/vk_sync.cpp
@@ -0,0 +1,55 @@
+/*
+ * vk_sync.cpp - Vulkan sync
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_sync.h"
+#include "vk_device.h"
+
+namespace XCam {
+
+VKFence::~VKFence ()
+{
+ if (_dev.ptr () && XCAM_IS_VALID_VK_ID (_fence_id))
+ _dev->destroy_fence (_fence_id);
+}
+
+VKFence::VKFence (const SmartPtr<VKDevice> dev, VkFence id)
+ : _fence_id (id)
+ , _dev (dev)
+{
+}
+
+XCamReturn
+VKFence::reset ()
+{
+ XCAM_ASSERT (_dev.ptr ());
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_fence_id));
+
+ return _dev->reset_fence (_fence_id);
+}
+
+XCamReturn
+VKFence::wait (uint64_t timeout)
+{
+ XCAM_ASSERT (_dev.ptr ());
+ XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_fence_id));
+ return _dev->wait_for_fence (_fence_id, timeout);
+}
+
+}
diff --git a/modules/vulkan/vk_sync.h b/modules/vulkan/vk_sync.h
new file mode 100644
index 0000000..e2a7d34
--- /dev/null
+++ b/modules/vulkan/vk_sync.h
@@ -0,0 +1,56 @@
+/*
+ * vk_sync.h - Vulkan sync
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_SYNC_H
+#define XCAM_VK_SYNC_H
+
+#include <vulkan/vulkan_std.h>
+
+namespace XCam {
+
+class VKDevice;
+
+class VKFence
+{
+ friend class VKDevice;
+public:
+ virtual ~VKFence ();
+
+ XCamReturn reset ();
+ XCamReturn wait (uint64_t timeout = UINT64_MAX);
+
+ VkFence get_fence_id () const {
+ return _fence_id;
+ }
+
+protected:
+ explicit VKFence (const SmartPtr<VKDevice> dev, VkFence id);
+
+private:
+ XCAM_DEAD_COPY (VKFence);
+
+protected:
+ VkFence _fence_id;
+ SmartPtr<VKDevice> _dev;
+};
+
+}
+
+#endif //XCAM_VK_SYNC_H
diff --git a/modules/vulkan/vk_video_buf_allocator.cpp b/modules/vulkan/vk_video_buf_allocator.cpp
new file mode 100644
index 0000000..c60476a
--- /dev/null
+++ b/modules/vulkan/vk_video_buf_allocator.cpp
@@ -0,0 +1,164 @@
+/*
+ * vk_video_buf_allocator.cpp - vulkan video buffer allocator implementation
+ *
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_video_buf_allocator.h"
+#include "vk_memory.h"
+#include "vk_device.h"
+
+namespace XCam {
+
+class VKVideoData
+ : public BufferData
+{
+ friend class VKVideoBuffer;
+public:
+ explicit VKVideoData (const SmartPtr<VKBuffer> vk_buf);
+ virtual ~VKVideoData ();
+
+ //derive from BufferData
+ virtual uint8_t *map ();
+ virtual bool unmap ();
+
+ bool is_valid ();
+
+private:
+ uint8_t *_mem_ptr;
+ SmartPtr<VKBuffer> _vk_buf;
+};
+
+VKVideoData::VKVideoData (const SmartPtr<VKBuffer> vk_buf)
+ : _mem_ptr (NULL)
+ , _vk_buf (vk_buf)
+{
+ XCAM_ASSERT (vk_buf.ptr ());
+}
+
+VKVideoData::~VKVideoData ()
+{
+}
+
+bool
+VKVideoData::is_valid ()
+{
+ return _vk_buf.ptr () && XCAM_IS_VALID_VK_ID (_vk_buf->get_buf_id ());
+}
+
+uint8_t *
+VKVideoData::map ()
+{
+ if (!_mem_ptr) {
+ _mem_ptr = (uint8_t *)_vk_buf->map ();
+ }
+ return _mem_ptr;
+}
+
+bool
+VKVideoData::unmap ()
+{
+ if (!_mem_ptr)
+ return false;
+
+ _mem_ptr = NULL;
+ _vk_buf->unmap ();
+ return true;
+}
+
+VKVideoBufAllocator::VKVideoBufAllocator (const SmartPtr<VKDevice> dev)
+ : _dev (dev)
+{
+}
+
+VKVideoBufAllocator::~VKVideoBufAllocator ()
+{
+}
+
+SmartPtr<BufferData>
+VKVideoBufAllocator::allocate_data (const VideoBufferInfo &buffer_info)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, buffer_info.size, NULL,
+ "VKVideoBufAllocator allocate data failed. buf_size is zero");
+
+ SmartPtr<VKBuffer> vk_buf =
+ VKBuffer::create_buffer (_dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, buffer_info.size);
+
+ XCAM_FAIL_RETURN (
+ ERROR, vk_buf.ptr (), NULL,
+ "VKVideoBufAllocator create vk memory failed. buf_size :%d", buffer_info.size);
+
+ VKBufInfo info;
+ info.format = buffer_info.format;
+ info.width = buffer_info.width;
+ info.height = buffer_info.height;
+ info.aligned_width = buffer_info.aligned_width;
+ info.aligned_height = buffer_info.aligned_height;
+ info.size = buffer_info.size;
+ info.strides[0] = buffer_info.strides[0];
+ info.strides[1] = buffer_info.strides[1];
+ info.offsets[0] = buffer_info.offsets[0];
+ info.offsets[1] = buffer_info.offsets[1];
+ info.slice_size[0] = buffer_info.strides[0] * buffer_info.aligned_height;
+ info.slice_size[1] = buffer_info.size - buffer_info.offsets[1];
+ vk_buf->set_buf_info (info);
+
+ SmartPtr<VKVideoData> data = new VKVideoData (vk_buf);
+ XCAM_FAIL_RETURN (
+ ERROR, data.ptr () && data->is_valid (), NULL,
+ "VKVideoBufAllocator allocate data failed. buf_size:%d", buffer_info.size);
+
+ return data;
+}
+
+SmartPtr<BufferProxy>
+VKVideoBufAllocator::create_buffer_from_data (SmartPtr<BufferData> &data)
+{
+ const VideoBufferInfo &info = get_video_info ();
+
+ XCAM_ASSERT (data.ptr ());
+ return new VKVideoBuffer (info, data);
+}
+
+VKVideoBuffer::VKVideoBuffer (const VideoBufferInfo &info, const SmartPtr<BufferData> &data)
+ : BufferProxy (info, data)
+{
+}
+
+SmartPtr<VKBuffer>
+VKVideoBuffer::get_vk_buf ()
+{
+ SmartPtr<BufferData> data = get_buffer_data ();
+ SmartPtr<VKVideoData> vk_data = data.dynamic_cast_ptr<VKVideoData> ();
+ XCAM_FAIL_RETURN (
+ ERROR, vk_data.ptr () && vk_data->_vk_buf.ptr (), VK_NULL_HANDLE,
+ "VKVideoBuffer get buf_id failed, data is empty");
+
+ return vk_data->_vk_buf;
+}
+
+SmartPtr<BufferPool>
+create_vk_buffer_pool (const SmartPtr<VKDevice> &dev)
+{
+ XCAM_FAIL_RETURN (
+ ERROR, dev.ptr () && XCAM_IS_VALID_VK_ID(dev->get_dev_id()), NULL,
+ "create_vk_buffer_pool failed since vk device is invalid");
+ return new VKVideoBufAllocator (dev);
+}
+
+}
diff --git a/modules/vulkan/vk_video_buf_allocator.h b/modules/vulkan/vk_video_buf_allocator.h
new file mode 100644
index 0000000..af56f94
--- /dev/null
+++ b/modules/vulkan/vk_video_buf_allocator.h
@@ -0,0 +1,58 @@
+/*
+ * vk_video_buf_allocator.h - vulkan video buffer allocator class
+ *
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_VIDEO_BUF_ALLOCATOR_H
+#define XCAM_VK_VIDEO_BUF_ALLOCATOR_H
+
+#include <buffer_pool.h>
+
+namespace XCam {
+
+class VKDevice;
+class VKBuffer;
+
+class VKVideoBufAllocator
+ : public BufferPool
+{
+public:
+ explicit VKVideoBufAllocator (const SmartPtr<VKDevice> dev);
+ virtual ~VKVideoBufAllocator ();
+
+private:
+ //derive from BufferPool
+ virtual SmartPtr<BufferData> allocate_data (const VideoBufferInfo &buffer_info);
+ virtual SmartPtr<BufferProxy> create_buffer_from_data (SmartPtr<BufferData> &data);
+
+private:
+ SmartPtr<VKDevice> _dev;
+};
+
+class VKVideoBuffer
+ : public BufferProxy
+{
+public:
+ explicit VKVideoBuffer (const VideoBufferInfo &info, const SmartPtr<BufferData> &data);
+ SmartPtr<VKBuffer> get_vk_buf ();
+};
+
+}
+
+#endif //XCAM_VK_VIDEO_BUF_ALLOCATOR_H
+
diff --git a/modules/vulkan/vk_worker.cpp b/modules/vulkan/vk_worker.cpp
new file mode 100644
index 0000000..f40a81a
--- /dev/null
+++ b/modules/vulkan/vk_worker.cpp
@@ -0,0 +1,218 @@
+/*
+ * vk_worker.cpp - vulkan worker class
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vk_worker.h"
+#include "vk_sync.h"
+#include "vk_pipeline.h"
+#include "vk_cmdbuf.h"
+#include "vk_device.h"
+#include "vulkan_common.h"
+
+namespace XCam {
+
+XCamReturn
+VKWorker::VKArguments::prepare_bindings (
+ VKDescriptor::SetBindInfoArray &binding_array,
+ VKConstRange::VKPushConstArgs &push_consts)
+{
+ XCAM_ASSERT (_binding_bufs.size ());
+ XCAM_FAIL_RETURN (
+ ERROR, _binding_bufs.size (), XCAM_RETURN_ERROR_PARAM,
+ "VKArguments found bindings empty, please check settings or derive interface prepare_bindings");
+
+ binding_array = _binding_bufs;
+ push_consts = _push_consts;
+ return XCAM_RETURN_NO_ERROR;
+}
+
+bool
+VKWorker::VKArguments::set_bindings (const VKDescriptor::SetBindInfoArray &arr)
+{
+ _binding_bufs = arr;
+ return true;
+}
+
+bool
+VKWorker::VKArguments::add_binding (const VKDescriptor::SetBindInfo &info)
+{
+ _binding_bufs.push_back (info);
+ return true;
+}
+
+bool
+VKWorker::VKArguments::add_push_const (const SmartPtr<VKConstRange::VKPushConstArg> &push_const)
+{
+ _push_consts.push_back (push_const);
+ return true;
+}
+
+VKWorker::VKWorker (SmartPtr<VKDevice> dev, const char *name, const SmartPtr<Callback> &cb)
+ : Worker (name, cb)
+ , _device (dev)
+{
+}
+
+VKWorker::~VKWorker ()
+{
+}
+
+XCamReturn
+VKWorker::build (
+ const VKShaderInfo &info,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKPushConstArgs &consts)
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ XCAM_FAIL_RETURN (
+ ERROR, _device.ptr (), XCAM_RETURN_ERROR_VULKAN,
+ "vk woker(%s) build failed since vk_device is null.", XCAM_STR (get_name ()));
+
+ SmartPtr<VKShader> shader;
+ if (info.type == VKSahderInfoSpirVPath) {
+ const char *dir_env = std::getenv (XCAM_VK_SHADER_PATH);
+ std::string vk_dir (dir_env, (dir_env ? strlen (dir_env) : 0));
+ if (vk_dir.empty () || !vk_dir.length())
+ vk_dir = XCAM_DEFAULT_VK_SHADER_PATH;
+ std::string spirv_path = vk_dir + "/" + info.spirv_path;
+ shader = _device->create_shader (spirv_path.c_str ());
+ } else if (info.type == VKSahderInfoSpirVBinary) {
+ shader = _device->create_shader (info.spirv_bin);
+ }
+ XCAM_FAIL_RETURN (
+ ERROR, shader.ptr (), XCAM_RETURN_ERROR_VULKAN,
+ "vk woker(%s) build failed when creating shader.", XCAM_STR (get_name ()));
+ shader->set_func_name (info.func_name.c_str ());
+
+ _desc_pool = new VKDescriptor::Pool (_device);
+ XCAM_ASSERT (_desc_pool.ptr ());
+ XCAM_FAIL_RETURN (
+ ERROR, _desc_pool->add_set_bindings (bindings), XCAM_RETURN_ERROR_VULKAN,
+ "vk woker(%s) build failed to add bindings to desc_pool", XCAM_STR (get_name ()));
+ ret = _desc_pool->create ();
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk woker(%s) build failed to craete bindings in desc_pool", XCAM_STR (get_name ()));
+
+ VKConstRange::VKConstantArray const_array;
+ for (size_t i = 0; i < consts.size(); ++i) {
+ VkPushConstantRange data_const = {0, 0, 0};
+ void *ptr = NULL;
+ consts[i]->get_const_data (data_const, ptr);
+ const_array.push_back (data_const);
+ }
+ _pipeline = VKPipeline::create_compute_pipeline (_device, shader, bindings, const_array);
+ XCAM_FAIL_RETURN (
+ ERROR, _pipeline.ptr (), XCAM_RETURN_ERROR_VULKAN,
+ "vk woker(%s) build failed when creating pipelines.", XCAM_STR (get_name ()));
+
+ _pipeline->set_desc_pool (_desc_pool);
+
+ _cmdbuf = VKCmdBuf::create_command_buffer (_device);
+ XCAM_FAIL_RETURN (
+ ERROR, _cmdbuf.ptr (), XCAM_RETURN_ERROR_VULKAN,
+ "vk woker(%s) build failed when creating command buffers.", XCAM_STR (get_name ()));
+
+ _fence = _device->create_fence (VK_FENCE_CREATE_SIGNALED_BIT);
+ XCAM_FAIL_RETURN (
+ ERROR, _fence.ptr (), XCAM_RETURN_ERROR_VULKAN,
+ "vk woker(%s) build failed when creating fence.", XCAM_STR (get_name ()));
+ return XCAM_RETURN_NO_ERROR;
+}
+
+// derived from Worker
+XCamReturn
+VKWorker::work (const SmartPtr<Worker::Arguments> &args)
+{
+ SmartPtr<VKArguments> vk_args = args.dynamic_cast_ptr<VKArguments>();
+ XCAM_FAIL_RETURN (
+ ERROR, vk_args.ptr(), XCAM_RETURN_ERROR_PARAM,
+ "vk woker(%s) work argements error.", XCAM_STR (get_name ()));
+
+ VKDescriptor::SetBindInfoArray binding_array;
+ VKConstRange::VKPushConstArgs push_consts;
+ XCamReturn ret = vk_args->prepare_bindings (binding_array, push_consts);
+
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk woker(%s) prepare argements failed.", XCAM_STR (get_name ()));
+
+ XCAM_FAIL_RETURN (
+ ERROR, !binding_array.empty (), XCAM_RETURN_ERROR_PARAM,
+ "vk woker(%s) binding_array is empty.", XCAM_STR (get_name ()));
+
+ ret = _pipeline->update_bindings (binding_array);
+
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk woker(%s) update binding argements failed.", XCAM_STR (get_name ()));
+
+ const WorkSize global = get_global_size ();
+ SmartPtr<VKCmdBuf::DispatchParam> dispatch =
+ new VKCmdBuf::DispatchParam (_pipeline, global.value[0], global.value[1], global.value[2]);
+ if (!push_consts.empty()) {
+ XCAM_FAIL_RETURN (
+ ERROR, dispatch->update_push_consts (push_consts), XCAM_RETURN_ERROR_PARAM,
+ "vk woker(%s) update push-consts failed.", XCAM_STR (get_name ()));
+ }
+
+ ret = _cmdbuf->record (dispatch);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk woker(%s) record cmdbuf failed.", XCAM_STR (get_name ()));
+
+ ret = _device->compute_queue_submit (_cmdbuf, _fence);
+ XCAM_FAIL_RETURN (
+ ERROR, xcam_ret_is_ok (ret), ret,
+ "vk woker(%s) submit compute queue failed.", XCAM_STR (get_name ()));
+
+ status_check (args, ret);
+
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKWorker::stop ()
+{
+ if (_pipeline.ptr () && _device.ptr ()) {
+ if (_fence.ptr ()) {
+ _fence->wait ();
+ _fence->reset ();
+ }
+ _device->compute_queue_wait_idle ();
+ }
+ return XCAM_RETURN_NO_ERROR;
+}
+
+XCamReturn
+VKWorker::wait_fence ()
+{
+ XCamReturn ret = XCAM_RETURN_NO_ERROR;
+ if (_fence.ptr ()) {
+ ret = _fence->wait ();
+ if (!xcam_ret_is_ok (ret)) {
+ XCAM_LOG_ERROR ("vk woker(%s) wait fence failed.", XCAM_STR (get_name ()));
+ }
+ _fence->reset ();
+ }
+
+ return ret;
+}
+
+}
diff --git a/modules/vulkan/vk_worker.h b/modules/vulkan/vk_worker.h
new file mode 100644
index 0000000..c23bd4d
--- /dev/null
+++ b/modules/vulkan/vk_worker.h
@@ -0,0 +1,112 @@
+/*
+ * vk_worker.h - vulkan worker class
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_WORKER_H
+#define XCAM_VK_WORKER_H
+
+#include <vulkan/vulkan_std.h>
+#include <vulkan/vk_descriptor.h>
+#include <worker.h>
+#include <string>
+
+namespace XCam {
+
+class VKPipeline;
+class VKDevice;
+class VKFence;
+class VKCmdBuf;
+
+enum VKSahderInfoType {
+ VKSahderInfoSpirVBinary = 0,
+ VKSahderInfoSpirVPath = 1,
+};
+
+struct VKShaderInfo {
+ VKSahderInfoType type;
+ std::string func_name;
+ std::string spirv_path;
+ std::vector<uint32_t> spirv_bin;
+
+ VKShaderInfo () {}
+ VKShaderInfo (const char *func, const char *path)
+ : type (VKSahderInfoSpirVPath)
+ , func_name (func)
+ , spirv_path (path)
+ {}
+ VKShaderInfo (const char *func, const std::vector<uint32_t> &binary)
+ : type (VKSahderInfoSpirVBinary)
+ , func_name (func)
+ , spirv_bin (binary)
+ {}
+};
+
+class VKWorker
+ : public Worker
+{
+public:
+ class VKArguments:
+ public Worker::Arguments
+ {
+ friend class VKWorker;
+ public:
+ VKArguments () {}
+ VKArguments (VKDescriptor::SetBindInfoArray &arr)
+ : _binding_bufs (arr)
+ {}
+ bool set_bindings (const VKDescriptor::SetBindInfoArray &arr);
+ bool add_binding (const VKDescriptor::SetBindInfo &info);
+ bool add_push_const (const SmartPtr<VKConstRange::VKPushConstArg> &push_const);
+
+ protected:
+ virtual XCamReturn prepare_bindings (
+ VKDescriptor::SetBindInfoArray &binding_array,
+ VKConstRange::VKPushConstArgs &push_consts);
+ private:
+ VKDescriptor::SetBindInfoArray _binding_bufs;
+ VKConstRange::VKPushConstArgs _push_consts;
+ };
+
+public:
+ explicit VKWorker (SmartPtr<VKDevice> dev, const char *name, const SmartPtr<Callback> &cb = NULL);
+ virtual ~VKWorker ();
+
+ XCamReturn build (
+ const VKShaderInfo &info,
+ const VKDescriptor::BindingArray &bindings,
+ const VKConstRange::VKPushConstArgs &consts);
+
+ // derived from Worker
+ virtual XCamReturn work (const SmartPtr<Arguments> &args);
+ virtual XCamReturn stop ();
+ XCamReturn wait_fence ();
+
+private:
+ XCAM_DEAD_COPY (VKWorker);
+
+private:
+ SmartPtr<VKDevice> _device;
+ SmartPtr<VKDescriptor::Pool> _desc_pool;
+ SmartPtr<VKPipeline> _pipeline;
+ SmartPtr<VKFence> _fence;
+ SmartPtr<VKCmdBuf> _cmdbuf;
+};
+
+}
+#endif //XCAM_VK_WORKER_H
diff --git a/modules/vulkan/vulkan_common.cpp b/modules/vulkan/vulkan_common.cpp
new file mode 100644
index 0000000..6e7ec66
--- /dev/null
+++ b/modules/vulkan/vulkan_common.cpp
@@ -0,0 +1,77 @@
+/*
+ * vulkan_common.cpp - vulkan common
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#include "vulkan_common.h"
+#include <map>
+
+#define VK_STR_INSERT(ERR) \
+ vk_errors.insert (VkErrorMap::value_type(VK_ ##ERR, #ERR))
+
+namespace XCam {
+
+typedef std::map <uint32_t, const char*> VkErrorMap;
+
+static VkErrorMap vk_errors;
+
+void vk_init_error_string ()
+{
+ if (!vk_errors.empty ())
+ return;
+
+ VK_STR_INSERT (SUCCESS);
+ VK_STR_INSERT (NOT_READY);
+ VK_STR_INSERT (TIMEOUT);
+ VK_STR_INSERT (EVENT_SET);
+ VK_STR_INSERT (EVENT_RESET);
+ VK_STR_INSERT (INCOMPLETE);
+ VK_STR_INSERT (ERROR_OUT_OF_HOST_MEMORY);
+ VK_STR_INSERT (ERROR_OUT_OF_DEVICE_MEMORY);
+ VK_STR_INSERT (ERROR_INITIALIZATION_FAILED);
+ VK_STR_INSERT (ERROR_DEVICE_LOST);
+ VK_STR_INSERT (ERROR_MEMORY_MAP_FAILED);
+ VK_STR_INSERT (ERROR_LAYER_NOT_PRESENT);
+ VK_STR_INSERT (ERROR_FEATURE_NOT_PRESENT);
+ VK_STR_INSERT (ERROR_INCOMPATIBLE_DRIVER);
+ VK_STR_INSERT (ERROR_TOO_MANY_OBJECTS);
+ VK_STR_INSERT (ERROR_FORMAT_NOT_SUPPORTED);
+ VK_STR_INSERT (ERROR_FRAGMENTED_POOL);
+}
+
+const char*
+vk_error_str(VkResult id)
+{
+ VkErrorMap::iterator i = vk_errors.find (id);
+ if (i == vk_errors.end ())
+ return "VkUnKnown";
+ return i->second;
+}
+
+const std::string
+xcam_default_shader_path ()
+{
+ std::string home = "~";
+ const char *env = std::getenv ("HOME");
+ if (env)
+ home.assign (env, strlen (env));
+
+ return home + "/.xcam/vk";
+}
+
+}
diff --git a/modules/vulkan/vulkan_common.h b/modules/vulkan/vulkan_common.h
new file mode 100644
index 0000000..8093029
--- /dev/null
+++ b/modules/vulkan/vulkan_common.h
@@ -0,0 +1,33 @@
+/*
+ * vulkan_common.h - vulkan common
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_COMMON_H
+#define XCAM_VK_COMMON_H
+
+#include <vulkan/vulkan_std.h>
+#include <string>
+
+namespace XCam {
+
+const char* vk_error_str(VkResult id);
+const std::string xcam_default_shader_path ();
+}
+
+#endif
diff --git a/modules/vulkan/vulkan_std.h b/modules/vulkan/vulkan_std.h
new file mode 100644
index 0000000..952645e
--- /dev/null
+++ b/modules/vulkan/vulkan_std.h
@@ -0,0 +1,43 @@
+/*
+ * vulkan_std.h - vulkan common
+ *
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Wind Yuan <feng.yuan@intel.com>
+ */
+
+#ifndef XCAM_VK_STD_H
+#define XCAM_VK_STD_H
+
+#include <xcam_std.h>
+#include <vulkan/vulkan.h>
+
+#define XCAM_VK_CHECK_RETURN(LEVEL, vk_exp, failed_value, format, ...) \
+ do { \
+ VkResult err = vk_exp; \
+ XCAM_FAIL_RETURN (LEVEL, err == VK_SUCCESS, failed_value, \
+ format ", vk_error(%d:%s)", ## __VA_ARGS__, \
+ (int)err, vk_error_str(err)); \
+ } while (0)
+
+
+#define XCAM_VK_NAME_LENGTH 256
+
+#define XCAM_IS_VALID_VK_ID(id) (VK_NULL_HANDLE != (id))
+
+#define XCAM_VK_SHADER_PATH "XCAM_VK_SHADER_PATH"
+#define XCAM_DEFAULT_VK_SHADER_PATH xcam_default_shader_path()
+
+#endif