1/*
2 * Copyright (C) 2020-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8#pragma once
9
10#include "shared/source/gmm_helper/gmm.h"
11#include "shared/source/gmm_helper/resource_info.h"
12#include "shared/source/helpers/string.h"
13#include "shared/source/helpers/surface_format_info.h"
14#include "shared/source/image/image_surface_state.h"
15#include "shared/source/memory_manager/allocation_properties.h"
16#include "shared/source/memory_manager/memory_manager.h"
17
18#include "level_zero/core/source/helpers/properties_parser.h"
19#include "level_zero/core/source/hw_helpers/l0_hw_helper.h"
20#include "level_zero/core/source/image/image_formats.h"
21#include "level_zero/core/source/image/image_hw.h"
22
23namespace L0 {
24
25template <GFXCORE_FAMILY gfxCoreFamily>
26ze_result_t ImageCoreFamily<gfxCoreFamily>::initialize(Device *device, const ze_image_desc_t *desc) {
27    using RENDER_SURFACE_STATE = typename GfxFamily::RENDER_SURFACE_STATE;
28
29    StructuresLookupTable lookupTable = {};
30
31    lookupTable.areImageProperties = true;
32    lookupTable.imageProperties.imageDescriptor = convertDescriptor(*desc);
33
34    auto parseResult = prepareL0StructuresLookupTable(lookupTable, desc->pNext);
35
36    if (parseResult != ZE_RESULT_SUCCESS) {
37        return parseResult;
38    }
39
40    bool isMediaFormatLayout = isMediaFormat(desc->format.layout);
41
42    imgInfo.imgDesc = lookupTable.imageProperties.imageDescriptor;
43
44    imgInfo.surfaceFormat = &ImageFormats::formats[desc->format.layout][desc->format.type];
45    imageFormatDesc = *const_cast<ze_image_desc_t *>(desc);
46
47    UNRECOVERABLE_IF(device == nullptr);
48    this->device = device;
49
50    if (imgInfo.surfaceFormat->GMMSurfaceFormat == GMM_FORMAT_INVALID) {
51        return ZE_RESULT_ERROR_UNSUPPORTED_IMAGE_FORMAT;
52    }
53
54    typename RENDER_SURFACE_STATE::SURFACE_TYPE surfaceType;
55    switch (desc->type) {
56    case ZE_IMAGE_TYPE_1D:
57    case ZE_IMAGE_TYPE_1DARRAY:
58        surfaceType = RENDER_SURFACE_STATE::SURFACE_TYPE_SURFTYPE_1D;
59        break;
60    case ZE_IMAGE_TYPE_2D:
61    case ZE_IMAGE_TYPE_2DARRAY:
62        surfaceType = RENDER_SURFACE_STATE::SURFACE_TYPE_SURFTYPE_2D;
63        break;
64    case ZE_IMAGE_TYPE_3D:
65        surfaceType = RENDER_SURFACE_STATE::SURFACE_TYPE_SURFTYPE_3D;
66        break;
67    default:
68        return ZE_RESULT_ERROR_INVALID_ARGUMENT;
69    }
70
71    imgInfo.linearStorage = surfaceType == RENDER_SURFACE_STATE::SURFACE_TYPE_SURFTYPE_1D;
72    imgInfo.plane = lookupTable.imageProperties.isPlanarExtension ? static_cast<GMM_YUV_PLANE>(lookupTable.imageProperties.planeIndex + 1u) : GMM_NO_PLANE;
73    imgInfo.useLocalMemory = false;
74
75    if (!isImageView) {
76        if (lookupTable.isSharedHandle) {
77            if (!lookupTable.sharedHandleType.isSupportedHandle) {
78                return ZE_RESULT_ERROR_UNSUPPORTED_ENUMERATION;
79            }
80            if (lookupTable.sharedHandleType.isDMABUFHandle) {
81                NEO::AllocationProperties properties(device->getRootDeviceIndex(), true, imgInfo, NEO::GraphicsAllocation::AllocationType::SHARED_IMAGE, device->getNEODevice()->getDeviceBitfield());
82                allocation = device->getNEODevice()->getMemoryManager()->createGraphicsAllocationFromSharedHandle(lookupTable.sharedHandleType.fd, properties, false, false);
83                device->getNEODevice()->getMemoryManager()->closeSharedHandle(allocation);
84            } else if (lookupTable.sharedHandleType.isNTHandle) {
85                auto verifyResult = device->getNEODevice()->getMemoryManager()->verifyHandle(NEO::toOsHandle(lookupTable.sharedHandleType.ntHnadle), device->getNEODevice()->getRootDeviceIndex(), true);
86                if (!verifyResult) {
87                    return ZE_RESULT_ERROR_INVALID_ARGUMENT;
88                }
89                allocation = device->getNEODevice()->getMemoryManager()->createGraphicsAllocationFromNTHandle(lookupTable.sharedHandleType.ntHnadle, device->getNEODevice()->getRootDeviceIndex(), NEO::GraphicsAllocation::AllocationType::SHARED_IMAGE);
90            }
91        } else {
92            NEO::AllocationProperties properties(device->getRootDeviceIndex(), true, imgInfo, NEO::GraphicsAllocation::AllocationType::IMAGE, device->getNEODevice()->getDeviceBitfield());
93
94            properties.flags.preferCompressed = isSuitableForCompression(lookupTable, imgInfo);
95
96            allocation = device->getNEODevice()->getMemoryManager()->allocateGraphicsMemoryWithProperties(properties);
97        }
98        if (allocation == nullptr) {
99            return ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY;
100        }
101    }
102
103    auto gmm = this->allocation->getDefaultGmm();
104    auto gmmHelper = static_cast<const NEO::RootDeviceEnvironment &>(device->getNEODevice()->getRootDeviceEnvironment()).getGmmHelper();
105
106    if (gmm != nullptr) {
107        gmm->updateImgInfoAndDesc(imgInfo, 0u);
108    }
109    NEO::SurfaceOffsets surfaceOffsets = {imgInfo.offset, imgInfo.xOffset, imgInfo.yOffset, imgInfo.yOffsetForUVPlane};
110
111    {
112        surfaceState = GfxFamily::cmdInitRenderSurfaceState;
113
114        NEO::setImageSurfaceState<GfxFamily>(&surfaceState, imgInfo, gmm, *gmmHelper, __GMM_NO_CUBE_MAP,
115                                             this->allocation->getGpuAddress(), surfaceOffsets,
116                                             isMediaFormatLayout);
117
118        NEO::setImageSurfaceStateDimensions<GfxFamily>(&surfaceState, imgInfo, __GMM_NO_CUBE_MAP, surfaceType);
119        surfaceState.setSurfaceMinLod(0u);
120        surfaceState.setMipCountLod(0u);
121        NEO::setMipTailStartLod<GfxFamily>(&surfaceState, gmm);
122
123        if (!isMediaFormatLayout) {
124            surfaceState.setShaderChannelSelectRed(
125                static_cast<const typename RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT>(
126                    shaderChannelSelect[desc->format.x]));
127            surfaceState.setShaderChannelSelectGreen(
128                static_cast<const typename RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT>(
129                    shaderChannelSelect[desc->format.y]));
130            surfaceState.setShaderChannelSelectBlue(
131                static_cast<const typename RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT>(
132                    shaderChannelSelect[desc->format.z]));
133            surfaceState.setShaderChannelSelectAlpha(
134                static_cast<const typename RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT>(
135                    shaderChannelSelect[desc->format.w]));
136        } else {
137            surfaceState.setShaderChannelSelectRed(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_RED);
138            surfaceState.setShaderChannelSelectGreen(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_GREEN);
139            surfaceState.setShaderChannelSelectBlue(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_BLUE);
140            surfaceState.setShaderChannelSelectAlpha(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_ZERO);
141        }
142
143        surfaceState.setNumberOfMultisamples(RENDER_SURFACE_STATE::NUMBER_OF_MULTISAMPLES::NUMBER_OF_MULTISAMPLES_MULTISAMPLECOUNT_1);
144
145        if (allocation->isCompressionEnabled()) {
146            NEO::EncodeSurfaceState<GfxFamily>::setImageAuxParamsForCCS(&surfaceState, gmm);
147        }
148    }
149    {
150        const uint32_t exponent = Math::log2(imgInfo.surfaceFormat->ImageElementSizeInBytes);
151        DEBUG_BREAK_IF(exponent >= 5u);
152
153        NEO::ImageInfo imgInfoRedescirebed;
154        imgInfoRedescirebed.surfaceFormat = &ImageFormats::surfaceFormatsForRedescribe[exponent % 5];
155        imgInfoRedescirebed.imgDesc = imgInfo.imgDesc;
156        imgInfoRedescirebed.qPitch = imgInfo.qPitch;
157        redescribedSurfaceState = GfxFamily::cmdInitRenderSurfaceState;
158
159        NEO::setImageSurfaceState<GfxFamily>(&redescribedSurfaceState, imgInfoRedescirebed, gmm, *gmmHelper,
160                                             __GMM_NO_CUBE_MAP, this->allocation->getGpuAddress(), surfaceOffsets,
161                                             desc->format.layout == ZE_IMAGE_FORMAT_LAYOUT_NV12);
162
163        NEO::setImageSurfaceStateDimensions<GfxFamily>(&redescribedSurfaceState, imgInfoRedescirebed, __GMM_NO_CUBE_MAP, surfaceType);
164        redescribedSurfaceState.setSurfaceMinLod(0u);
165        redescribedSurfaceState.setMipCountLod(0u);
166        NEO::setMipTailStartLod<GfxFamily>(&redescribedSurfaceState, gmm);
167
168        if (imgInfoRedescirebed.surfaceFormat->GMMSurfaceFormat == GMM_FORMAT_R8_UINT_TYPE ||
169            imgInfoRedescirebed.surfaceFormat->GMMSurfaceFormat == GMM_FORMAT_R16_UINT_TYPE ||
170            imgInfoRedescirebed.surfaceFormat->GMMSurfaceFormat == GMM_FORMAT_R32_UINT_TYPE) {
171            redescribedSurfaceState.setShaderChannelSelectRed(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_RED);
172            redescribedSurfaceState.setShaderChannelSelectGreen(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_ZERO);
173            redescribedSurfaceState.setShaderChannelSelectBlue(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_ZERO);
174        } else if (imgInfoRedescirebed.surfaceFormat->GMMSurfaceFormat == GMM_FORMAT_R32G32_UINT_TYPE) {
175            redescribedSurfaceState.setShaderChannelSelectRed(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_RED);
176            redescribedSurfaceState.setShaderChannelSelectGreen(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_GREEN);
177            redescribedSurfaceState.setShaderChannelSelectBlue(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_ZERO);
178        } else {
179            redescribedSurfaceState.setShaderChannelSelectRed(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_RED);
180            redescribedSurfaceState.setShaderChannelSelectGreen(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_GREEN);
181            redescribedSurfaceState.setShaderChannelSelectBlue(RENDER_SURFACE_STATE::SHADER_CHANNEL_SELECT_BLUE);
182        }
183
184        redescribedSurfaceState.setNumberOfMultisamples(RENDER_SURFACE_STATE::NUMBER_OF_MULTISAMPLES::NUMBER_OF_MULTISAMPLES_MULTISAMPLECOUNT_1);
185
186        if (allocation->isCompressionEnabled()) {
187            NEO::EncodeSurfaceState<GfxFamily>::setImageAuxParamsForCCS(&redescribedSurfaceState, gmm);
188        }
189    }
190
191    return ZE_RESULT_SUCCESS;
192}
193
194template <GFXCORE_FAMILY gfxCoreFamily>
195void ImageCoreFamily<gfxCoreFamily>::copySurfaceStateToSSH(void *surfaceStateHeap,
196                                                           const uint32_t surfaceStateOffset,
197                                                           bool isMediaBlockArg) {
198    using GfxFamily = typename NEO::GfxFamilyMapper<gfxCoreFamily>::GfxFamily;
199    using RENDER_SURFACE_STATE = typename GfxFamily::RENDER_SURFACE_STATE;
200
201    // Copy the image's surface state into position in the provided surface state heap
202    auto destSurfaceState = ptrOffset(surfaceStateHeap, surfaceStateOffset);
203    memcpy_s(destSurfaceState, sizeof(RENDER_SURFACE_STATE),
204             &surfaceState, sizeof(RENDER_SURFACE_STATE));
205    if (isMediaBlockArg) {
206        RENDER_SURFACE_STATE *dstRss = static_cast<RENDER_SURFACE_STATE *>(destSurfaceState);
207        uint32_t elSize = static_cast<uint32_t>(imgInfo.surfaceFormat->ImageElementSizeInBytes);
208        dstRss->setWidth(static_cast<uint32_t>((imgInfo.imgDesc.imageWidth * elSize) / sizeof(uint32_t)));
209    }
210}
211
212template <GFXCORE_FAMILY gfxCoreFamily>
213void ImageCoreFamily<gfxCoreFamily>::copyRedescribedSurfaceStateToSSH(void *surfaceStateHeap,
214                                                                      const uint32_t surfaceStateOffset) {
215    using GfxFamily = typename NEO::GfxFamilyMapper<gfxCoreFamily>::GfxFamily;
216    using RENDER_SURFACE_STATE = typename GfxFamily::RENDER_SURFACE_STATE;
217
218    // Copy the image's surface state into position in the provided surface state heap
219    auto destSurfaceState = ptrOffset(surfaceStateHeap, surfaceStateOffset);
220    memcpy_s(destSurfaceState, sizeof(RENDER_SURFACE_STATE),
221             &redescribedSurfaceState, sizeof(RENDER_SURFACE_STATE));
222}
223
224template <GFXCORE_FAMILY gfxCoreFamily>
225bool ImageCoreFamily<gfxCoreFamily>::isSuitableForCompression(const StructuresLookupTable &structuresLookupTable, const NEO::ImageInfo &imgInfo) {
226    auto &hwInfo = device->getHwInfo();
227    auto &l0HwHelper = L0HwHelper::get(hwInfo.platform.eRenderCoreFamily);
228
229    if (structuresLookupTable.uncompressedHint) {
230        return false;
231    }
232
233    return (l0HwHelper.imageCompressionSupported(hwInfo) && !imgInfo.linearStorage);
234}
235
236} // namespace L0
237