From 7bf05e286b6fff674d4c59ea75501a2ec2ddf7d5 Mon Sep 17 00:00:00 2001 From: Anthony Lombardi Date: Tue, 24 Oct 2023 14:05:18 -0400 Subject: [PATCH] WIP: Precompile ocl kernels upon object creation --- .../src/gpu/opencl/BackgroundRenderer.cpp | 43 +++++++------- .../src/gpu/opencl/BackgroundRenderer.hpp | 2 + .../src/gpu/opencl/ContrastFilter.cpp | 27 +++++---- .../src/gpu/opencl/ContrastFilter.hpp | 3 +- .../src/gpu/opencl/GaussianFilter.cpp | 27 +++++---- .../src/gpu/opencl/GaussianFilter.hpp | 2 + libautoscoper/src/gpu/opencl/Ncc.cpp | 57 +++++++++++-------- libautoscoper/src/gpu/opencl/RadRenderer.cpp | 43 +++++++------- libautoscoper/src/gpu/opencl/RadRenderer.hpp | 2 + libautoscoper/src/gpu/opencl/RayCaster.cpp | 42 ++++++++------ libautoscoper/src/gpu/opencl/RayCaster.hpp | 3 + .../src/gpu/opencl/SharpenFilter.cpp | 33 ++++++----- .../src/gpu/opencl/SharpenFilter.hpp | 2 + libautoscoper/src/gpu/opencl/SobelFilter.cpp | 28 +++++---- libautoscoper/src/gpu/opencl/SobelFilter.hpp | 4 +- 15 files changed, 186 insertions(+), 132 deletions(-) diff --git a/libautoscoper/src/gpu/opencl/BackgroundRenderer.cpp b/libautoscoper/src/gpu/opencl/BackgroundRenderer.cpp index 1a6f73f0..efd547eb 100644 --- a/libautoscoper/src/gpu/opencl/BackgroundRenderer.cpp +++ b/libautoscoper/src/gpu/opencl/BackgroundRenderer.cpp @@ -66,11 +66,13 @@ BackgroundRenderer::BackgroundRenderer() : image_(0) viewport_[1] = -1.0f; viewport_[2] = 2.0f; viewport_[3] = 2.0f; + kernel_ = background_renderer_program_.compile(BackgroundRenderer_cl, "background_render_kernel"); } BackgroundRenderer::~BackgroundRenderer() { if (image_) delete image_; + if (kernel_) delete kernel_; } void @@ -108,30 +110,31 @@ BackgroundRenderer::set_viewport(float x, float y, float width, float height) void BackgroundRenderer::render(const Buffer* buffer, unsigned width, unsigned height, float threshold) const { - Kernel* kernel = background_renderer_program_.compile( - BackgroundRenderer_cl, "background_render_kernel"); - - kernel->addBufferArg(buffer); - kernel->addArg(width); - kernel->addArg(height); - kernel->addArg(image_plane_[0]); - kernel->addArg(image_plane_[1]); - kernel->addArg(image_plane_[2]); - kernel->addArg(image_plane_[3]); - kernel->addArg(viewport_[0]); - kernel->addArg(viewport_[1]); - kernel->addArg(viewport_[2]); - kernel->addArg(viewport_[3]); - kernel->addArg(threshold), - kernel->addImageArg(image_); + // Kernel* kernel = background_renderer_program_.compile( + // BackgroundRenderer_cl, "background_render_kernel"); + + kernel_->addBufferArg(buffer); + kernel_->addArg(width); + kernel_->addArg(height); + kernel_->addArg(image_plane_[0]); + kernel_->addArg(image_plane_[1]); + kernel_->addArg(image_plane_[2]); + kernel_->addArg(image_plane_[3]); + kernel_->addArg(viewport_[0]); + kernel_->addArg(viewport_[1]); + kernel_->addArg(viewport_[2]); + kernel_->addArg(viewport_[3]); + kernel_->addArg(threshold), + kernel_->addImageArg(image_); // Calculate the block and grid sizes. - kernel->block2d(BX, BY); - kernel->grid2d((width+BX-1)/BX, (height+BY-1)/BY); + kernel_->block2d(BX, BY); + kernel_->grid2d((width+BX-1)/BX, (height+BY-1)/BY); - kernel->launch(); + kernel_->launch(); - delete kernel; + kernel_->reset(); + // delete kernel; } } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/BackgroundRenderer.hpp b/libautoscoper/src/gpu/opencl/BackgroundRenderer.hpp index 45c300a2..9b2a2c30 100644 --- a/libautoscoper/src/gpu/opencl/BackgroundRenderer.hpp +++ b/libautoscoper/src/gpu/opencl/BackgroundRenderer.hpp @@ -66,6 +66,8 @@ namespace xromm { namespace gpu Image* image_; float image_plane_[4]; float viewport_[4]; + + mutable Kernel* kernel_; }; } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/ContrastFilter.cpp b/libautoscoper/src/gpu/opencl/ContrastFilter.cpp index 7a65060d..6f041126 100644 --- a/libautoscoper/src/gpu/opencl/ContrastFilter.cpp +++ b/libautoscoper/src/gpu/opencl/ContrastFilter.cpp @@ -64,6 +64,7 @@ ContrastFilter::ContrastFilter() std::stringstream name_stream; name_stream << "ContrastFilter" << (++num_contrast_filters); name_ = name_stream.str(); + kernel_ = contrast_program_.compile(ContrastFilter_cl, KERNEL_NAME); } void @@ -73,22 +74,24 @@ ContrastFilter::apply( int width, int height) { - Kernel* kernel = contrast_program_.compile(ContrastFilter_cl, KERNEL_NAME); + // Kernel* kernel = contrast_program_.compile(ContrastFilter_cl, KERNEL_NAME); - kernel->block2d(KERNEL_X, KERNEL_Y); - kernel->grid2d((width-1)/KERNEL_X+1, (height-1)/KERNEL_Y+1); + kernel_->block2d(KERNEL_X, KERNEL_Y); + kernel_->grid2d((width-1)/KERNEL_X+1, (height-1)/KERNEL_Y+1); - kernel->addBufferArg(input); - kernel->addBufferArg(output); - kernel->addArg(width); - kernel->addArg(height); - kernel->addArg(alpha_); - kernel->addArg(beta_); - kernel->addArg(size_); + kernel_->addBufferArg(input); + kernel_->addBufferArg(output); + kernel_->addArg(width); + kernel_->addArg(height); + kernel_->addArg(alpha_); + kernel_->addArg(beta_); + kernel_->addArg(size_); - kernel->launch(); + kernel_->launch(); - delete kernel; + kernel_->reset(); + + //delete kernel; } } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/ContrastFilter.hpp b/libautoscoper/src/gpu/opencl/ContrastFilter.hpp index 10aebac3..e93003b3 100644 --- a/libautoscoper/src/gpu/opencl/ContrastFilter.hpp +++ b/libautoscoper/src/gpu/opencl/ContrastFilter.hpp @@ -53,7 +53,7 @@ class ContrastFilter : public Filter { public: ContrastFilter(); - virtual ~ContrastFilter() {} + ~ContrastFilter() { if (kernel_) delete kernel_; } // Apply the filter to the input image virtual void apply(const Buffer* input, @@ -72,6 +72,7 @@ class ContrastFilter : public Filter float alpha_; float beta_; int size_; + Kernel* kernel_; }; } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/GaussianFilter.cpp b/libautoscoper/src/gpu/opencl/GaussianFilter.cpp index 21baa22c..5565b99b 100644 --- a/libautoscoper/src/gpu/opencl/GaussianFilter.cpp +++ b/libautoscoper/src/gpu/opencl/GaussianFilter.cpp @@ -64,11 +64,14 @@ GaussianFilter::GaussianFilter() name_ = name_stream.str(); set_radius(1); + + kernel_ = gaussian_program_.compile(GaussianFilter_cl, KERNEL_NAME); } GaussianFilter::~GaussianFilter() { if (gaussian_ != NULL) delete gaussian_; + if (kernel_) delete kernel_; } void GaussianFilter::set_radius(float radius) @@ -133,21 +136,23 @@ GaussianFilter::apply(const Buffer* input, } else { - Kernel* kernel = gaussian_program_.compile(GaussianFilter_cl, KERNEL_NAME); + //Kernel* kernel = gaussian_program_.compile(GaussianFilter_cl, KERNEL_NAME); + + kernel_->block2d(KERNEL_X, KERNEL_Y); + kernel_->grid2d((width-1)/KERNEL_X+1, (height-1)/KERNEL_Y+1); - kernel->block2d(KERNEL_X, KERNEL_Y); - kernel->grid2d((width-1)/KERNEL_X+1, (height-1)/KERNEL_Y+1); + kernel_->addBufferArg(input); + kernel_->addBufferArg(output); + kernel_->addArg(width); + kernel_->addArg(height); + kernel_->addBufferArg(gaussian_); + kernel_->addArg(filterSize_); - kernel->addBufferArg(input); - kernel->addBufferArg(output); - kernel->addArg(width); - kernel->addArg(height); - kernel->addBufferArg(gaussian_); - kernel->addArg(filterSize_); + kernel_->launch(); - kernel->launch(); + kernel_->reset(); - delete kernel; + //delete kernel; } } diff --git a/libautoscoper/src/gpu/opencl/GaussianFilter.hpp b/libautoscoper/src/gpu/opencl/GaussianFilter.hpp index 04139fa3..4dff8ec2 100644 --- a/libautoscoper/src/gpu/opencl/GaussianFilter.hpp +++ b/libautoscoper/src/gpu/opencl/GaussianFilter.hpp @@ -69,6 +69,8 @@ class GaussianFilter : public Filter float radius_; Buffer* gaussian_; int filterSize_; + + Kernel* kernel_; }; } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/Ncc.cpp b/libautoscoper/src/gpu/opencl/Ncc.cpp index a6d9a79f..5a1d11f6 100644 --- a/libautoscoper/src/gpu/opencl/Ncc.cpp +++ b/libautoscoper/src/gpu/opencl/Ncc.cpp @@ -63,6 +63,9 @@ static Buffer* d_den2s = NULL; static Program ncc_kernel_; static Program ncc_sum_kernel_; +Kernel* ncc_kernel; +Kernel* ncc_sum_kernel; + //////// Helper functions //////// static void get_max_threads() @@ -108,7 +111,7 @@ static float ncc_sum(Buffer* f, unsigned n) size_t numThreads, numBlocks, sizeMem; get_device_params(n, numThreads, numBlocks, sizeMem); - Kernel* kernel = ncc_sum_kernel_.compile(NccSum_cl, "ncc_sum_kernel"); + //Kernel* kernel = ncc_sum_kernel_.compile(NccSum_cl, "ncc_sum_kernel"); while (n > 1) { @@ -118,15 +121,15 @@ static float ncc_sum(Buffer* f, unsigned n) std::cerr << "ncc_sum[" << n << "] sizeMem = " << sizeMem << std::endl; #endif - kernel->block2d(numThreads, 1); - kernel->grid2d(1, numBlocks); + ncc_sum_kernel->block2d(numThreads, 1); + ncc_sum_kernel->grid2d(1, numBlocks); - kernel->addBufferArg(f); - kernel->addBufferArg(d_sums); - kernel->addLocalMem(sizeMem); - kernel->addArg(n); + ncc_sum_kernel->addBufferArg(f); + ncc_sum_kernel->addBufferArg(d_sums); + ncc_sum_kernel->addLocalMem(sizeMem); + ncc_sum_kernel->addArg(n); - kernel->launch(); + ncc_sum_kernel->launch(); #if DEBUG float *tmp = new float[numBlocks]; @@ -142,10 +145,10 @@ static float ncc_sum(Buffer* f, unsigned n) get_device_params(n, numThreads, numBlocks, sizeMem); f = d_sums; - kernel->reset(); + ncc_sum_kernel->reset(); } - delete kernel; + //delete kernel; float h_sum; d_sums->write(&h_sum, sizeof(float)); @@ -171,6 +174,8 @@ void ncc_init(unsigned max_n) g_max_n = max_n; } + ncc_kernel = ncc_kernel_.compile(Ncc_cl, "ncc_kernel"); + ncc_sum_kernel = ncc_sum_kernel_.compile(NccSum_cl, "ncc_sum_kernel"); } void ncc_deinit() @@ -179,6 +184,8 @@ void ncc_deinit() delete d_nums; delete d_den1s; delete d_den2s; + delete ncc_kernel; + delete ncc_sum_kernel; g_max_n = 0; } @@ -197,24 +204,26 @@ float ncc(Buffer* f, Buffer* g, Buffer* mask, unsigned n) size_t numThreads, numBlocks, sizeMem; get_device_params(n, numThreads, numBlocks, sizeMem); - Kernel* kernel = ncc_kernel_.compile(Ncc_cl, "ncc_kernel"); + //Kernel* kernel = ncc_kernel_.compile(Ncc_cl, "ncc_kernel"); + + ncc_kernel->block1d(numThreads); + ncc_kernel->grid1d(numBlocks); - kernel->block1d(numThreads); - kernel->grid1d(numBlocks); + ncc_kernel->addBufferArg(f); + ncc_kernel->addArg(meanF); + ncc_kernel->addBufferArg(g); + ncc_kernel->addArg(meanG); + ncc_kernel->addBufferArg(mask); + ncc_kernel->addBufferArg(d_nums); + ncc_kernel->addBufferArg(d_den1s); + ncc_kernel->addBufferArg(d_den2s); + ncc_kernel->addArg(n); - kernel->addBufferArg(f); - kernel->addArg(meanF); - kernel->addBufferArg(g); - kernel->addArg(meanG); - kernel->addBufferArg(mask); - kernel->addBufferArg(d_nums); - kernel->addBufferArg(d_den1s); - kernel->addBufferArg(d_den2s); - kernel->addArg(n); + ncc_kernel->launch(); - kernel->launch(); + ncc_kernel->reset(); - delete kernel; + //delete kernel; float den = sqrt(ncc_sum(d_den1s,n)*ncc_sum(d_den2s,n)); diff --git a/libautoscoper/src/gpu/opencl/RadRenderer.cpp b/libautoscoper/src/gpu/opencl/RadRenderer.cpp index 7a0f5ec5..e5e34ce2 100644 --- a/libautoscoper/src/gpu/opencl/RadRenderer.cpp +++ b/libautoscoper/src/gpu/opencl/RadRenderer.cpp @@ -71,11 +71,14 @@ RadRenderer::RadRenderer() : image_(0) std::stringstream name_stream; name_stream << "RadRenderer" << (++num_rad_renderers); name_ = name_stream.str(); + + kernel_ = rad_renderer_program_.compile( RadRenderer_cl, "rad_render_kernel"); } RadRenderer::~RadRenderer() { if (image_) delete image_; + if (kernel_) delete kernel_; } void @@ -119,29 +122,31 @@ RadRenderer::set_viewport(float x, float y, float width, float height) void RadRenderer::render(const Buffer* buffer, unsigned width, unsigned height) const { - Kernel* kernel = rad_renderer_program_.compile( - RadRenderer_cl, "rad_render_kernel"); - - kernel->addBufferArg(buffer); - kernel->addArg(width); - kernel->addArg(height); - kernel->addArg(image_plane_[0]); - kernel->addArg(image_plane_[1]); - kernel->addArg(image_plane_[2]); - kernel->addArg(image_plane_[3]); - kernel->addArg(viewport_[0]); - kernel->addArg(viewport_[1]); - kernel->addArg(viewport_[2]); - kernel->addArg(viewport_[3]); - kernel->addImageArg(image_); + /*Kernel* kernel = rad_renderer_program_.compile( + RadRenderer_cl, "rad_render_kernel");*/ + + kernel_->addBufferArg(buffer); + kernel_->addArg(width); + kernel_->addArg(height); + kernel_->addArg(image_plane_[0]); + kernel_->addArg(image_plane_[1]); + kernel_->addArg(image_plane_[2]); + kernel_->addArg(image_plane_[3]); + kernel_->addArg(viewport_[0]); + kernel_->addArg(viewport_[1]); + kernel_->addArg(viewport_[2]); + kernel_->addArg(viewport_[3]); + kernel_->addImageArg(image_); // Calculate the block and grid sizes. - kernel->block2d(BX, BY); - kernel->grid2d((width+BX-1)/BX, (height+BY-1)/BY); + kernel_->block2d(BX, BY); + kernel_->grid2d((width+BX-1)/BX, (height+BY-1)/BY); + + kernel_->launch(); - kernel->launch(); + kernel_->reset(); - delete kernel; + //delete kernel; } } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/RadRenderer.hpp b/libautoscoper/src/gpu/opencl/RadRenderer.hpp index de2d4915..d786ccd4 100644 --- a/libautoscoper/src/gpu/opencl/RadRenderer.hpp +++ b/libautoscoper/src/gpu/opencl/RadRenderer.hpp @@ -70,6 +70,8 @@ class RadRenderer float image_plane_[4]; float viewport_[4]; std::string name_; + + Kernel* kernel_; }; } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/RayCaster.cpp b/libautoscoper/src/gpu/opencl/RayCaster.cpp index 272dcd37..36ee0cc1 100644 --- a/libautoscoper/src/gpu/opencl/RayCaster.cpp +++ b/libautoscoper/src/gpu/opencl/RayCaster.cpp @@ -75,11 +75,15 @@ RayCaster::RayCaster() : volumeDescription_(0), b_viewport_ = new Buffer(4*sizeof(float), CL_MEM_READ_ONLY); b_viewport_->read(viewport_); visible_ = true; + + // Compile kernel + kernel_ = raycaster_program_.compile(RayCaster_cl, "volume_render_kernel"); } RayCaster::~RayCaster() { if (b_viewport_) delete b_viewport_; + if (kernel_) delete kernel_; } void @@ -166,29 +170,31 @@ RayCaster::render(const Buffer* buffer, unsigned width, unsigned height) return; } - Kernel* kernel = raycaster_program_.compile( - RayCaster_cl, "volume_render_kernel"); + /* Kernel* kernel = raycaster_program_.compile( + RayCaster_cl, "volume_render_kernel");*/ Buffer* b_imv = new Buffer(12*sizeof(float), CL_MEM_READ_ONLY); b_imv->read(invModelView_); // Calculate the block and grid sizes. - kernel->block2d(BX, BY); - kernel->grid2d((width+BX-1)/BX, (height+BY-1)/BY); - - kernel->addBufferArg(buffer); - kernel->addArg(width); - kernel->addArg(height); - kernel->addArg(sampleDistance_); - kernel->addArg(rayIntensity_); - kernel->addArg(cutoff_); - kernel->addBufferArg(b_viewport_); - kernel->addBufferArg(b_imv); - kernel->addImageArg(volumeDescription_->image()); - - kernel->launch(); - - delete kernel; + kernel_ ->block2d(BX, BY); + kernel_->grid2d((width+BX-1)/BX, (height+BY-1)/BY); + + kernel_->addBufferArg(buffer); + kernel_->addArg(width); + kernel_->addArg(height); + kernel_->addArg(sampleDistance_); + kernel_->addArg(rayIntensity_); + kernel_->addArg(cutoff_); + kernel_->addBufferArg(b_viewport_); + kernel_->addBufferArg(b_imv); + kernel_->addImageArg(volumeDescription_->image()); + + kernel_->launch(); + + kernel_->reset(); + + //delete kernel; delete b_imv; } diff --git a/libautoscoper/src/gpu/opencl/RayCaster.hpp b/libautoscoper/src/gpu/opencl/RayCaster.hpp index 49810e46..42f2116d 100644 --- a/libautoscoper/src/gpu/opencl/RayCaster.hpp +++ b/libautoscoper/src/gpu/opencl/RayCaster.hpp @@ -114,6 +114,9 @@ class RayCaster float cutoff_; std::string name_; bool visible_; + + // Compile once, upon object creation + Kernel* kernel_; }; } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/SharpenFilter.cpp b/libautoscoper/src/gpu/opencl/SharpenFilter.cpp index 2c4031be..234e5b02 100644 --- a/libautoscoper/src/gpu/opencl/SharpenFilter.cpp +++ b/libautoscoper/src/gpu/opencl/SharpenFilter.cpp @@ -70,11 +70,14 @@ SharpenFilter::SharpenFilter() set_radius(1); set_contrast(1); set_threshold(0); + + kernel_ = sharpen_program_.compile(SharpenFilter_cl, "sharpen_filter_kernel"); } SharpenFilter::~SharpenFilter() { if (sharpen_ != NULL) delete sharpen_; + if (kernel_) delete kernel_; } void SharpenFilter::set_radius(float radius) @@ -155,24 +158,26 @@ SharpenFilter::apply( } else { - Kernel* kernel = sharpen_program_.compile( - SharpenFilter_cl, "sharpen_filter_kernel"); + /* Kernel* kernel = sharpen_program_.compile( + SharpenFilter_cl, "sharpen_filter_kernel");*/ + + kernel_->block2d(BX, BY); + kernel_->grid2d((width-1)/BX+1, (height-1)/BY+1); - kernel->block2d(BX, BY); - kernel->grid2d((width-1)/BX+1, (height-1)/BY+1); + kernel_->addBufferArg(input); + kernel_->addBufferArg(output); + kernel_->addArg(width); + kernel_->addArg(height); + kernel_->addBufferArg(sharpen_); + kernel_->addArg(filterSize_); + kernel_->addArg(contrast_); + kernel_->addArg(threshold_); - kernel->addBufferArg(input); - kernel->addBufferArg(output); - kernel->addArg(width); - kernel->addArg(height); - kernel->addBufferArg(sharpen_); - kernel->addArg(filterSize_); - kernel->addArg(contrast_); - kernel->addArg(threshold_); + kernel_->launch(); - kernel->launch(); + kernel_->reset(); - delete kernel; + //delete kernel; } } diff --git a/libautoscoper/src/gpu/opencl/SharpenFilter.hpp b/libautoscoper/src/gpu/opencl/SharpenFilter.hpp index cdf910a1..772f1a31 100644 --- a/libautoscoper/src/gpu/opencl/SharpenFilter.hpp +++ b/libautoscoper/src/gpu/opencl/SharpenFilter.hpp @@ -79,6 +79,8 @@ class SharpenFilter : public Filter Buffer* sharpen_; int filterSize_; + Kernel* kernel_; + void makeFilter(); }; diff --git a/libautoscoper/src/gpu/opencl/SobelFilter.cpp b/libautoscoper/src/gpu/opencl/SobelFilter.cpp index a0d830d1..4e6bec2a 100644 --- a/libautoscoper/src/gpu/opencl/SobelFilter.cpp +++ b/libautoscoper/src/gpu/opencl/SobelFilter.cpp @@ -60,6 +60,8 @@ SobelFilter::SobelFilter() : Filter(XROMM_GPU_SOBEL_FILTER,""), std::stringstream name_stream; name_stream << "SobelFilter" << (++num_sobel_filters); name_ = name_stream.str(); + + kernel_ = sobel_program_.compile(SobelFilter_cl, "sobel_filter_kernel"); } void @@ -69,22 +71,24 @@ SobelFilter::apply( int width, int height) { - Kernel* kernel = sobel_program_.compile( - SobelFilter_cl, "sobel_filter_kernel"); + /*Kernel* kernel = sobel_program_.compile( + SobelFilter_cl, "sobel_filter_kernel");*/ + + kernel_->block2d(BX, BY); + kernel_->grid2d((width-1)/BX+1, (height-1)/BY+1); - kernel->block2d(BX, BY); - kernel->grid2d((width-1)/BX+1, (height-1)/BY+1); + kernel_->addBufferArg(input); + kernel_->addBufferArg(output); + kernel_->addArg(width); + kernel_->addArg(height); + kernel_->addArg(scale_); + kernel_->addArg(blend_); - kernel->addBufferArg(input); - kernel->addBufferArg(output); - kernel->addArg(width); - kernel->addArg(height); - kernel->addArg(scale_); - kernel->addArg(blend_); + kernel_->launch(); - kernel->launch(); + kernel_->reset(); - delete kernel; + //delete kernel; } } } // namespace xromm::opencl diff --git a/libautoscoper/src/gpu/opencl/SobelFilter.hpp b/libautoscoper/src/gpu/opencl/SobelFilter.hpp index 3e6ed19d..b080ceba 100644 --- a/libautoscoper/src/gpu/opencl/SobelFilter.hpp +++ b/libautoscoper/src/gpu/opencl/SobelFilter.hpp @@ -53,7 +53,7 @@ class SobelFilter : public Filter { public: SobelFilter(); - virtual ~SobelFilter() {} + ~SobelFilter() { if (kernel_) delete kernel_; } // Apply the filter to the input image virtual void apply(const Buffer* input, @@ -71,6 +71,8 @@ class SobelFilter : public Filter private: float scale_; float blend_; + + Kernel* kernel_; }; } } // namespace xromm::opencl