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, ©Origin[0], ©Region[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 ©Size, MemObjOffsetArray ©Offset) {
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 ©Size, MemObjOffsetArray ©Offset) {
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