1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 #include "shared/source/device/device.h"
10 #include "shared/source/helpers/hash.h"
11 #include "shared/source/helpers/string.h"
12 #include "shared/source/program/kernel_info.h"
13 
14 #include "opencl/source/cl_device/cl_device.h"
15 #include "opencl/source/kernel/multi_device_kernel.h"
16 #include "opencl/source/program/program.h"
17 
18 #include "gmock/gmock.h"
19 
20 #include <string>
21 
22 namespace NEO {
23 
24 class GraphicsAllocation;
25 ClDeviceVector toClDeviceVector(ClDevice &clDevice);
26 ////////////////////////////////////////////////////////////////////////////////
27 // Program - Core implementation
28 ////////////////////////////////////////////////////////////////////////////////
29 class MockProgram : public Program {
30   public:
31     using Program::allowNonUniform;
32     using Program::applyAdditionalOptions;
33     using Program::areSpecializationConstantsInitialized;
34     using Program::blockKernelManager;
35     using Program::buildInfos;
36     using Program::context;
37     using Program::createdFrom;
38     using Program::createProgramFromBinary;
39     using Program::debugData;
40     using Program::debugDataSize;
41     using Program::deviceBuildInfos;
42     using Program::extractInternalOptions;
43     using Program::getKernelInfo;
44     using Program::internalOptionsToExtract;
45     using Program::irBinary;
46     using Program::irBinarySize;
47     using Program::isBuiltIn;
48     using Program::isSpirV;
49     using Program::kernelDebugEnabled;
50     using Program::linkBinary;
51     using Program::options;
52     using Program::packDeviceBinary;
53     using Program::Program;
54     using Program::separateBlockKernels;
55     using Program::setBuildStatus;
56     using Program::shouldWarnAboutRebuild;
57     using Program::sourceCode;
58     using Program::specConstantsIds;
59     using Program::specConstantsSizes;
60     using Program::specConstantsValues;
61     using Program::updateNonUniformFlag;
62 
MockProgram(const ClDeviceVector & deviceVector)63     MockProgram(const ClDeviceVector &deviceVector) : Program(nullptr, false, deviceVector) {
64     }
65 
~MockProgram()66     ~MockProgram() override {
67         if (contextSet)
68             context = nullptr;
69     }
70     KernelInfo mockKernelInfo;
setBuildOptions(const char * buildOptions)71     void setBuildOptions(const char *buildOptions) {
72         options = buildOptions != nullptr ? buildOptions : "";
73     }
getInitInternalOptions()74     std::string getInitInternalOptions() const {
75         std::string internalOptions;
76         initInternalOptions(internalOptions);
77         return internalOptions;
78     };
setConstantSurface(GraphicsAllocation * gfxAllocation)79     void setConstantSurface(GraphicsAllocation *gfxAllocation) {
80         if (gfxAllocation) {
81             buildInfos[gfxAllocation->getRootDeviceIndex()].constantSurface = gfxAllocation;
82         } else {
83             for (auto &buildInfo : buildInfos) {
84                 buildInfo.constantSurface = nullptr;
85             }
86         }
87     }
setGlobalSurface(GraphicsAllocation * gfxAllocation)88     void setGlobalSurface(GraphicsAllocation *gfxAllocation) {
89         if (gfxAllocation) {
90             buildInfos[gfxAllocation->getRootDeviceIndex()].globalSurface = gfxAllocation;
91         } else {
92             for (auto &buildInfo : buildInfos) {
93                 buildInfo.globalSurface = nullptr;
94             }
95         }
96     }
getKernelInfoArray(uint32_t rootDeviceIndex)97     std::vector<KernelInfo *> &getKernelInfoArray(uint32_t rootDeviceIndex) {
98         return buildInfos[rootDeviceIndex].kernelInfoArray;
99     }
addKernelInfo(KernelInfo * inInfo,uint32_t rootDeviceIndex)100     void addKernelInfo(KernelInfo *inInfo, uint32_t rootDeviceIndex) {
101         buildInfos[rootDeviceIndex].kernelInfoArray.push_back(inInfo);
102     }
getParentKernelInfoArray(uint32_t rootDeviceIndex)103     std::vector<KernelInfo *> &getParentKernelInfoArray(uint32_t rootDeviceIndex) {
104         return buildInfos[rootDeviceIndex].parentKernelInfoArray;
105     }
getSubgroupKernelInfoArray(uint32_t rootDeviceIndex)106     std::vector<KernelInfo *> &getSubgroupKernelInfoArray(uint32_t rootDeviceIndex) {
107         return buildInfos[rootDeviceIndex].subgroupKernelInfoArray;
108     }
setContext(Context * context)109     void setContext(Context *context) {
110         this->context = context;
111         contextSet = true;
112     }
setSourceCode(const char * ptr)113     void setSourceCode(const char *ptr) { sourceCode = ptr; }
clearOptions()114     void clearOptions() { options = ""; }
setCreatedFromBinary(bool createdFromBin)115     void setCreatedFromBinary(bool createdFromBin) { isCreatedFromBinary = createdFromBin; }
clearLog(uint32_t rootDeviceIndex)116     void clearLog(uint32_t rootDeviceIndex) { buildInfos[rootDeviceIndex].buildLog.clear(); }
117 
setIrBinary(char * ptr,bool isSpirv)118     void setIrBinary(char *ptr, bool isSpirv) {
119         irBinary.reset(ptr);
120         this->isSpirV = isSpirV;
121     }
setIrBinarySize(size_t bsz,bool isSpirv)122     void setIrBinarySize(size_t bsz, bool isSpirv) {
123         irBinarySize = bsz;
124         this->isSpirV = isSpirV;
125     }
126 
127     std::string getCachedFileName() const;
setAllowNonUniform(bool allow)128     void setAllowNonUniform(bool allow) {
129         allowNonUniform = allow;
130     }
131 
isFlagOption(ConstStringRef option)132     bool isFlagOption(ConstStringRef option) override {
133         if (isFlagOptionOverride != -1) {
134             return (isFlagOptionOverride > 0);
135         }
136         return Program::isFlagOption(option);
137     }
138 
isOptionValueValid(ConstStringRef option,ConstStringRef value)139     bool isOptionValueValid(ConstStringRef option, ConstStringRef value) override {
140         if (isOptionValueValidOverride != -1) {
141             return (isOptionValueValidOverride > 0);
142         }
143         return Program::isOptionValueValid(option, value);
144     }
145 
rebuildProgramFromIr()146     cl_int rebuildProgramFromIr() {
147         this->isCreatedFromBinary = false;
148         this->shouldWarnAboutRebuild = true;
149         setBuildStatus(CL_BUILD_NONE);
150         std::unordered_map<std::string, BuiltinDispatchInfoBuilder *> builtins;
151         return this->build(getDevices(), this->options.c_str(), false, builtins);
152     }
153 
recompile()154     cl_int recompile() {
155         this->isCreatedFromBinary = false;
156         this->shouldWarnAboutRebuild = true;
157         setBuildStatus(CL_BUILD_NONE);
158         return this->compile(getDevices(), this->options.c_str(), 0, nullptr, nullptr);
159     }
160 
replaceDeviceBinary(std::unique_ptr<char[]> && newBinary,size_t newBinarySize,uint32_t rootDeviceIndex)161     void replaceDeviceBinary(std::unique_ptr<char[]> &&newBinary, size_t newBinarySize, uint32_t rootDeviceIndex) override {
162         if (replaceDeviceBinaryCalledPerRootDevice.find(rootDeviceIndex) == replaceDeviceBinaryCalledPerRootDevice.end()) {
163             replaceDeviceBinaryCalledPerRootDevice.insert({rootDeviceIndex, 1});
164         } else {
165             replaceDeviceBinaryCalledPerRootDevice[rootDeviceIndex]++;
166         }
167         Program::replaceDeviceBinary(std::move(newBinary), newBinarySize, rootDeviceIndex);
168     }
processGenBinary(const ClDevice & clDevice)169     cl_int processGenBinary(const ClDevice &clDevice) override {
170         auto rootDeviceIndex = clDevice.getRootDeviceIndex();
171         if (processGenBinaryCalledPerRootDevice.find(rootDeviceIndex) == processGenBinaryCalledPerRootDevice.end()) {
172             processGenBinaryCalledPerRootDevice.insert({rootDeviceIndex, 1});
173         } else {
174             processGenBinaryCalledPerRootDevice[rootDeviceIndex]++;
175         }
176         return Program::processGenBinary(clDevice);
177     }
178 
initInternalOptions(std::string & internalOptions)179     void initInternalOptions(std::string &internalOptions) const override {
180         initInternalOptionsCalled++;
181         Program::initInternalOptions(internalOptions);
182     };
183 
getKernelInfoForKernel(const char * kernelName)184     const KernelInfo &getKernelInfoForKernel(const char *kernelName) const {
185         return *getKernelInfo(kernelName, getDevices()[0]->getRootDeviceIndex());
186     }
187 
getKernelInfosForKernel(const char * kernelName)188     const KernelInfoContainer getKernelInfosForKernel(const char *kernelName) const {
189         KernelInfoContainer kernelInfos;
190         kernelInfos.resize(getMaxRootDeviceIndex() + 1);
191         for (auto i = 0u; i < kernelInfos.size(); i++) {
192             kernelInfos[i] = getKernelInfo(kernelName, i);
193         }
194         return kernelInfos;
195     }
196 
197     std::map<uint32_t, int> processGenBinaryCalledPerRootDevice;
198     std::map<uint32_t, int> replaceDeviceBinaryCalledPerRootDevice;
199     static int initInternalOptionsCalled;
200     bool contextSet = false;
201     int isFlagOptionOverride = -1;
202     int isOptionValueValidOverride = -1;
203 };
204 
205 class GMockProgram : public Program {
206   public:
207     using Program::Program;
208     MOCK_METHOD(bool, appendKernelDebugOptions, (ClDevice &, std::string &), (override));
209 };
210 
211 } // namespace NEO
212