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 }