1 module oclcv.countnonzero; 2 3 import oclcv.clcore; 4 import std.array; 5 import dplug.core.nogc; 6 import bc.string; 7 8 final class CountNonZero { 9 public: 10 @nogc nothrow: 11 this(int height, int width, string comparisonOP, CLContext ctx){ 12 13 import std.algorithm: canFind; 14 15 if(!["<", ">", "<=", ">=", "==", "!="].staticArray[].canFind(comparisonOP)){ 16 debug _assert(0, `unsupported OP. Please use one of these OPs: "<", ">", "<=", ">=", "==", "!="`); 17 } 18 19 width_ = width; height_= height; _comparisonOP = comparisonOP; 20 initialize(ctx); 21 } 22 23 ~this(){ 24 destroyFree(prog_); 25 } 26 27 private bool initialize(CLContext ctx){ 28 if(!ctx) 29 return false; 30 context_ = ctx; 31 32 prog_ = mallocNew!CLProgram(CTKernel.KCOUNTNONZERO, context_, RCStringZ.from("-D OP=", _comparisonOP)[]); 33 _kernel = prog_.getKernel("countNonZero"); 34 35 return true; 36 } 37 38 @nogc nothrow: 39 ulong run(CLBuffer d_src_mono, ubyte cval){ 40 debug _assert(d_src_mono.metaData.dataType == UBYTE, "Input type must be ubyte"); 41 debug _assert(d_src_mono.metaData.numberOfChannels == 1, "Input's channel count must be 1"); 42 43 CLBuffer d_count = mallocNew!CLBuffer(context_, BufferMeta(ULONG, 1, 1, 1)); 44 45 ulong ret; 46 d_count.upload((&ret)[0..1]); 47 48 int[2] sz = [width_, height_]; 49 _kernel.setArgs(d_src_mono, cval, d_count, sz); 50 51 compute(); 52 d_count.download((&ret)[0..1]); 53 destroyFree(d_count); 54 return ret; 55 } 56 57 private void compute(){ 58 _kernel.launch(0, GridDim((width_ + 16 - 1)/16, (height_ + 16 - 1)/16), 59 BlockDim(16,16)); 60 context_.finish(0); 61 } 62 63 private: 64 int width_, height_; 65 string _comparisonOP; 66 CLContext context_; 67 CLProgram prog_; 68 69 CLKernel _kernel; 70 }