1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "opencl/source/mem_obj/image.h"
9 
10 #include "shared/source/debug_settings/debug_settings_manager.h"
11 #include "shared/source/gmm_helper/gmm.h"
12 #include "shared/source/gmm_helper/resource_info.h"
13 #include "shared/source/helpers/aligned_memory.h"
14 #include "shared/source/helpers/basic_math.h"
15 #include "shared/source/helpers/get_info.h"
16 #include "shared/source/helpers/hw_helper.h"
17 #include "shared/source/helpers/hw_info.h"
18 #include "shared/source/helpers/ptr_math.h"
19 #include "shared/source/helpers/string.h"
20 #include "shared/source/memory_manager/memory_manager.h"
21 
22 #include "opencl/source/cl_device/cl_device.h"
23 #include "opencl/source/cl_device/cl_device_get_cap.inl"
24 #include "opencl/source/command_queue/command_queue.h"
25 #include "opencl/source/context/context.h"
26 #include "opencl/source/helpers/cl_hw_helper.h"
27 #include "opencl/source/helpers/cl_memory_properties_helpers.h"
28 #include "opencl/source/helpers/get_info_status_mapper.h"
29 #include "opencl/source/helpers/gmm_types_converter.h"
30 #include "opencl/source/helpers/mipmap.h"
31 #include "opencl/source/helpers/surface_formats.h"
32 #include "opencl/source/mem_obj/buffer.h"
33 #include "opencl/source/mem_obj/mem_obj_helper.h"
34 #include "opencl/source/platform/platform.h"
35 
36 #include "igfxfmid.h"
37 
38 #include <map>
39 
40 namespace NEO {
41 
42 ImageFactoryFuncs imageFactory[IGFX_MAX_CORE] = {};
43 
44 namespace ImageFunctions {
45 ValidateAndCreateImageFunc validateAndCreateImage = Image::validateAndCreateImage;
46 } // namespace ImageFunctions
47 
Image(Context * context,const MemoryProperties & memoryProperties,cl_mem_flags flags,cl_mem_flags_intel flagsIntel,size_t size,void * memoryStorage,void * hostPtr,cl_image_format imageFormat,const cl_image_desc & imageDesc,bool zeroCopy,MultiGraphicsAllocation multiGraphicsAllocation,bool isObjectRedescribed,uint32_t baseMipLevel,uint32_t mipCount,const ClSurfaceFormatInfo & surfaceFormatInfo,const SurfaceOffsets * surfaceOffsets)48 Image::Image(Context *context,
49              const MemoryProperties &memoryProperties,
50              cl_mem_flags flags,
51              cl_mem_flags_intel flagsIntel,
52              size_t size,
53              void *memoryStorage,
54              void *hostPtr,
55              cl_image_format imageFormat,
56              const cl_image_desc &imageDesc,
57              bool zeroCopy,
58              MultiGraphicsAllocation multiGraphicsAllocation,
59              bool isObjectRedescribed,
60              uint32_t baseMipLevel,
61              uint32_t mipCount,
62              const ClSurfaceFormatInfo &surfaceFormatInfo,
63              const SurfaceOffsets *surfaceOffsets)
64     : MemObj(context,
65              imageDesc.image_type,
66              memoryProperties,
67              flags,
68              flagsIntel,
69              size,
70              memoryStorage,
71              hostPtr,
72              std::move(multiGraphicsAllocation),
73              zeroCopy,
74              false,
75              isObjectRedescribed),
76       createFunction(nullptr),
77       imageFormat(std::move(imageFormat)),
78       imageDesc(imageDesc),
79       surfaceFormatInfo(surfaceFormatInfo),
80       cubeFaceIndex(__GMM_NO_CUBE_MAP),
81       mediaPlaneType(0),
82       baseMipLevel(baseMipLevel),
83       mipCount(mipCount) {
84     magic = objectMagic;
85     if (surfaceOffsets)
86         setSurfaceOffsets(surfaceOffsets->offset, surfaceOffsets->xOffset, surfaceOffsets->yOffset, surfaceOffsets->yOffsetForUVplane);
87     else
88         setSurfaceOffsets(0, 0, 0, 0);
89 }
90 
transferData(void * dest,size_t destRowPitch,size_t destSlicePitch,void * src,size_t srcRowPitch,size_t srcSlicePitch,std::array<size_t,3> copyRegion,std::array<size_t,3> copyOrigin)91 void Image::transferData(void *dest, size_t destRowPitch, size_t destSlicePitch,
92                          void *src, size_t srcRowPitch, size_t srcSlicePitch,
93                          std::array<size_t, 3> copyRegion, std::array<size_t, 3> copyOrigin) {
94 
95     size_t pixelSize = surfaceFormatInfo.surfaceFormat.ImageElementSizeInBytes;
96     size_t lineWidth = copyRegion[0] * pixelSize;
97 
98     DBG_LOG(LogMemoryObject, __FUNCTION__, "memcpy dest:", dest, "sizeRowToCopy:", lineWidth, "src:", src);
99 
100     if (imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY) {
101         // For 1DArray type, array region and origin are stored on 2nd position. For 2Darray its on 3rd position.
102         std::swap(copyOrigin[1], copyOrigin[2]);
103         std::swap(copyRegion[1], copyRegion[2]);
104     }
105 
106     for (size_t slice = copyOrigin[2]; slice < (copyOrigin[2] + copyRegion[2]); slice++) {
107         auto srcSliceOffset = ptrOffset(src, srcSlicePitch * slice);
108         auto dstSliceOffset = ptrOffset(dest, destSlicePitch * slice);
109 
110         for (size_t height = copyOrigin[1]; height < (copyOrigin[1] + copyRegion[1]); height++) {
111             auto srcRowOffset = ptrOffset(srcSliceOffset, srcRowPitch * height);
112             auto dstRowOffset = ptrOffset(dstSliceOffset, destRowPitch * height);
113 
114             memcpy_s(ptrOffset(dstRowOffset, copyOrigin[0] * pixelSize), lineWidth,
115                      ptrOffset(srcRowOffset, copyOrigin[0] * pixelSize), lineWidth);
116         }
117     }
118 }
119 
120 Image::~Image() = default;
121 
create(Context * context,const MemoryProperties & memoryProperties,cl_mem_flags flags,cl_mem_flags_intel flagsIntel,const ClSurfaceFormatInfo * surfaceFormat,const cl_image_desc * imageDesc,const void * hostPtr,cl_int & errcodeRet)122 Image *Image::create(Context *context,
123                      const MemoryProperties &memoryProperties,
124                      cl_mem_flags flags,
125                      cl_mem_flags_intel flagsIntel,
126                      const ClSurfaceFormatInfo *surfaceFormat,
127                      const cl_image_desc *imageDesc,
128                      const void *hostPtr,
129                      cl_int &errcodeRet) {
130     UNRECOVERABLE_IF(surfaceFormat == nullptr);
131 
132     Image *image = nullptr;
133     MemoryManager *memoryManager = context->getMemoryManager();
134 
135     Buffer *parentBuffer = castToObject<Buffer>(imageDesc->mem_object);
136     Image *parentImage = castToObject<Image>(imageDesc->mem_object);
137 
138     auto &defaultHwHelper = HwHelper::get(context->getDevice(0)->getHardwareInfo().platform.eRenderCoreFamily);
139 
140     bool transferedMemory = false;
141     do {
142         size_t imageWidth = imageDesc->image_width;
143         size_t imageHeight = 1;
144         size_t imageDepth = 1;
145         size_t imageCount = 1;
146         size_t hostPtrMinSize = 0;
147 
148         cl_image_desc imageDescriptor = *imageDesc;
149         ImageInfo imgInfo = {};
150         void *hostPtrToSet = nullptr;
151 
152         if (memoryProperties.flags.useHostPtr) {
153             hostPtrToSet = const_cast<void *>(hostPtr);
154         }
155 
156         imgInfo.imgDesc = Image::convertDescriptor(imageDescriptor);
157         imgInfo.surfaceFormat = &surfaceFormat->surfaceFormat;
158         imgInfo.mipCount = imageDesc->num_mip_levels;
159 
160         if (imageDesc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY || imageDesc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY) {
161             imageCount = imageDesc->image_array_size;
162         }
163 
164         switch (imageDesc->image_type) {
165         case CL_MEM_OBJECT_IMAGE3D:
166             imageDepth = imageDesc->image_depth;
167             [[fallthrough]];
168         case CL_MEM_OBJECT_IMAGE2D:
169         case CL_MEM_OBJECT_IMAGE2D_ARRAY:
170             imageHeight = imageDesc->image_height;
171         case CL_MEM_OBJECT_IMAGE1D:
172         case CL_MEM_OBJECT_IMAGE1D_ARRAY:
173         case CL_MEM_OBJECT_IMAGE1D_BUFFER:
174             break;
175         default:
176             DEBUG_BREAK_IF("Unsupported cl_image_type");
177             break;
178         }
179 
180         if (parentImage) {
181             imageWidth = parentImage->getImageDesc().image_width;
182             imageHeight = parentImage->getImageDesc().image_height;
183             imageDepth = 1;
184             if (isNV12Image(&parentImage->getImageFormat())) {
185                 if (imageDesc->image_depth == 1) { // UV Plane
186                     imageWidth /= 2;
187                     imageHeight /= 2;
188                     imgInfo.plane = GMM_PLANE_U;
189                 } else {
190                     imgInfo.plane = GMM_PLANE_Y;
191                 }
192             }
193 
194             imgInfo.surfaceFormat = &parentImage->surfaceFormatInfo.surfaceFormat;
195             imageDescriptor = parentImage->getImageDesc();
196         }
197 
198         auto hostPtrRowPitch = imageDesc->image_row_pitch ? imageDesc->image_row_pitch : imageWidth * surfaceFormat->surfaceFormat.ImageElementSizeInBytes;
199         auto hostPtrSlicePitch = imageDesc->image_slice_pitch ? imageDesc->image_slice_pitch : hostPtrRowPitch * imageHeight;
200         auto &clHwHelper = ClHwHelper::get(context->getDevice(0)->getHardwareInfo().platform.eRenderCoreFamily);
201         imgInfo.linearStorage = !defaultHwHelper.tilingAllowed(context->isSharedContext, Image::isImage1d(*imageDesc),
202                                                                memoryProperties.flags.forceLinearStorage);
203         bool preferCompression = MemObjHelper::isSuitableForCompression(!imgInfo.linearStorage, memoryProperties,
204                                                                         *context, true);
205         preferCompression &= clHwHelper.allowImageCompression(surfaceFormat->OCLImageFormat);
206         preferCompression &= !clHwHelper.isFormatRedescribable(surfaceFormat->OCLImageFormat);
207 
208         if (!context->getDevice(0)->getSharedDeviceInfo().imageSupport && !imgInfo.linearStorage) {
209             errcodeRet = CL_INVALID_OPERATION;
210             return nullptr;
211         }
212 
213         switch (imageDesc->image_type) {
214         case CL_MEM_OBJECT_IMAGE3D:
215             hostPtrMinSize = hostPtrSlicePitch * imageDepth;
216             break;
217         case CL_MEM_OBJECT_IMAGE2D:
218             if (isNV12Image(&surfaceFormat->OCLImageFormat)) {
219                 hostPtrMinSize = hostPtrRowPitch * imageHeight + hostPtrRowPitch * imageHeight / 2;
220             } else {
221                 hostPtrMinSize = hostPtrRowPitch * imageHeight;
222             }
223             hostPtrSlicePitch = 0;
224             break;
225         case CL_MEM_OBJECT_IMAGE1D_ARRAY:
226         case CL_MEM_OBJECT_IMAGE2D_ARRAY:
227             hostPtrMinSize = hostPtrSlicePitch * imageCount;
228             break;
229         case CL_MEM_OBJECT_IMAGE1D:
230         case CL_MEM_OBJECT_IMAGE1D_BUFFER:
231             hostPtrMinSize = hostPtrRowPitch;
232             hostPtrSlicePitch = 0;
233             break;
234         default:
235             DEBUG_BREAK_IF("Unsupported cl_image_type");
236             break;
237         }
238 
239         auto maxRootDeviceIndex = context->getMaxRootDeviceIndex();
240         auto multiGraphicsAllocation = MultiGraphicsAllocation(maxRootDeviceIndex);
241 
242         AllocationInfoType allocationInfo;
243         allocationInfo.resize(maxRootDeviceIndex + 1u);
244         bool isParentObject = parentBuffer || parentImage;
245 
246         for (auto &rootDeviceIndex : context->getRootDeviceIndices()) {
247             allocationInfo[rootDeviceIndex] = {};
248             allocationInfo[rootDeviceIndex].zeroCopyAllowed = false;
249 
250             Gmm *gmm = nullptr;
251             auto &hwInfo = *memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo();
252             auto &hwHelper = HwHelper::get((&memoryManager->peekExecutionEnvironment())->rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo()->platform.eRenderCoreFamily);
253             auto clientContext = (&memoryManager->peekExecutionEnvironment())->rootDeviceEnvironments[rootDeviceIndex]->getGmmClientContext();
254 
255             if (((imageDesc->image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER) || (imageDesc->image_type == CL_MEM_OBJECT_IMAGE2D)) && (parentBuffer != nullptr)) {
256 
257                 allocationInfo[rootDeviceIndex].memory = parentBuffer->getGraphicsAllocation(rootDeviceIndex);
258                 if (!hwHelper.checkResourceCompatibility(*allocationInfo[rootDeviceIndex].memory)) {
259                     cleanAllGraphicsAllocations(*context, *memoryManager, allocationInfo, isParentObject);
260                     errcodeRet = CL_INVALID_MEM_OBJECT;
261                     return nullptr;
262                 }
263 
264                 // Image from buffer - we never allocate memory, we use what buffer provides
265                 allocationInfo[rootDeviceIndex].zeroCopyAllowed = true;
266                 hostPtr = parentBuffer->getHostPtr();
267                 hostPtrToSet = const_cast<void *>(hostPtr);
268                 parentBuffer->incRefInternal();
269                 GmmTypesConverter::queryImgFromBufferParams(imgInfo, allocationInfo[rootDeviceIndex].memory);
270 
271                 UNRECOVERABLE_IF(imgInfo.offset != 0);
272                 imgInfo.offset = parentBuffer->getOffset();
273 
274                 if (memoryManager->peekVirtualPaddingSupport() && (imageDesc->image_type == CL_MEM_OBJECT_IMAGE2D) && (allocationInfo[rootDeviceIndex].memory->getUnderlyingBuffer() != 0)) {
275                     // Retrieve sizes from GMM and apply virtual padding if buffer storage is not big enough
276                     auto queryGmmImgInfo(imgInfo);
277                     auto gmm = std::make_unique<Gmm>(clientContext, queryGmmImgInfo, StorageInfo{}, preferCompression);
278                     auto gmmAllocationSize = gmm->gmmResourceInfo->getSizeAllocation();
279                     if (gmmAllocationSize > allocationInfo[rootDeviceIndex].memory->getUnderlyingBufferSize()) {
280                         allocationInfo[rootDeviceIndex].memory = memoryManager->createGraphicsAllocationWithPadding(allocationInfo[rootDeviceIndex].memory, gmmAllocationSize);
281                     }
282                 }
283             } else if (parentImage != nullptr) {
284                 allocationInfo[rootDeviceIndex].memory = parentImage->getGraphicsAllocation(rootDeviceIndex);
285                 allocationInfo[rootDeviceIndex].memory->getDefaultGmm()->queryImageParams(imgInfo);
286             } else {
287                 errcodeRet = CL_OUT_OF_HOST_MEMORY;
288                 if (memoryProperties.flags.useHostPtr) {
289                     if (!context->isSharedContext) {
290                         AllocationProperties allocProperties = MemObjHelper::getAllocationPropertiesWithImageInfo(rootDeviceIndex, imgInfo,
291                                                                                                                   false, // allocateMemory
292                                                                                                                   memoryProperties, hwInfo,
293                                                                                                                   context->getDeviceBitfieldForAllocation(rootDeviceIndex),
294                                                                                                                   context->isSingleDeviceContext());
295                         allocProperties.flags.preferCompressed = preferCompression;
296 
297                         allocationInfo[rootDeviceIndex].memory = memoryManager->allocateGraphicsMemoryWithProperties(allocProperties, hostPtr);
298 
299                         if (allocationInfo[rootDeviceIndex].memory) {
300                             if (allocationInfo[rootDeviceIndex].memory->getUnderlyingBuffer() != hostPtr) {
301                                 allocationInfo[rootDeviceIndex].zeroCopyAllowed = false;
302                                 allocationInfo[rootDeviceIndex].transferNeeded = true;
303                             } else {
304                                 allocationInfo[rootDeviceIndex].zeroCopyAllowed = true;
305                             }
306                         }
307                     } else {
308                         gmm = new Gmm(clientContext, imgInfo, StorageInfo{}, preferCompression);
309                         allocationInfo[rootDeviceIndex].memory = memoryManager->allocateGraphicsMemoryWithProperties({rootDeviceIndex,
310                                                                                                                       false, // allocateMemory
311                                                                                                                       imgInfo.size, GraphicsAllocation::AllocationType::SHARED_CONTEXT_IMAGE,
312                                                                                                                       false, // isMultiStorageAllocation
313                                                                                                                       context->getDeviceBitfieldForAllocation(rootDeviceIndex)},
314                                                                                                                      hostPtr);
315                         allocationInfo[rootDeviceIndex].memory->setDefaultGmm(gmm);
316                         allocationInfo[rootDeviceIndex].zeroCopyAllowed = true;
317                     }
318                     if (!allocationInfo[rootDeviceIndex].zeroCopyAllowed) {
319                         if (allocationInfo[rootDeviceIndex].memory) {
320                             AllocationProperties properties{rootDeviceIndex,
321                                                             false, // allocateMemory
322                                                             hostPtrMinSize, GraphicsAllocation::AllocationType::MAP_ALLOCATION,
323                                                             false, // isMultiStorageAllocation
324                                                             context->getDeviceBitfieldForAllocation(rootDeviceIndex)};
325                             properties.flags.flushL3RequiredForRead = properties.flags.flushL3RequiredForWrite = true;
326                             properties.flags.preferCompressed = preferCompression;
327                             allocationInfo[rootDeviceIndex].mapAllocation = memoryManager->allocateGraphicsMemoryWithProperties(properties, hostPtr);
328                         }
329                     }
330                 } else {
331                     AllocationProperties allocProperties = MemObjHelper::getAllocationPropertiesWithImageInfo(rootDeviceIndex, imgInfo,
332                                                                                                               true, // allocateMemory
333                                                                                                               memoryProperties, hwInfo,
334                                                                                                               context->getDeviceBitfieldForAllocation(rootDeviceIndex),
335                                                                                                               context->isSingleDeviceContext());
336                     allocProperties.flags.preferCompressed = preferCompression;
337                     allocationInfo[rootDeviceIndex].memory = memoryManager->allocateGraphicsMemoryWithProperties(allocProperties);
338 
339                     if (allocationInfo[rootDeviceIndex].memory && MemoryPool::isSystemMemoryPool(allocationInfo[rootDeviceIndex].memory->getMemoryPool())) {
340                         allocationInfo[rootDeviceIndex].zeroCopyAllowed = true;
341                     }
342                 }
343             }
344             allocationInfo[rootDeviceIndex].transferNeeded |= memoryProperties.flags.copyHostPtr;
345 
346             if (!allocationInfo[rootDeviceIndex].memory) {
347                 cleanAllGraphicsAllocations(*context, *memoryManager, allocationInfo, isParentObject);
348                 return image;
349             }
350 
351             if (parentBuffer == nullptr) {
352                 allocationInfo[rootDeviceIndex].memory->setAllocationType(GraphicsAllocation::AllocationType::IMAGE);
353             }
354 
355             allocationInfo[rootDeviceIndex].memory->setMemObjectsAllocationWithWritableFlags(!memoryProperties.flags.readOnly &&
356                                                                                              !memoryProperties.flags.hostReadOnly &&
357                                                                                              !memoryProperties.flags.hostNoAccess);
358 
359             DBG_LOG(LogMemoryObject, __FUNCTION__, "hostPtr:", hostPtr, "size:", allocationInfo[rootDeviceIndex].memory->getUnderlyingBufferSize(),
360                     "memoryStorage:", allocationInfo[rootDeviceIndex].memory->getUnderlyingBuffer(), "GPU address:", std::hex, allocationInfo[rootDeviceIndex].memory->getGpuAddress());
361 
362             if (parentImage) {
363                 imageDescriptor.image_height = imageHeight;
364                 imageDescriptor.image_width = imageWidth;
365                 imageDescriptor.image_type = CL_MEM_OBJECT_IMAGE2D;
366                 imageDescriptor.image_depth = 1;
367                 imageDescriptor.image_array_size = 0;
368                 imageDescriptor.image_row_pitch = 0;
369                 imageDescriptor.image_slice_pitch = 0;
370                 imageDescriptor.mem_object = imageDesc->mem_object;
371                 parentImage->incRefInternal();
372                 imgInfo.imgDesc = Image::convertDescriptor(imageDescriptor);
373             }
374 
375             multiGraphicsAllocation.addAllocation(allocationInfo[rootDeviceIndex].memory);
376         }
377 
378         auto defaultRootDeviceIndex = context->getDevice(0u)->getRootDeviceIndex();
379 
380         multiGraphicsAllocation.setMultiStorage(context->getRootDeviceIndices().size() > 1);
381 
382         image = createImageHw(context, memoryProperties, flags, flagsIntel, imgInfo.size, hostPtrToSet, surfaceFormat->OCLImageFormat,
383                               imageDescriptor, allocationInfo[defaultRootDeviceIndex].zeroCopyAllowed, std::move(multiGraphicsAllocation), false, 0, 0, surfaceFormat);
384 
385         for (auto &rootDeviceIndex : context->getRootDeviceIndices()) {
386 
387             auto &hwInfo = *memoryManager->peekExecutionEnvironment().rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo();
388 
389             if (context->isProvidingPerformanceHints() && HwHelper::compressedImagesSupported(hwInfo)) {
390                 if (allocationInfo[rootDeviceIndex].memory->isCompressionEnabled()) {
391                     context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_NEUTRAL_INTEL, IMAGE_IS_COMPRESSED, image);
392                 } else {
393                     context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_NEUTRAL_INTEL, IMAGE_IS_NOT_COMPRESSED, image);
394                 }
395             }
396 
397             if (imageDesc->image_type != CL_MEM_OBJECT_IMAGE1D_ARRAY && imageDesc->image_type != CL_MEM_OBJECT_IMAGE2D_ARRAY) {
398                 image->imageDesc.image_array_size = 0;
399             }
400             if ((imageDesc->image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER) || ((imageDesc->image_type == CL_MEM_OBJECT_IMAGE2D) && (imageDesc->mem_object != nullptr))) {
401                 image->associatedMemObject = castToObject<MemObj>(imageDesc->mem_object);
402             }
403 
404             // Driver needs to store rowPitch passed by the app in order to synchronize the host_ptr later on map call
405             image->setHostPtrRowPitch(imageDesc->image_row_pitch ? imageDesc->image_row_pitch : hostPtrRowPitch);
406             image->setHostPtrSlicePitch(hostPtrSlicePitch);
407             image->setImageCount(imageCount);
408             image->setHostPtrMinSize(hostPtrMinSize);
409             image->setImageRowPitch(imgInfo.rowPitch);
410             image->setImageSlicePitch(imgInfo.slicePitch);
411             image->setQPitch(imgInfo.qPitch);
412             image->setSurfaceOffsets(imgInfo.offset, imgInfo.xOffset, imgInfo.yOffset, imgInfo.yOffsetForUVPlane);
413             image->setMipCount(imgInfo.mipCount);
414             if (parentImage) {
415                 image->setMediaPlaneType(static_cast<cl_uint>(imageDesc->image_depth));
416                 image->setParentSharingHandler(parentImage->getSharingHandler());
417             }
418             if (parentBuffer) {
419                 image->setParentSharingHandler(parentBuffer->getSharingHandler());
420             }
421             errcodeRet = CL_SUCCESS;
422             if (context->isProvidingPerformanceHints() && image->isMemObjZeroCopy()) {
423                 context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL, CL_IMAGE_MEETS_ALIGNMENT_RESTRICTIONS, static_cast<cl_mem>(image));
424             }
425             if (allocationInfo[rootDeviceIndex].transferNeeded && !transferedMemory) {
426                 std::array<size_t, 3> copyOrigin = {{0, 0, 0}};
427                 std::array<size_t, 3> copyRegion = {{imageWidth, imageHeight, std::max(imageDepth, imageCount)}};
428                 if (imageDesc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY) {
429                     copyRegion = {{imageWidth, imageCount, 1}};
430                 } else {
431                     copyRegion = {{imageWidth, imageHeight, std::max(imageDepth, imageCount)}};
432                 }
433 
434                 bool isCpuTransferPreferrred = imgInfo.linearStorage &&
435                                                (MemoryPool::isSystemMemoryPool(allocationInfo[rootDeviceIndex].memory->getMemoryPool()) ||
436                                                 defaultHwHelper.isCpuImageTransferPreferred(hwInfo));
437                 if (!isCpuTransferPreferrred) {
438                     auto cmdQ = context->getSpecialQueue(rootDeviceIndex);
439 
440                     if (isNV12Image(&image->getImageFormat())) {
441                         errcodeRet = image->writeNV12Planes(hostPtr, hostPtrRowPitch, rootDeviceIndex);
442                     } else {
443                         errcodeRet = cmdQ->enqueueWriteImage(image, CL_TRUE, &copyOrigin[0], &copyRegion[0],
444                                                              hostPtrRowPitch, hostPtrSlicePitch,
445                                                              hostPtr, allocationInfo[rootDeviceIndex].mapAllocation, 0, nullptr, nullptr);
446                     }
447                 } else {
448                     void *pDestinationAddress = allocationInfo[rootDeviceIndex].memory->getUnderlyingBuffer();
449                     auto isNotInSystemMemory = !MemoryPool::isSystemMemoryPool(allocationInfo[rootDeviceIndex].memory->getMemoryPool());
450                     if (isNotInSystemMemory) {
451                         pDestinationAddress = context->getMemoryManager()->lockResource(allocationInfo[rootDeviceIndex].memory);
452                     }
453 
454                     image->transferData(pDestinationAddress, imgInfo.rowPitch, imgInfo.slicePitch,
455                                         const_cast<void *>(hostPtr), hostPtrRowPitch, hostPtrSlicePitch,
456                                         copyRegion, copyOrigin);
457 
458                     if (isNotInSystemMemory) {
459                         context->getMemoryManager()->unlockResource(allocationInfo[rootDeviceIndex].memory);
460                     }
461                 }
462                 transferedMemory = true;
463             }
464 
465             if (allocationInfo[rootDeviceIndex].mapAllocation) {
466                 image->mapAllocations.addAllocation(allocationInfo[rootDeviceIndex].mapAllocation);
467             }
468         }
469         if (errcodeRet != CL_SUCCESS) {
470             image->release();
471             image = nullptr;
472             cleanAllGraphicsAllocations(*context, *memoryManager, allocationInfo, isParentObject);
473             return image;
474         }
475     } while (false);
476 
477     return image;
478 }
479 
createImageHw(Context * context,const MemoryProperties & memoryProperties,cl_mem_flags flags,cl_mem_flags_intel flagsIntel,size_t size,void * hostPtr,const cl_image_format & imageFormat,const cl_image_desc & imageDesc,bool zeroCopy,MultiGraphicsAllocation multiGraphicsAllocation,bool isObjectRedescribed,uint32_t baseMipLevel,uint32_t mipCount,const ClSurfaceFormatInfo * surfaceFormatInfo)480 Image *Image::createImageHw(Context *context, const MemoryProperties &memoryProperties, cl_mem_flags flags, cl_mem_flags_intel flagsIntel, size_t size, void *hostPtr,
481                             const cl_image_format &imageFormat, const cl_image_desc &imageDesc,
482                             bool zeroCopy, MultiGraphicsAllocation multiGraphicsAllocation,
483                             bool isObjectRedescribed, uint32_t baseMipLevel, uint32_t mipCount,
484                             const ClSurfaceFormatInfo *surfaceFormatInfo) {
485     const auto device = context->getDevice(0);
486     const auto &hwInfo = device->getHardwareInfo();
487 
488     auto funcCreate = imageFactory[hwInfo.platform.eRenderCoreFamily].createImageFunction;
489     DEBUG_BREAK_IF(nullptr == funcCreate);
490     auto image = funcCreate(context, memoryProperties, flags, flagsIntel, size, hostPtr, imageFormat, imageDesc,
491                             zeroCopy, std::move(multiGraphicsAllocation), isObjectRedescribed, baseMipLevel, mipCount, surfaceFormatInfo, nullptr);
492     DEBUG_BREAK_IF(nullptr == image);
493     image->createFunction = funcCreate;
494     return image;
495 }
496 
createSharedImage(Context * context,SharingHandler * sharingHandler,const McsSurfaceInfo & mcsSurfaceInfo,MultiGraphicsAllocation multiGraphicsAllocation,GraphicsAllocation * mcsAllocation,cl_mem_flags flags,cl_mem_flags_intel flagsIntel,const ClSurfaceFormatInfo * surfaceFormat,ImageInfo & imgInfo,uint32_t cubeFaceIndex,uint32_t baseMipLevel,uint32_t mipCount)497 Image *Image::createSharedImage(Context *context, SharingHandler *sharingHandler, const McsSurfaceInfo &mcsSurfaceInfo,
498                                 MultiGraphicsAllocation multiGraphicsAllocation, GraphicsAllocation *mcsAllocation,
499                                 cl_mem_flags flags, cl_mem_flags_intel flagsIntel, const ClSurfaceFormatInfo *surfaceFormat,
500                                 ImageInfo &imgInfo, uint32_t cubeFaceIndex, uint32_t baseMipLevel, uint32_t mipCount) {
501     auto rootDeviceIndex = context->getDevice(0)->getRootDeviceIndex();
502     auto size = multiGraphicsAllocation.getGraphicsAllocation(rootDeviceIndex)->getUnderlyingBufferSize();
503     auto sharedImage = createImageHw(
504         context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context->getDevice(0)->getDevice()),
505         flags, flagsIntel, size, nullptr,
506         surfaceFormat->OCLImageFormat, Image::convertDescriptor(imgInfo.imgDesc), false,
507         std::move(multiGraphicsAllocation), false, baseMipLevel, mipCount, surfaceFormat);
508     sharedImage->setSharingHandler(sharingHandler);
509     sharedImage->setMcsAllocation(mcsAllocation);
510     sharedImage->setQPitch(imgInfo.qPitch);
511     sharedImage->setHostPtrRowPitch(imgInfo.imgDesc.imageRowPitch);
512     sharedImage->setHostPtrSlicePitch(imgInfo.imgDesc.imageSlicePitch);
513     sharedImage->setCubeFaceIndex(cubeFaceIndex);
514     sharedImage->setSurfaceOffsets(imgInfo.offset, imgInfo.xOffset, imgInfo.yOffset, imgInfo.yOffsetForUVPlane);
515     sharedImage->setMcsSurfaceInfo(mcsSurfaceInfo);
516     return sharedImage;
517 }
518 
validate(Context * context,const MemoryProperties & memoryProperties,const ClSurfaceFormatInfo * surfaceFormat,const cl_image_desc * imageDesc,const void * hostPtr)519 cl_int Image::validate(Context *context,
520                        const MemoryProperties &memoryProperties,
521                        const ClSurfaceFormatInfo *surfaceFormat,
522                        const cl_image_desc *imageDesc,
523                        const void *hostPtr) {
524     auto pClDevice = context->getDevice(0);
525     size_t srcSize = 0;
526     size_t retSize = 0;
527     const size_t *maxWidth = nullptr;
528     const size_t *maxHeight = nullptr;
529     const uint32_t *pitchAlignment = nullptr;
530     const uint32_t *baseAddressAlignment = nullptr;
531     if (!surfaceFormat) {
532         return CL_IMAGE_FORMAT_NOT_SUPPORTED;
533     }
534 
535     Image *parentImage = castToObject<Image>(imageDesc->mem_object);
536     Buffer *parentBuffer = castToObject<Buffer>(imageDesc->mem_object);
537     if (imageDesc->image_type == CL_MEM_OBJECT_IMAGE2D) {
538         if ((imageDesc->mem_object != nullptr) && (pClDevice->getSharedDeviceInfo().imageSupport == false)) {
539             return CL_INVALID_OPERATION;
540         }
541 
542         pClDevice->getCap<CL_DEVICE_IMAGE2D_MAX_WIDTH>(reinterpret_cast<const void *&>(maxWidth), srcSize, retSize);
543         pClDevice->getCap<CL_DEVICE_IMAGE2D_MAX_HEIGHT>(reinterpret_cast<const void *&>(maxHeight), srcSize, retSize);
544         if (imageDesc->image_width > *maxWidth ||
545             imageDesc->image_height > *maxHeight) {
546             return CL_INVALID_IMAGE_SIZE;
547         }
548         if (parentBuffer) { // Image 2d from buffer
549             pClDevice->getCap<CL_DEVICE_IMAGE_PITCH_ALIGNMENT>(reinterpret_cast<const void *&>(pitchAlignment), srcSize, retSize);
550             pClDevice->getCap<CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT>(reinterpret_cast<const void *&>(baseAddressAlignment), srcSize, retSize);
551 
552             const auto rowSize = imageDesc->image_row_pitch != 0 ? imageDesc->image_row_pitch : alignUp(imageDesc->image_width * surfaceFormat->surfaceFormat.NumChannels * surfaceFormat->surfaceFormat.PerChannelSizeInBytes, *pitchAlignment);
553             const auto minimumBufferSize = imageDesc->image_height * rowSize;
554 
555             if ((imageDesc->image_row_pitch % (*pitchAlignment)) ||
556                 ((parentBuffer->getFlags() & CL_MEM_USE_HOST_PTR) && (reinterpret_cast<uint64_t>(parentBuffer->getHostPtr()) % (*baseAddressAlignment))) ||
557                 (minimumBufferSize > parentBuffer->getSize())) {
558                 return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
559             } else if (memoryProperties.flags.useHostPtr || memoryProperties.flags.copyHostPtr) {
560                 return CL_INVALID_VALUE;
561             }
562         }
563         if (parentImage && !isNV12Image(&parentImage->getImageFormat())) { // Image 2d from image 2d
564             if (!parentImage->hasSameDescriptor(*imageDesc) || !parentImage->hasValidParentImageFormat(surfaceFormat->OCLImageFormat)) {
565                 return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
566             }
567         }
568         if (!(parentImage && isNV12Image(&parentImage->getImageFormat())) &&
569             (imageDesc->image_width == 0 || imageDesc->image_height == 0)) {
570             return CL_INVALID_IMAGE_DESCRIPTOR;
571         }
572     }
573     if (hostPtr == nullptr) {
574         if (imageDesc->image_row_pitch != 0 && imageDesc->mem_object == nullptr) {
575             return CL_INVALID_IMAGE_DESCRIPTOR;
576         }
577     } else {
578         if (imageDesc->image_row_pitch != 0) {
579             if (imageDesc->image_row_pitch % surfaceFormat->surfaceFormat.ImageElementSizeInBytes != 0 ||
580                 imageDesc->image_row_pitch < imageDesc->image_width * surfaceFormat->surfaceFormat.ImageElementSizeInBytes) {
581                 return CL_INVALID_IMAGE_DESCRIPTOR;
582             }
583         }
584     }
585 
586     if (parentBuffer && imageDesc->image_type != CL_MEM_OBJECT_IMAGE1D_BUFFER && imageDesc->image_type != CL_MEM_OBJECT_IMAGE2D) {
587         return CL_INVALID_IMAGE_DESCRIPTOR;
588     }
589 
590     if (parentImage && imageDesc->image_type != CL_MEM_OBJECT_IMAGE2D) {
591         return CL_INVALID_IMAGE_DESCRIPTOR;
592     }
593 
594     return validateImageTraits(context, memoryProperties, &surfaceFormat->OCLImageFormat, imageDesc, hostPtr);
595 }
596 
validateImageFormat(const cl_image_format * imageFormat)597 cl_int Image::validateImageFormat(const cl_image_format *imageFormat) {
598     if (!imageFormat) {
599         return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
600     }
601     bool isValidFormat = isValidSingleChannelFormat(imageFormat) ||
602                          isValidIntensityFormat(imageFormat) ||
603                          isValidLuminanceFormat(imageFormat) ||
604                          isValidDepthFormat(imageFormat) ||
605                          isValidDoubleChannelFormat(imageFormat) ||
606                          isValidTripleChannelFormat(imageFormat) ||
607                          isValidRGBAFormat(imageFormat) ||
608                          isValidSRGBFormat(imageFormat) ||
609                          isValidARGBFormat(imageFormat) ||
610                          isValidDepthStencilFormat(imageFormat) ||
611                          isValidYUVFormat(imageFormat);
612 
613     if (isValidFormat) {
614         return CL_SUCCESS;
615     }
616     return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
617 }
618 
validatePlanarYUV(Context * context,const MemoryProperties & memoryProperties,const cl_image_desc * imageDesc,const void * hostPtr)619 cl_int Image::validatePlanarYUV(Context *context,
620                                 const MemoryProperties &memoryProperties,
621                                 const cl_image_desc *imageDesc,
622                                 const void *hostPtr) {
623     cl_int errorCode = CL_SUCCESS;
624     auto pClDevice = context->getDevice(0);
625     const size_t *maxWidth = nullptr;
626     const size_t *maxHeight = nullptr;
627     size_t srcSize = 0;
628     size_t retSize = 0;
629 
630     while (true) {
631 
632         Image *memObject = castToObject<Image>(imageDesc->mem_object);
633         if (memObject != nullptr) {
634             if (memObject->memObjectType == CL_MEM_OBJECT_IMAGE2D) {
635                 if (imageDesc->image_depth != 1 && imageDesc->image_depth != 0) {
636                     errorCode = CL_INVALID_IMAGE_DESCRIPTOR;
637                 }
638             }
639             break;
640         }
641 
642         if (imageDesc->mem_object != nullptr) {
643             errorCode = CL_INVALID_IMAGE_DESCRIPTOR;
644             break;
645         }
646         if (!memoryProperties.flags.hostNoAccess) {
647             errorCode = CL_INVALID_VALUE;
648             break;
649         } else {
650             if (imageDesc->image_height % 4 ||
651                 imageDesc->image_width % 4 ||
652                 imageDesc->image_type != CL_MEM_OBJECT_IMAGE2D) {
653                 errorCode = CL_INVALID_IMAGE_DESCRIPTOR;
654                 break;
655             }
656         }
657 
658         pClDevice->getCap<CL_DEVICE_PLANAR_YUV_MAX_WIDTH_INTEL>(reinterpret_cast<const void *&>(maxWidth), srcSize, retSize);
659         pClDevice->getCap<CL_DEVICE_PLANAR_YUV_MAX_HEIGHT_INTEL>(reinterpret_cast<const void *&>(maxHeight), srcSize, retSize);
660         if (imageDesc->image_width > *maxWidth || imageDesc->image_height > *maxHeight) {
661             errorCode = CL_INVALID_IMAGE_SIZE;
662             break;
663         }
664         break;
665     }
666     return errorCode;
667 }
668 
validatePackedYUV(const MemoryProperties & memoryProperties,const cl_image_desc * imageDesc)669 cl_int Image::validatePackedYUV(const MemoryProperties &memoryProperties, const cl_image_desc *imageDesc) {
670     cl_int errorCode = CL_SUCCESS;
671     while (true) {
672         if (!memoryProperties.flags.readOnly) {
673             errorCode = CL_INVALID_VALUE;
674             break;
675         } else {
676             if (imageDesc->image_width % 2 != 0 ||
677                 imageDesc->image_type != CL_MEM_OBJECT_IMAGE2D) {
678                 errorCode = CL_INVALID_IMAGE_DESCRIPTOR;
679                 break;
680             }
681         }
682         break;
683     }
684     return errorCode;
685 }
686 
validateImageTraits(Context * context,const MemoryProperties & memoryProperties,const cl_image_format * imageFormat,const cl_image_desc * imageDesc,const void * hostPtr)687 cl_int Image::validateImageTraits(Context *context, const MemoryProperties &memoryProperties, const cl_image_format *imageFormat, const cl_image_desc *imageDesc, const void *hostPtr) {
688     if (isNV12Image(imageFormat))
689         return validatePlanarYUV(context, memoryProperties, imageDesc, hostPtr);
690     else if (isPackedYuvImage(imageFormat))
691         return validatePackedYUV(memoryProperties, imageDesc);
692 
693     return CL_SUCCESS;
694 }
695 
calculateHostPtrSize(const size_t * region,size_t rowPitch,size_t slicePitch,size_t pixelSize,uint32_t imageType)696 size_t Image::calculateHostPtrSize(const size_t *region, size_t rowPitch, size_t slicePitch, size_t pixelSize, uint32_t imageType) {
697     DEBUG_BREAK_IF(!((rowPitch != 0) && (slicePitch != 0)));
698     size_t sizeToReturn = 0u;
699 
700     switch (imageType) {
701     case CL_MEM_OBJECT_IMAGE1D:
702     case CL_MEM_OBJECT_IMAGE1D_BUFFER:
703         sizeToReturn = region[0] * pixelSize;
704         break;
705     case CL_MEM_OBJECT_IMAGE2D:
706         sizeToReturn = (region[1] - 1) * rowPitch + region[0] * pixelSize;
707         break;
708     case CL_MEM_OBJECT_IMAGE1D_ARRAY:
709         sizeToReturn = (region[1] - 1) * slicePitch + region[0] * pixelSize;
710         break;
711     case CL_MEM_OBJECT_IMAGE3D:
712     case CL_MEM_OBJECT_IMAGE2D_ARRAY:
713         sizeToReturn = (region[2] - 1) * slicePitch + (region[1] - 1) * rowPitch + region[0] * pixelSize;
714         break;
715     default:
716         DEBUG_BREAK_IF("Unsupported cl_image_type");
717         break;
718     }
719 
720     DEBUG_BREAK_IF(sizeToReturn == 0);
721     return sizeToReturn;
722 }
723 
calculateHostPtrOffset(size_t * imageOffset,const size_t * origin,const size_t * region,size_t rowPitch,size_t slicePitch,uint32_t imageType,size_t bytesPerPixel)724 void Image::calculateHostPtrOffset(size_t *imageOffset, const size_t *origin, const size_t *region, size_t rowPitch, size_t slicePitch, uint32_t imageType, size_t bytesPerPixel) {
725 
726     size_t computedImageRowPitch = rowPitch ? rowPitch : region[0] * bytesPerPixel;
727     size_t computedImageSlicePitch = slicePitch ? slicePitch : region[1] * computedImageRowPitch * bytesPerPixel;
728     switch (imageType) {
729     case CL_MEM_OBJECT_IMAGE1D:
730     case CL_MEM_OBJECT_IMAGE1D_BUFFER:
731     case CL_MEM_OBJECT_IMAGE2D:
732         DEBUG_BREAK_IF(slicePitch != 0 && slicePitch < computedImageRowPitch * region[1]);
733         [[fallthrough]];
734     case CL_MEM_OBJECT_IMAGE2D_ARRAY:
735     case CL_MEM_OBJECT_IMAGE3D:
736         *imageOffset = origin[2] * computedImageSlicePitch + origin[1] * computedImageRowPitch + origin[0] * bytesPerPixel;
737         break;
738     case CL_MEM_OBJECT_IMAGE1D_ARRAY:
739         *imageOffset = origin[1] * computedImageSlicePitch + origin[0] * bytesPerPixel;
740         break;
741     default:
742         DEBUG_BREAK_IF("Unsupported cl_image_type");
743         *imageOffset = 0;
744         break;
745     }
746 }
747 
748 // Called by clGetImageParamsINTEL to obtain image row pitch and slice pitch
749 // Assumption: all parameters are already validated be calling function
getImageParams(Context * context,cl_mem_flags memFlags,const ClSurfaceFormatInfo * surfaceFormat,const cl_image_desc * imageDesc,size_t * imageRowPitch,size_t * imageSlicePitch)750 cl_int Image::getImageParams(Context *context,
751                              cl_mem_flags memFlags,
752                              const ClSurfaceFormatInfo *surfaceFormat,
753                              const cl_image_desc *imageDesc,
754                              size_t *imageRowPitch,
755                              size_t *imageSlicePitch) {
756     cl_int retVal = CL_SUCCESS;
757     auto clientContext = context->getDevice(0)->getRootDeviceEnvironment().getGmmClientContext();
758 
759     ImageInfo imgInfo = {};
760     cl_image_desc imageDescriptor = *imageDesc;
761     imgInfo.imgDesc = Image::convertDescriptor(imageDescriptor);
762     imgInfo.surfaceFormat = &surfaceFormat->surfaceFormat;
763 
764     auto gmm = std::make_unique<Gmm>(clientContext, imgInfo, StorageInfo{}, false);
765 
766     *imageRowPitch = imgInfo.rowPitch;
767     *imageSlicePitch = imgInfo.slicePitch;
768 
769     return retVal;
770 }
771 
getImageDesc() const772 const cl_image_desc &Image::getImageDesc() const {
773     return imageDesc;
774 }
775 
getImageFormat() const776 const cl_image_format &Image::getImageFormat() const {
777     return imageFormat;
778 }
779 
getSurfaceFormatInfo() const780 const ClSurfaceFormatInfo &Image::getSurfaceFormatInfo() const {
781     return surfaceFormatInfo;
782 }
783 
convertType(const ImageType type)784 cl_mem_object_type Image::convertType(const ImageType type) {
785     switch (type) {
786     case ImageType::Image2D:
787         return CL_MEM_OBJECT_IMAGE2D;
788     case ImageType::Image3D:
789         return CL_MEM_OBJECT_IMAGE3D;
790     case ImageType::Image2DArray:
791         return CL_MEM_OBJECT_IMAGE2D_ARRAY;
792     case ImageType::Image1D:
793         return CL_MEM_OBJECT_IMAGE1D;
794     case ImageType::Image1DArray:
795         return CL_MEM_OBJECT_IMAGE1D_ARRAY;
796     case ImageType::Image1DBuffer:
797         return CL_MEM_OBJECT_IMAGE1D_BUFFER;
798     default:
799         break;
800     }
801     return 0;
802 }
803 
convertType(const cl_mem_object_type type)804 ImageType Image::convertType(const cl_mem_object_type type) {
805     switch (type) {
806     case CL_MEM_OBJECT_IMAGE2D:
807         return ImageType::Image2D;
808     case CL_MEM_OBJECT_IMAGE3D:
809         return ImageType::Image3D;
810     case CL_MEM_OBJECT_IMAGE2D_ARRAY:
811         return ImageType::Image2DArray;
812     case CL_MEM_OBJECT_IMAGE1D:
813         return ImageType::Image1D;
814     case CL_MEM_OBJECT_IMAGE1D_ARRAY:
815         return ImageType::Image1DArray;
816     case CL_MEM_OBJECT_IMAGE1D_BUFFER:
817         return ImageType::Image1DBuffer;
818     default:
819         break;
820     }
821     return ImageType::Invalid;
822 }
823 
convertDescriptor(const cl_image_desc & imageDesc)824 ImageDescriptor Image::convertDescriptor(const cl_image_desc &imageDesc) {
825     ImageDescriptor desc = {};
826     desc.fromParent = imageDesc.mem_object != nullptr;
827     desc.imageArraySize = imageDesc.image_array_size;
828     desc.imageDepth = imageDesc.image_depth;
829     desc.imageHeight = imageDesc.image_height;
830     desc.imageRowPitch = imageDesc.image_row_pitch;
831     desc.imageSlicePitch = imageDesc.image_slice_pitch;
832     desc.imageType = convertType(imageDesc.image_type);
833     desc.imageWidth = imageDesc.image_width;
834     desc.numMipLevels = imageDesc.num_mip_levels;
835     desc.numSamples = imageDesc.num_samples;
836     return desc;
837 }
838 
convertDescriptor(const ImageDescriptor & imageDesc)839 cl_image_desc Image::convertDescriptor(const ImageDescriptor &imageDesc) {
840     cl_image_desc desc = {};
841     desc.mem_object = nullptr;
842     desc.image_array_size = imageDesc.imageArraySize;
843     desc.image_depth = imageDesc.imageDepth;
844     desc.image_height = imageDesc.imageHeight;
845     desc.image_row_pitch = imageDesc.imageRowPitch;
846     desc.image_slice_pitch = imageDesc.imageSlicePitch;
847     desc.image_type = convertType(imageDesc.imageType);
848     desc.image_width = imageDesc.imageWidth;
849     desc.num_mip_levels = imageDesc.numMipLevels;
850     desc.num_samples = imageDesc.numSamples;
851     return desc;
852 }
853 
getImageInfo(cl_image_info paramName,size_t paramValueSize,void * paramValue,size_t * paramValueSizeRet)854 cl_int Image::getImageInfo(cl_image_info paramName,
855                            size_t paramValueSize,
856                            void *paramValue,
857                            size_t *paramValueSizeRet) {
858     cl_int retVal;
859     size_t srcParamSize = GetInfo::invalidSourceSize;
860     void *srcParam = nullptr;
861     auto imageDesc = getImageDesc();
862     auto surfFmtInfo = getSurfaceFormatInfo();
863     size_t retParam;
864     size_t array_size = imageDesc.image_array_size * (imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY || imageDesc.image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY);
865     size_t SlicePitch = hostPtrSlicePitch * !(imageDesc.image_type == CL_MEM_OBJECT_IMAGE2D || imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D || imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER);
866 
867     switch (paramName) {
868     case CL_IMAGE_FORMAT:
869         srcParamSize = sizeof(cl_image_format);
870         srcParam = &(surfFmtInfo.OCLImageFormat);
871         break;
872 
873     case CL_IMAGE_ELEMENT_SIZE:
874         srcParamSize = sizeof(size_t);
875         srcParam = &(surfFmtInfo.surfaceFormat.ImageElementSizeInBytes);
876         break;
877 
878     case CL_IMAGE_ROW_PITCH:
879         srcParamSize = sizeof(size_t);
880         if (mcsSurfaceInfo.multisampleCount > 1) {
881             retParam = imageDesc.image_width * surfFmtInfo.surfaceFormat.ImageElementSizeInBytes * imageDesc.num_samples;
882         } else {
883             retParam = hostPtrRowPitch;
884         }
885         srcParam = &retParam;
886         break;
887 
888     case CL_IMAGE_SLICE_PITCH:
889         srcParamSize = sizeof(size_t);
890         srcParam = &SlicePitch;
891         break;
892 
893     case CL_IMAGE_WIDTH:
894         srcParamSize = sizeof(size_t);
895         retParam = imageDesc.image_width;
896         if (this->baseMipLevel) {
897             retParam = imageDesc.image_width >> this->baseMipLevel;
898             retParam = std::max(retParam, (size_t)1);
899         }
900         srcParam = &retParam;
901         break;
902 
903     case CL_IMAGE_HEIGHT:
904         srcParamSize = sizeof(size_t);
905         retParam = imageDesc.image_height * !((imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D) || (imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY) || (imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER));
906         if ((retParam != 0) && (this->baseMipLevel > 0)) {
907             retParam = retParam >> this->baseMipLevel;
908             retParam = std::max(retParam, (size_t)1);
909         }
910         srcParam = &retParam;
911         break;
912 
913     case CL_IMAGE_DEPTH:
914         srcParamSize = sizeof(size_t);
915         retParam = imageDesc.image_depth * (imageDesc.image_type == CL_MEM_OBJECT_IMAGE3D);
916         if ((retParam != 0) && (this->baseMipLevel > 0)) {
917             retParam = retParam >> this->baseMipLevel;
918             retParam = std::max(retParam, (size_t)1);
919         }
920         srcParam = &retParam;
921         break;
922 
923     case CL_IMAGE_ARRAY_SIZE:
924         srcParamSize = sizeof(size_t);
925         srcParam = &(array_size);
926         break;
927 
928     case CL_IMAGE_BUFFER:
929         srcParamSize = sizeof(cl_mem);
930         srcParam = &(imageDesc.buffer);
931         break;
932 
933     case CL_IMAGE_NUM_MIP_LEVELS:
934         srcParamSize = sizeof(cl_uint);
935         srcParam = &(imageDesc.num_mip_levels);
936         break;
937 
938     case CL_IMAGE_NUM_SAMPLES:
939         srcParamSize = sizeof(cl_uint);
940         srcParam = &(imageDesc.num_samples);
941         break;
942 
943     default:
944         getOsSpecificImageInfo(paramName, &srcParamSize, &srcParam);
945         break;
946     }
947 
948     auto getInfoStatus = GetInfo::getInfo(paramValue, paramValueSize, srcParam, srcParamSize);
949     retVal = changeGetInfoStatusToCLResultType(getInfoStatus);
950     GetInfo::setParamValueReturnSize(paramValueSizeRet, srcParamSize, getInfoStatus);
951 
952     return retVal;
953 }
954 
redescribeFillImage()955 Image *Image::redescribeFillImage() {
956     const uint32_t redescribeTable[3][3] = {
957         {17, 27, 5}, // {CL_R, CL_UNSIGNED_INT8},  {CL_RG, CL_UNSIGNED_INT8},  {CL_RGBA, CL_UNSIGNED_INT8}
958         {18, 28, 6}, // {CL_R, CL_UNSIGNED_INT16}, {CL_RG, CL_UNSIGNED_INT16}, {CL_RGBA, CL_UNSIGNED_INT16}
959         {19, 29, 7}  // {CL_R, CL_UNSIGNED_INT32}, {CL_RG, CL_UNSIGNED_INT32}, {CL_RGBA, CL_UNSIGNED_INT32}
960     };
961 
962     auto imageFormatNew = this->imageFormat;
963     auto imageDescNew = this->imageDesc;
964     const ClSurfaceFormatInfo *surfaceFormat = nullptr;
965     uint32_t redescribeTableCol = this->surfaceFormatInfo.surfaceFormat.NumChannels / 2;
966     uint32_t redescribeTableRow = this->surfaceFormatInfo.surfaceFormat.PerChannelSizeInBytes / 2;
967 
968     ArrayRef<const ClSurfaceFormatInfo> readWriteSurfaceFormats = SurfaceFormats::readWrite();
969 
970     uint32_t surfaceFormatIdx = redescribeTable[redescribeTableRow][redescribeTableCol];
971     surfaceFormat = &readWriteSurfaceFormats[surfaceFormatIdx];
972 
973     imageFormatNew.image_channel_order = surfaceFormat->OCLImageFormat.image_channel_order;
974     imageFormatNew.image_channel_data_type = surfaceFormat->OCLImageFormat.image_channel_data_type;
975 
976     DEBUG_BREAK_IF(nullptr == createFunction);
977     MemoryProperties memoryProperties = ClMemoryPropertiesHelper::createMemoryProperties(flags | CL_MEM_USE_HOST_PTR, flagsIntel, 0,
978                                                                                          &context->getDevice(0)->getDevice());
979     auto image = createFunction(context,
980                                 memoryProperties,
981                                 flags | CL_MEM_USE_HOST_PTR,
982                                 flagsIntel,
983                                 this->getSize(),
984                                 this->getCpuAddress(),
985                                 imageFormatNew,
986                                 imageDescNew,
987                                 this->isMemObjZeroCopy(),
988                                 this->multiGraphicsAllocation,
989                                 true,
990                                 this->baseMipLevel,
991                                 this->mipCount,
992                                 surfaceFormat,
993                                 &this->surfaceOffsets);
994     image->setQPitch(this->getQPitch());
995     image->setCubeFaceIndex(this->getCubeFaceIndex());
996     image->associatedMemObject = this->associatedMemObject;
997     return image;
998 }
999 
1000 static const uint32_t redescribeTableBytes[] = {
1001     17, // {CL_R, CL_UNSIGNED_INT8}        1 byte
1002     18, // {CL_R, CL_UNSIGNED_INT16}       2 byte
1003     19, // {CL_R, CL_UNSIGNED_INT32}       4 byte
1004     29, // {CL_RG, CL_UNSIGNED_INT32}      8 byte
1005     7   // {CL_RGBA, CL_UNSIGNED_INT32}    16 byte
1006 };
1007 
redescribe()1008 Image *Image::redescribe() {
1009     const uint32_t bytesPerPixel = this->surfaceFormatInfo.surfaceFormat.NumChannels * surfaceFormatInfo.surfaceFormat.PerChannelSizeInBytes;
1010     const uint32_t exponent = Math::log2(bytesPerPixel);
1011     DEBUG_BREAK_IF(exponent >= 5u);
1012     const uint32_t surfaceFormatIdx = redescribeTableBytes[exponent % 5];
1013     const ArrayRef<const ClSurfaceFormatInfo> readWriteSurfaceFormats = SurfaceFormats::readWrite();
1014     const ClSurfaceFormatInfo *surfaceFormat = &readWriteSurfaceFormats[surfaceFormatIdx];
1015 
1016     auto imageFormatNew = this->imageFormat;
1017     imageFormatNew.image_channel_order = surfaceFormat->OCLImageFormat.image_channel_order;
1018     imageFormatNew.image_channel_data_type = surfaceFormat->OCLImageFormat.image_channel_data_type;
1019 
1020     DEBUG_BREAK_IF(nullptr == createFunction);
1021     MemoryProperties memoryProperties = ClMemoryPropertiesHelper::createMemoryProperties(flags | CL_MEM_USE_HOST_PTR, flagsIntel, 0,
1022                                                                                          &context->getDevice(0)->getDevice());
1023     auto image = createFunction(context,
1024                                 memoryProperties,
1025                                 flags | CL_MEM_USE_HOST_PTR,
1026                                 flagsIntel,
1027                                 this->getSize(),
1028                                 this->getCpuAddress(),
1029                                 imageFormatNew,
1030                                 this->imageDesc,
1031                                 this->isMemObjZeroCopy(),
1032                                 this->multiGraphicsAllocation,
1033                                 true,
1034                                 this->baseMipLevel,
1035                                 this->mipCount,
1036                                 surfaceFormat,
1037                                 &this->surfaceOffsets);
1038     image->setQPitch(this->getQPitch());
1039     image->setCubeFaceIndex(this->getCubeFaceIndex());
1040     image->associatedMemObject = this->associatedMemObject;
1041     image->createFunction = createFunction;
1042     return image;
1043 }
1044 
transferDataToHostPtr(MemObjSizeArray & copySize,MemObjOffsetArray & copyOffset)1045 void Image::transferDataToHostPtr(MemObjSizeArray &copySize, MemObjOffsetArray &copyOffset) {
1046     transferData(hostPtr, hostPtrRowPitch, hostPtrSlicePitch,
1047                  memoryStorage, imageDesc.image_row_pitch, imageDesc.image_slice_pitch,
1048                  copySize, copyOffset);
1049 }
1050 
transferDataFromHostPtr(MemObjSizeArray & copySize,MemObjOffsetArray & copyOffset)1051 void Image::transferDataFromHostPtr(MemObjSizeArray &copySize, MemObjOffsetArray &copyOffset) {
1052     transferData(memoryStorage, imageDesc.image_row_pitch, imageDesc.image_slice_pitch,
1053                  hostPtr, hostPtrRowPitch, hostPtrSlicePitch,
1054                  copySize, copyOffset);
1055 }
1056 
writeNV12Planes(const void * hostPtr,size_t hostPtrRowPitch,uint32_t rootDeviceIndex)1057 cl_int Image::writeNV12Planes(const void *hostPtr, size_t hostPtrRowPitch, uint32_t rootDeviceIndex) {
1058     CommandQueue *cmdQ = context->getSpecialQueue(rootDeviceIndex);
1059     size_t origin[3] = {0, 0, 0};
1060     size_t region[3] = {this->imageDesc.image_width, this->imageDesc.image_height, 1};
1061 
1062     cl_int retVal = 0;
1063     cl_image_desc imageDesc = {0};
1064     cl_image_format imageFormat = {0};
1065     // Make NV12 planes readable and writable both on device and host
1066     cl_mem_flags flags = CL_MEM_READ_WRITE;
1067 
1068     // Plane Y
1069     imageFormat.image_channel_data_type = CL_UNORM_INT8;
1070     imageFormat.image_channel_order = CL_R;
1071 
1072     imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D;
1073     // image_width & image_height are ignored for plane extraction
1074     imageDesc.image_width = 0;
1075     imageDesc.image_height = 0;
1076     // set mem_object to the full NV12 image
1077     imageDesc.mem_object = this;
1078     // get access to the Y plane (CL_R)
1079     imageDesc.image_depth = 0;
1080     const ClSurfaceFormatInfo *surfaceFormat = Image::getSurfaceFormatFromTable(flags, &imageFormat, context->getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features);
1081 
1082     // Create NV12 UV Plane image
1083     std::unique_ptr<Image> imageYPlane(Image::create(
1084         context,
1085         ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context->getDevice(0)->getDevice()),
1086         flags,
1087         0,
1088         surfaceFormat,
1089         &imageDesc,
1090         nullptr,
1091         retVal));
1092 
1093     retVal = cmdQ->enqueueWriteImage(imageYPlane.get(), CL_TRUE, origin, region, hostPtrRowPitch, 0, hostPtr, nullptr, 0, nullptr, nullptr);
1094 
1095     // UV Plane is two times smaller than Plane Y
1096     region[0] = region[0] / 2;
1097     region[1] = region[1] / 2;
1098 
1099     imageDesc.image_width = 0;
1100     imageDesc.image_height = 0;
1101     imageDesc.image_depth = 1; // UV plane
1102     imageFormat.image_channel_order = CL_RG;
1103 
1104     hostPtr = static_cast<const void *>(static_cast<const char *>(hostPtr) + (hostPtrRowPitch * this->imageDesc.image_height));
1105     surfaceFormat = Image::getSurfaceFormatFromTable(flags, &imageFormat, context->getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features);
1106     // Create NV12 UV Plane image
1107     std::unique_ptr<Image> imageUVPlane(Image::create(
1108         context,
1109         ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context->getDevice(0)->getDevice()),
1110         flags,
1111         0,
1112         surfaceFormat,
1113         &imageDesc,
1114         nullptr,
1115         retVal));
1116 
1117     retVal = cmdQ->enqueueWriteImage(imageUVPlane.get(), CL_TRUE, origin, region, hostPtrRowPitch, 0, hostPtr, nullptr, 0, nullptr, nullptr);
1118 
1119     return retVal;
1120 }
1121 
getSurfaceFormatFromTable(cl_mem_flags flags,const cl_image_format * imageFormat,bool supportsOcl20Features)1122 const ClSurfaceFormatInfo *Image::getSurfaceFormatFromTable(cl_mem_flags flags, const cl_image_format *imageFormat, bool supportsOcl20Features) {
1123     if (!imageFormat) {
1124         DEBUG_BREAK_IF("Invalid format");
1125         return nullptr;
1126     }
1127 
1128     ArrayRef<const ClSurfaceFormatInfo> formats = SurfaceFormats::surfaceFormats(flags, imageFormat, supportsOcl20Features);
1129 
1130     for (auto &format : formats) {
1131         if (format.OCLImageFormat.image_channel_data_type == imageFormat->image_channel_data_type &&
1132             format.OCLImageFormat.image_channel_order == imageFormat->image_channel_order) {
1133             return &format;
1134         }
1135     }
1136     DEBUG_BREAK_IF("Invalid format");
1137     return nullptr;
1138 }
1139 
isImage1d(const cl_image_desc & imageDesc)1140 bool Image::isImage1d(const cl_image_desc &imageDesc) {
1141     auto imageType = imageDesc.image_type;
1142     auto buffer = castToObject<Buffer>(imageDesc.buffer);
1143 
1144     return (imageType == CL_MEM_OBJECT_IMAGE1D || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY ||
1145             imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER || buffer);
1146 }
1147 
isImage2d(cl_mem_object_type imageType)1148 bool Image::isImage2d(cl_mem_object_type imageType) {
1149     return imageType == CL_MEM_OBJECT_IMAGE2D;
1150 }
1151 
isImage2dOr2dArray(cl_mem_object_type imageType)1152 bool Image::isImage2dOr2dArray(cl_mem_object_type imageType) {
1153     return imageType == CL_MEM_OBJECT_IMAGE2D || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY;
1154 }
1155 
isDepthFormat(const cl_image_format & imageFormat)1156 bool Image::isDepthFormat(const cl_image_format &imageFormat) {
1157     return imageFormat.image_channel_order == CL_DEPTH || imageFormat.image_channel_order == CL_DEPTH_STENCIL;
1158 }
1159 
validateAndCreateImage(cl_context context,const cl_mem_properties * properties,cl_mem_flags flags,cl_mem_flags_intel flagsIntel,const cl_image_format * imageFormat,const cl_image_desc * imageDesc,const void * hostPtr,cl_int & errcodeRet)1160 cl_mem Image::validateAndCreateImage(cl_context context,
1161                                      const cl_mem_properties *properties,
1162                                      cl_mem_flags flags,
1163                                      cl_mem_flags_intel flagsIntel,
1164                                      const cl_image_format *imageFormat,
1165                                      const cl_image_desc *imageDesc,
1166                                      const void *hostPtr,
1167                                      cl_int &errcodeRet) {
1168 
1169     Context *pContext = nullptr;
1170     errcodeRet = validateObjects(WithCastToInternal(context, &pContext));
1171     if (errcodeRet != CL_SUCCESS) {
1172         return nullptr;
1173     }
1174 
1175     MemoryProperties memoryProperties{};
1176     cl_mem_flags_intel emptyFlagsIntel = 0;
1177     cl_mem_alloc_flags_intel allocflags = 0;
1178     if ((false == ClMemoryPropertiesHelper::parseMemoryProperties(nullptr, memoryProperties, flags, emptyFlagsIntel, allocflags,
1179                                                                   MemoryPropertiesHelper::ObjType::IMAGE, *pContext)) ||
1180         (false == MemObjHelper::validateMemoryPropertiesForImage(memoryProperties, flags, emptyFlagsIntel, imageDesc->mem_object,
1181                                                                  *pContext))) {
1182         errcodeRet = CL_INVALID_VALUE;
1183         return nullptr;
1184     }
1185 
1186     if ((false == ClMemoryPropertiesHelper::parseMemoryProperties(properties, memoryProperties, flags, flagsIntel, allocflags,
1187                                                                   MemoryPropertiesHelper::ObjType::IMAGE, *pContext)) ||
1188         (false == MemObjHelper::validateMemoryPropertiesForImage(memoryProperties, flags, flagsIntel, imageDesc->mem_object,
1189                                                                  *pContext))) {
1190         errcodeRet = CL_INVALID_PROPERTY;
1191         return nullptr;
1192     }
1193 
1194     bool isHostPtrUsed = (hostPtr != nullptr);
1195     bool areHostPtrFlagsUsed = memoryProperties.flags.copyHostPtr || memoryProperties.flags.useHostPtr;
1196     if (isHostPtrUsed != areHostPtrFlagsUsed) {
1197         errcodeRet = CL_INVALID_HOST_PTR;
1198         return nullptr;
1199     }
1200 
1201     errcodeRet = Image::validateImageFormat(imageFormat);
1202     if (errcodeRet != CL_SUCCESS) {
1203         return nullptr;
1204     }
1205 
1206     const auto surfaceFormat = Image::getSurfaceFormatFromTable(flags, imageFormat, pContext->getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features);
1207 
1208     errcodeRet = Image::validate(pContext, memoryProperties, surfaceFormat, imageDesc, hostPtr);
1209     if (errcodeRet != CL_SUCCESS) {
1210         return nullptr;
1211     }
1212 
1213     auto image = Image::create(pContext, memoryProperties, flags, flagsIntel, surfaceFormat, imageDesc, hostPtr, errcodeRet);
1214 
1215     if (errcodeRet == CL_SUCCESS) {
1216         image->storeProperties(properties);
1217     }
1218 
1219     return image;
1220 }
1221 
isValidSingleChannelFormat(const cl_image_format * imageFormat)1222 bool Image::isValidSingleChannelFormat(const cl_image_format *imageFormat) {
1223     auto channelOrder = imageFormat->image_channel_order;
1224     auto dataType = imageFormat->image_channel_data_type;
1225 
1226     bool isValidOrder = (channelOrder == CL_A) ||
1227                         (channelOrder == CL_R) ||
1228                         (channelOrder == CL_Rx);
1229 
1230     bool isValidDataType = (dataType == CL_UNORM_INT8) ||
1231                            (dataType == CL_UNORM_INT16) ||
1232                            (dataType == CL_SNORM_INT8) ||
1233                            (dataType == CL_SNORM_INT16) ||
1234                            (dataType == CL_HALF_FLOAT) ||
1235                            (dataType == CL_FLOAT) ||
1236                            (dataType == CL_SIGNED_INT8) ||
1237                            (dataType == CL_SIGNED_INT16) ||
1238                            (dataType == CL_SIGNED_INT32) ||
1239                            (dataType == CL_UNSIGNED_INT8) ||
1240                            (dataType == CL_UNSIGNED_INT16) ||
1241                            (dataType == CL_UNSIGNED_INT32);
1242 
1243     return isValidOrder && isValidDataType;
1244 }
1245 
isValidIntensityFormat(const cl_image_format * imageFormat)1246 bool Image::isValidIntensityFormat(const cl_image_format *imageFormat) {
1247     if (imageFormat->image_channel_order != CL_INTENSITY) {
1248         return false;
1249     }
1250     auto dataType = imageFormat->image_channel_data_type;
1251     return (dataType == CL_UNORM_INT8) ||
1252            (dataType == CL_UNORM_INT16) ||
1253            (dataType == CL_SNORM_INT8) ||
1254            (dataType == CL_SNORM_INT16) ||
1255            (dataType == CL_HALF_FLOAT) ||
1256            (dataType == CL_FLOAT);
1257 }
1258 
isValidLuminanceFormat(const cl_image_format * imageFormat)1259 bool Image::isValidLuminanceFormat(const cl_image_format *imageFormat) {
1260     if (imageFormat->image_channel_order != CL_LUMINANCE) {
1261         return false;
1262     }
1263     auto dataType = imageFormat->image_channel_data_type;
1264     return (dataType == CL_UNORM_INT8) ||
1265            (dataType == CL_UNORM_INT16) ||
1266            (dataType == CL_SNORM_INT8) ||
1267            (dataType == CL_SNORM_INT16) ||
1268            (dataType == CL_HALF_FLOAT) ||
1269            (dataType == CL_FLOAT);
1270 }
1271 
isValidDepthFormat(const cl_image_format * imageFormat)1272 bool Image::isValidDepthFormat(const cl_image_format *imageFormat) {
1273     if (imageFormat->image_channel_order != CL_DEPTH) {
1274         return false;
1275     }
1276     auto dataType = imageFormat->image_channel_data_type;
1277     return (dataType == CL_UNORM_INT16) ||
1278            (dataType == CL_FLOAT);
1279 }
1280 
isValidDoubleChannelFormat(const cl_image_format * imageFormat)1281 bool Image::isValidDoubleChannelFormat(const cl_image_format *imageFormat) {
1282     auto channelOrder = imageFormat->image_channel_order;
1283     auto dataType = imageFormat->image_channel_data_type;
1284 
1285     bool isValidOrder = (channelOrder == CL_RG) ||
1286                         (channelOrder == CL_RGx) ||
1287                         (channelOrder == CL_RA);
1288 
1289     bool isValidDataType = (dataType == CL_UNORM_INT8) ||
1290                            (dataType == CL_UNORM_INT16) ||
1291                            (dataType == CL_SNORM_INT8) ||
1292                            (dataType == CL_SNORM_INT16) ||
1293                            (dataType == CL_HALF_FLOAT) ||
1294                            (dataType == CL_FLOAT) ||
1295                            (dataType == CL_SIGNED_INT8) ||
1296                            (dataType == CL_SIGNED_INT16) ||
1297                            (dataType == CL_SIGNED_INT32) ||
1298                            (dataType == CL_UNSIGNED_INT8) ||
1299                            (dataType == CL_UNSIGNED_INT16) ||
1300                            (dataType == CL_UNSIGNED_INT32);
1301 
1302     return isValidOrder && isValidDataType;
1303 }
1304 
isValidTripleChannelFormat(const cl_image_format * imageFormat)1305 bool Image::isValidTripleChannelFormat(const cl_image_format *imageFormat) {
1306     auto channelOrder = imageFormat->image_channel_order;
1307     auto dataType = imageFormat->image_channel_data_type;
1308 
1309     bool isValidOrder = (channelOrder == CL_RGB) ||
1310                         (channelOrder == CL_RGBx);
1311 
1312     bool isValidDataType = (dataType == CL_UNORM_SHORT_565) ||
1313                            (dataType == CL_UNORM_SHORT_555) ||
1314                            (dataType == CL_UNORM_INT_101010);
1315 
1316     return isValidOrder && isValidDataType;
1317 }
1318 
isValidRGBAFormat(const cl_image_format * imageFormat)1319 bool Image::isValidRGBAFormat(const cl_image_format *imageFormat) {
1320     if (imageFormat->image_channel_order != CL_RGBA) {
1321         return false;
1322     }
1323     auto dataType = imageFormat->image_channel_data_type;
1324     return (dataType == CL_UNORM_INT8) ||
1325            (dataType == CL_UNORM_INT16) ||
1326            (dataType == CL_SNORM_INT8) ||
1327            (dataType == CL_SNORM_INT16) ||
1328            (dataType == CL_HALF_FLOAT) ||
1329            (dataType == CL_FLOAT) ||
1330            (dataType == CL_SIGNED_INT8) ||
1331            (dataType == CL_SIGNED_INT16) ||
1332            (dataType == CL_SIGNED_INT32) ||
1333            (dataType == CL_UNSIGNED_INT8) ||
1334            (dataType == CL_UNSIGNED_INT16) ||
1335            (dataType == CL_UNSIGNED_INT32);
1336 }
1337 
isValidSRGBFormat(const cl_image_format * imageFormat)1338 bool Image::isValidSRGBFormat(const cl_image_format *imageFormat) {
1339     auto channelOrder = imageFormat->image_channel_order;
1340     auto dataType = imageFormat->image_channel_data_type;
1341 
1342     bool isValidOrder = (channelOrder == CL_sRGB) ||
1343                         (channelOrder == CL_sRGBx) ||
1344                         (channelOrder == CL_sRGBA) ||
1345                         (channelOrder == CL_sBGRA);
1346 
1347     bool isValidDataType = (dataType == CL_UNORM_INT8);
1348 
1349     return isValidOrder && isValidDataType;
1350 }
1351 
isValidARGBFormat(const cl_image_format * imageFormat)1352 bool Image::isValidARGBFormat(const cl_image_format *imageFormat) {
1353     auto channelOrder = imageFormat->image_channel_order;
1354     auto dataType = imageFormat->image_channel_data_type;
1355 
1356     bool isValidOrder = (channelOrder == CL_ARGB) ||
1357                         (channelOrder == CL_BGRA) ||
1358                         (channelOrder == CL_ABGR);
1359 
1360     bool isValidDataType = (dataType == CL_UNORM_INT8) ||
1361                            (dataType == CL_SNORM_INT8) ||
1362                            (dataType == CL_SIGNED_INT8) ||
1363                            (dataType == CL_UNSIGNED_INT8);
1364 
1365     return isValidOrder && isValidDataType;
1366 }
1367 
isValidDepthStencilFormat(const cl_image_format * imageFormat)1368 bool Image::isValidDepthStencilFormat(const cl_image_format *imageFormat) {
1369     if (imageFormat->image_channel_order != CL_DEPTH_STENCIL) {
1370         return false;
1371     }
1372     auto dataType = imageFormat->image_channel_data_type;
1373     return (dataType == CL_UNORM_INT24) ||
1374            (dataType == CL_FLOAT);
1375 }
1376 
isValidYUVFormat(const cl_image_format * imageFormat)1377 bool Image::isValidYUVFormat(const cl_image_format *imageFormat) {
1378     auto dataType = imageFormat->image_channel_data_type;
1379 
1380     bool isValidOrder = isNV12Image(imageFormat) || isPackedYuvImage(imageFormat);
1381 
1382     bool isValidDataType = (dataType == CL_UNORM_INT8);
1383 
1384     return isValidOrder && isValidDataType;
1385 }
1386 
hasAlphaChannel(const cl_image_format * imageFormat)1387 bool Image::hasAlphaChannel(const cl_image_format *imageFormat) {
1388     auto channelOrder = imageFormat->image_channel_order;
1389     return (channelOrder == CL_A) ||
1390            (channelOrder == CL_Rx) ||
1391            (channelOrder == CL_RA) ||
1392            (channelOrder == CL_RGx) ||
1393            (channelOrder == CL_RGBx) ||
1394            (channelOrder == CL_RGBA) ||
1395            (channelOrder == CL_BGRA) ||
1396            (channelOrder == CL_ARGB) ||
1397            (channelOrder == CL_INTENSITY) ||
1398            (channelOrder == CL_sRGBA) ||
1399            (channelOrder == CL_sBGRA) ||
1400            (channelOrder == CL_sRGBx) ||
1401            (channelOrder == CL_ABGR);
1402 }
1403 
calculateOffsetForMapping(const MemObjOffsetArray & origin) const1404 size_t Image::calculateOffsetForMapping(const MemObjOffsetArray &origin) const {
1405     size_t rowPitch = mappingOnCpuAllowed() ? imageDesc.image_row_pitch : getHostPtrRowPitch();
1406     size_t slicePitch = mappingOnCpuAllowed() ? imageDesc.image_slice_pitch : getHostPtrSlicePitch();
1407 
1408     size_t offset = getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0];
1409 
1410     switch (imageDesc.image_type) {
1411     case CL_MEM_OBJECT_IMAGE1D_ARRAY:
1412         offset += slicePitch * origin[1];
1413         break;
1414     case CL_MEM_OBJECT_IMAGE2D:
1415         offset += rowPitch * origin[1];
1416         break;
1417     case CL_MEM_OBJECT_IMAGE2D_ARRAY:
1418     case CL_MEM_OBJECT_IMAGE3D:
1419         offset += rowPitch * origin[1] + slicePitch * origin[2];
1420         break;
1421     default:
1422         break;
1423     }
1424 
1425     return offset;
1426 }
1427 
validateRegionAndOrigin(const size_t * origin,const size_t * region,const cl_image_desc & imgDesc)1428 cl_int Image::validateRegionAndOrigin(const size_t *origin, const size_t *region, const cl_image_desc &imgDesc) {
1429     if (region[0] == 0 || region[1] == 0 || region[2] == 0) {
1430         return CL_INVALID_VALUE;
1431     }
1432 
1433     bool notMipMapped = (false == isMipMapped(imgDesc));
1434 
1435     if ((imgDesc.image_type == CL_MEM_OBJECT_IMAGE1D || imgDesc.image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER) &&
1436         (((origin[1] > 0) && notMipMapped) || origin[2] > 0 || region[1] > 1 || region[2] > 1)) {
1437         return CL_INVALID_VALUE;
1438     }
1439 
1440     if ((imgDesc.image_type == CL_MEM_OBJECT_IMAGE2D || imgDesc.image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY) &&
1441         (((origin[2] > 0) && notMipMapped) || region[2] > 1)) {
1442         return CL_INVALID_VALUE;
1443     }
1444 
1445     if (notMipMapped) {
1446         return CL_SUCCESS;
1447     }
1448 
1449     uint32_t mipLevel = findMipLevel(imgDesc.image_type, origin);
1450     if (mipLevel < imgDesc.num_mip_levels) {
1451         return CL_SUCCESS;
1452     } else {
1453         return CL_INVALID_MIP_LEVEL;
1454     }
1455 }
1456 
hasSameDescriptor(const cl_image_desc & imageDesc) const1457 bool Image::hasSameDescriptor(const cl_image_desc &imageDesc) const {
1458     return this->imageDesc.image_type == imageDesc.image_type &&
1459            this->imageDesc.image_width == imageDesc.image_width &&
1460            this->imageDesc.image_height == imageDesc.image_height &&
1461            this->imageDesc.image_depth == imageDesc.image_depth &&
1462            this->imageDesc.image_array_size == imageDesc.image_array_size &&
1463            this->hostPtrRowPitch == imageDesc.image_row_pitch &&
1464            this->hostPtrSlicePitch == imageDesc.image_slice_pitch &&
1465            this->imageDesc.num_mip_levels == imageDesc.num_mip_levels &&
1466            this->imageDesc.num_samples == imageDesc.num_samples;
1467 }
1468 
hasValidParentImageFormat(const cl_image_format & imageFormat) const1469 bool Image::hasValidParentImageFormat(const cl_image_format &imageFormat) const {
1470     if (this->imageFormat.image_channel_data_type != imageFormat.image_channel_data_type) {
1471         return false;
1472     }
1473     switch (this->imageFormat.image_channel_order) {
1474     case CL_BGRA:
1475         return imageFormat.image_channel_order == CL_sBGRA;
1476     case CL_sBGRA:
1477         return imageFormat.image_channel_order == CL_BGRA;
1478     case CL_RGBA:
1479         return imageFormat.image_channel_order == CL_sRGBA;
1480     case CL_sRGBA:
1481         return imageFormat.image_channel_order == CL_RGBA;
1482     case CL_RGB:
1483         return imageFormat.image_channel_order == CL_sRGB;
1484     case CL_sRGB:
1485         return imageFormat.image_channel_order == CL_RGB;
1486     case CL_RGBx:
1487         return imageFormat.image_channel_order == CL_sRGBx;
1488     case CL_sRGBx:
1489         return imageFormat.image_channel_order == CL_RGBx;
1490     case CL_R:
1491         return imageFormat.image_channel_order == CL_DEPTH;
1492     default:
1493         return false;
1494     }
1495 }
1496 
checkIfDeviceSupportsImages(cl_context context)1497 cl_int Image::checkIfDeviceSupportsImages(cl_context context) {
1498     auto pContext = castToObject<Context>(context);
1499     if (pContext != nullptr) {
1500         auto capabilityTable = pContext->getDevice(0)->getHardwareInfo().capabilityTable;
1501         if (!capabilityTable.supportsImages) {
1502             return CL_INVALID_OPERATION;
1503         }
1504 
1505         return CL_SUCCESS;
1506     }
1507 
1508     return CL_INVALID_CONTEXT;
1509 }
fillImageRegion(size_t * region) const1510 void Image::fillImageRegion(size_t *region) const {
1511     region[0] = imageDesc.image_width;
1512     if (imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY) {
1513         region[1] = imageDesc.image_array_size;
1514     } else if (Image::isImage1d(imageDesc)) {
1515         region[1] = 1u;
1516     } else {
1517         region[1] = imageDesc.image_height;
1518     }
1519 
1520     if (imageDesc.image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY) {
1521         region[2] = imageDesc.image_array_size;
1522     } else if (imageDesc.image_type == CL_MEM_OBJECT_IMAGE3D) {
1523         region[2] = imageDesc.image_depth;
1524     } else {
1525         region[2] = 1u;
1526     }
1527 }
1528 } // namespace NEO
1529