1 module oclcv.morphed; 2 3 import oclcv.clcore; 4 5 import dplug.core.nogc; 6 import bc.string; 7 8 alias MORPH_OP = int; 9 enum : MORPH_OP { 10 ERODE, 11 DILATE 12 } 13 14 final class MorphED { 15 public: 16 @nogc nothrow: 17 this(int height, int width, MORPH_OP op, int kernelSize, CLContext ctx){ 18 19 width_ = width; height_= height; _op = op; kernelSize_ = kernelSize; 20 21 initialize(ctx); 22 } 23 24 ~this(){ 25 destroyFree(prog_); 26 } 27 28 private bool initialize(CLContext ctx){ 29 if(!ctx) 30 return false; 31 context_ = ctx; 32 33 tile_w = width_; 34 tile_h = 1; 35 36 block2 = BlockDim(tile_w + (2 * kernelSize_), tile_h); 37 38 import std.conv : to; 39 40 auto compilerParam = RCStringZ.from(nogcFormat!"-D %s -D SHARED_SIZE=%d -D radio=%d"( 41 ((_op==ERODE)?"ERODE":"DILATE"), block2.y*block2.x, kernelSize_ )); 42 prog_ = mallocNew!CLProgram(CTKernel.KMORPHED, context_, compilerParam[]); 43 44 _kernel_step1 = prog_.getKernel("morphSharedStep1"); 45 _kernel_step2 = prog_.getKernel("morphSharedStep2"); 46 47 return true; 48 } 49 50 CLBuffer run(CLBuffer d_src_mono, CLBuffer ownedBuffer = null){ 51 52 import core.stdc.math : ceil; 53 54 debug _assert(d_src_mono.metaData.dataType == UBYTE, "Input type must be ubyte"); 55 debug _assert(d_src_mono.metaData.numberOfChannels == 1, "Input's channel count must be 1"); 56 57 CLBuffer d_output; 58 if(ownedBuffer is null){ 59 d_output = mallocNew!CLBuffer(context_, BufferMeta(UBYTE, height_, width_, 1)); 60 } else { 61 d_output = ownedBuffer; 62 } 63 64 CLBuffer d_tmp = mallocNew!CLBuffer(context_, BufferMeta(UBYTE, height_, width_, 1)); 65 66 tile_w = width_; 67 tile_h = 1; 68 69 block2 = BlockDim(tile_w + (2 * kernelSize_), tile_h); 70 71 _kernel_step1.setArgs(d_src_mono, d_tmp, width_, height_, tile_w, tile_h); 72 73 _kernel_step1.launch(0, GridDim(cast(int)ceil(cast(float)width_ / tile_w), 74 cast(int)ceil(cast(float)height_ / tile_h)), 75 block2); 76 context_.finish(0); 77 78 tile_w = 8; 79 tile_h = 64; 80 81 _kernel_step2.setArgs(d_tmp, d_output, width_, height_, tile_w, tile_h); 82 83 _kernel_step2.launch(0, 84 GridDim(cast(int)ceil(cast(float)width_ / tile_w), cast(int)ceil(cast(float)height_ / tile_h)), 85 BlockDim(tile_w, tile_h + (2 * kernelSize_))); 86 context_.finish(0); 87 88 destroyFree(d_tmp); 89 90 return d_output; 91 } 92 93 private: 94 int width_, height_; 95 int kernelSize_; 96 int tile_w; 97 int tile_h; 98 BlockDim block2; 99 CLContext context_; 100 CLProgram prog_; 101 102 CLKernel _kernel_step1; 103 CLKernel _kernel_step2; 104 MORPH_OP _op; 105 }