1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 #include "opencl_backend.h"
 27 
 28 
 29 /*
 30   OpenCLBuffer
 31   */
 32 
 33 OpenCLBackend::OpenCLBuffer::OpenCLBuffer(Backend *backend, Arg_s *arg, BufferState_s *bufferState)
 34         : Backend::Buffer(backend, arg, bufferState) {
 35     cl_int status;
 36     OpenCLBackend * openclBackend = dynamic_cast<OpenCLBackend *>(backend);
 37     clMem = clCreateBuffer(
 38         openclBackend->context,
 39         CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE,
 40         bufferState->length,// arg->value.buffer.sizeInBytes,
 41         arg->value.buffer.memorySegment,
 42         &status);
 43 
 44     if (status != CL_SUCCESS) {
 45         std::cerr << OpenCLBackend::errorMsg(status) << std::endl;
 46         exit(1);
 47     }
 48      bufferState->vendorPtr =  static_cast<void *>(this);
 49     if (openclBackend->openclConfig.traceCopies){
 50         std::cout << "created buffer for arg idx "<< arg->idx << std::endl;
 51     }
 52 
 53 }
 54 
 55 bool OpenCLBackend::OpenCLBuffer::shouldCopyToDevice( Arg_s *arg){
 56 //std::cout << "shouldCopyToDevice( Arg_s *arg)" <<std::endl;
 57 // std::cout <<std::hex;
 58 //// std::cout << "arg=="<<((long) arg) <<std::endl;
 59 // std::cout << "arg->idx=="<<arg->idx <<std::endl;
 60  //  std::cout << "bufferState=="<<((long) bufferState) <<std::endl;
 61   //  std::cout << "kernel=="<<((long) kernel) <<std::endl;
 62   //    std::cout << "kernel->name=="<<kernel->name <<std::endl;
 63   //   std::cout << "kernel->program=="<<((long) kernel->program) <<std::endl;
 64    //   std::cout << "kernel->program->backend=="<<((long) kernel->program->backend) <<std::endl;
 65    //   std::cout <<std::dec;
 66          OpenCLBackend * openclBackend = dynamic_cast<OpenCLBackend *>(backend);
 67 
 68 
 69    bool kernelReadsFromThisArg = (arg->value.buffer.access==RW_BYTE) || (arg->value.buffer.access==RO_BYTE);
 70    bool isAlwaysCopyingOrNewStateOrHostOwned =
 71         openclBackend->openclConfig.alwaysCopy
 72         ||  (bufferState->state == BufferState_s::NEW_STATE)
 73         || ((bufferState->state == BufferState_s::HOST_OWNED));
 74 
 75    if (openclBackend->openclConfig.showWhy){
 76        std::cout<<
 77                    "config.alwaysCopy="<<openclBackend->openclConfig.alwaysCopy
 78                    << " | arg.RW="<<(arg->value.buffer.access==RW_BYTE)
 79                    << " | arg.RO="<<(arg->value.buffer.access==RO_BYTE)
 80                    << " | kernel.needsToRead="<<  kernelReadsFromThisArg
 81                    << " | Buffer state = "<< BufferState_s::stateNames[bufferState->state]
 82                    <<" so "
 83                      ;
 84      }
 85      return isAlwaysCopyingOrNewStateOrHostOwned;
 86 }
 87 bool OpenCLBackend::OpenCLBuffer::shouldCopyFromDevice(Arg_s *arg){
 88    OpenCLBackend * openclBackend = dynamic_cast<OpenCLBackend *>(backend);
 89  bool kernelWroteToThisArg = (arg->value.buffer.access==WO_BYTE) |  (arg->value.buffer.access==RW_BYTE);
 90        if (openclBackend->openclConfig.showWhy){
 91            std::cout<<
 92              "config.alwaysCopy="<<openclBackend->openclConfig.alwaysCopy
 93                 << " | arg.WO="<<(arg->value.buffer.access==WO_BYTE)
 94                 << " | arg.RW="<<(arg->value.buffer.access==RW_BYTE)
 95                 << " | kernel.wroteToThisArg="<<  kernelWroteToThisArg
 96                 << "Buffer state = "<< BufferState_s::stateNames[bufferState->state]
 97                 <<" so " ;
 98        }
 99        return openclBackend->openclConfig.alwaysCopy;
100 }
101 
102 
103 void OpenCLBackend::OpenCLBuffer::copyToDevice() {
104   //  OpenCLKernel *openclKernel = dynamic_cast<OpenCLKernel *>(kernel);
105     OpenCLBackend *openclBackend = dynamic_cast<OpenCLBackend *>(backend);
106    //  std::cout << "copyTo(" <<std::hex << (long) arg->value.buffer.memorySegment << "," << std::dec<<   bufferState->length <<")"<<std::endl;
107 
108     cl_int status = clEnqueueWriteBuffer(
109        openclBackend->openclQueue.command_queue,
110        clMem,
111        CL_FALSE,
112        0,
113        bufferState->length, // arg->value.buffer.sizeInBytes,
114        arg->value.buffer.memorySegment,
115        openclBackend->openclQueue.eventc,
116        openclBackend->openclQueue.eventListPtr(),
117        openclBackend->openclQueue.nextEventPtr()
118     );
119     openclBackend->openclQueue.markAsCopyToDeviceAndInc(arg->idx);
120 
121     if (status != CL_SUCCESS) {
122         std::cerr << OpenCLBackend::errorMsg(status) << std::endl;
123         exit(1);
124     }
125     if(openclBackend->openclConfig.traceCopies){
126         std::cout << "enqueued buffer for arg idx " << arg->idx << " in OpenCLBuffer::copyToDevice()" << std::endl;
127     }
128 }
129 
130 void OpenCLBackend::OpenCLBuffer::copyFromDevice() {
131 //    OpenCLKernel * openclKernel = dynamic_cast<OpenCLKernel *>(kernel);
132     OpenCLBackend * openclBackend = dynamic_cast<OpenCLBackend *>(backend);
133  //  std::cout << "copyFrom(" <<std::hex << (long) arg->value.buffer.memorySegment << "," << std::dec<<   bufferState->length <<")"<<std::endl;
134 
135     cl_int status = clEnqueueReadBuffer(
136        openclBackend->openclQueue.command_queue,
137        clMem,
138        CL_FALSE,
139        0,
140        bufferState->length,//arg->value.buffer.sizeInBytes,
141        arg->value.buffer.memorySegment,
142        openclBackend->openclQueue.eventc,
143        openclBackend->openclQueue.eventListPtr(),
144        openclBackend->openclQueue.nextEventPtr()
145     );
146     openclBackend->openclQueue.markAsCopyFromDeviceAndInc(arg->idx);
147     if (status != CL_SUCCESS) {
148         std::cerr << OpenCLBackend::errorMsg(status) << std::endl;
149         exit(1);
150     }
151     if(openclBackend->openclConfig.traceCopies){
152        std::cout << "enqueued buffer for arg idx " << arg->idx << " in OpenCLBuffer::copyFromDevice()" << std::endl;
153     }
154 }
155 
156 OpenCLBackend::OpenCLBuffer::~OpenCLBuffer() {
157     clReleaseMemObject(clMem);
158 }
159 
160