From 69ed7b53da7f0ef3c981727266ef9f9f88de9149 Mon Sep 17 00:00:00 2001 From: Romaric Jodin Date: Mon, 2 Sep 2024 15:17:21 +0200 Subject: [PATCH] init image at creation time fix #719 --- README.md | 6 ++++++ src/CMakeLists.txt | 1 + src/config.def | 2 ++ src/context.cpp | 32 ++++++++++++++++++++++++++++++++ src/context.hpp | 8 ++++++++ src/memory.cpp | 18 ++++++++++++++++++ src/queue.cpp | 4 ++++ 7 files changed, 71 insertions(+) create mode 100644 src/context.cpp diff --git a/README.md b/README.md index b8ed7785..f6a458ee 100644 --- a/README.md +++ b/README.md @@ -532,6 +532,12 @@ using the name of the corresponding environment variable. can be a work-around when having issues with clang compiling in the application thread. +* `CLVK_INIT_IMAGE_AT_CREATION` force to initialize OpenCL images created with + `CL_MEM_COPY_HOST_PTR` or `CL_MEM_USE_HOST_PTR` at creation time instead of + initializing them during first use of the image (default: false). It reduces + the memory footprint as clvk needs to keep a buffer with the data to + initialize at first use. + # Limitations * Only one device per CL context diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d848e02a..f68a6d5d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -56,6 +56,7 @@ endif() add_library(OpenCL-objects OBJECT api.cpp config.cpp + context.cpp device.cpp device_properties.cpp event.cpp diff --git a/src/config.def b/src/config.def index 28b7ed55..b6677e05 100644 --- a/src/config.def +++ b/src/config.def @@ -31,6 +31,8 @@ OPTION(uint32_t, opencl_version, (uint32_t)CL_MAKE_VERSION(3, 0, 0)) OPTION(bool, build_in_separate_thread, false) +OPTION(bool, init_image_at_creation, false) + #if COMPILER_AVAILABLE OPTION(std::string, clspv_options, "") #if !CLSPV_ONLINE_COMPILER diff --git a/src/context.cpp b/src/context.cpp new file mode 100644 index 00000000..cea80008 --- /dev/null +++ b/src/context.cpp @@ -0,0 +1,32 @@ +// Copyright 2024 The clvk authors. +// +// 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. + +#include "context.hpp" +#include "queue.hpp" + +cvk_command_queue* cvk_context::get_or_create_image_init_command_queue() { + if (m_queue_image_init != nullptr) { + return m_queue_image_init; + } + std::vector properties_array; + m_queue_image_init = + new cvk_command_queue(this, m_device, 0, std::move(properties_array)); + cl_int ret = m_queue_image_init->init(); + if (ret != CL_SUCCESS) { + return nullptr; + } + return m_queue_image_init; +} + +void cvk_context::free_image_init_command_queue() { delete m_queue_image_init; } diff --git a/src/context.hpp b/src/context.hpp index cbfaaa8a..995e7db7 100644 --- a/src/context.hpp +++ b/src/context.hpp @@ -29,6 +29,8 @@ struct cvk_context_callback { void* data; }; +struct cvk_command_queue; + struct cvk_context : public _cl_context, refcounted, object_magic_header { @@ -75,6 +77,7 @@ struct cvk_context : public _cl_context, auto cb = *cbi; cb.pointer(this, cb.data); } + free_image_init_command_queue(); } const std::vector& properties() const { @@ -112,6 +115,9 @@ struct cvk_context : public _cl_context, cvk_printf_callback_t get_printf_callback() { return m_printf_callback; } void* get_printf_userdata() { return m_user_data; } + cvk_command_queue* get_or_create_image_init_command_queue(); + void free_image_init_command_queue(); + private: cvk_device* m_device; std::mutex m_callbacks_lock; @@ -120,6 +126,8 @@ struct cvk_context : public _cl_context, size_t m_printf_buffersize; cvk_printf_callback_t m_printf_callback; void* m_user_data; + + cvk_command_queue* m_queue_image_init = nullptr; }; static inline cvk_context* icd_downcast(cl_context context) { diff --git a/src/memory.cpp b/src/memory.cpp index 2a04436f..74925ec9 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -508,6 +508,24 @@ bool cvk_image::init_vulkan_image() { "Could not copy image host_ptr data to the staging buffer"); return false; } + + if (config.init_image_at_creation()) { + auto queue = m_context->get_or_create_image_init_command_queue(); + if (queue == nullptr) { + return false; + } + + auto initimage = new cvk_command_image_init(queue, this); + ret = queue->enqueue_command_with_deps(initimage, 0, nullptr, + nullptr); + if (ret != CL_SUCCESS) { + return false; + } + ret = queue->finish(); + if (ret != CL_SUCCESS) { + return false; + } + } } return true; diff --git a/src/queue.cpp b/src/queue.cpp index 861370a1..7f2f1065 100644 --- a/src/queue.cpp +++ b/src/queue.cpp @@ -101,6 +101,10 @@ cl_int cvk_command_queue::satisfy_data_dependencies(cvk_command* cmd) { continue; } CVK_ASSERT(mem->is_image_type()); + if (config.init_image_at_creation()) { + tracker.set_state(cvk_mem_init_state::completed); + continue; + } auto initcmd = new cvk_command_image_init(this, static_cast(mem)); _cl_event* initev;