:orphan: .. _ZE_experimental_bindless_image: ======================================== Bindless Image Experimental Extension ======================================== API ---- * Enumerations * :ref:`ze-bindless-image-exp-version-t` * :ref:`ze-image-bindless-exp-flags-t` * Structures * :ref:`ze-device-pitched-alloc-exp-properties-t` * :ref:`ze-image-bindless-exp-desc-t` * :ref:`ze-image-pitched-exp-desc-t` * Functions * :ref:`zeMemGetPitchFor2dImage` * :ref:`zeImageGetDeviceOffsetExp` Bindless Images ~~~~~~~~~~~~~~~ A bindless image is defined as one which provides access to the underlying data via image reference handles. At the application level, this allows the user to implement programs where the number of images is not known at compile-time, and store all handles to images irrespective of varying formats and layouts in some container such as a dynamic array. Currently, in Level Zero, `zeImageCreate` performs the image memory allocation and image handle generation. This function only allows for the allocation of image memory in an implementation-specific layout. In this extension, we propose the following additions: * Provide a new image descriptor and flags for Bindless images. * Support for creation of images on linearly allocated memory backed by USM. * Extension API to create an image handle from pitched memory A "Bindless image" can be created by passing :ref:`ze-image-bindless-exp-desc-t` to pNext member of :ref:`ze-image-desc-t` and set the flags value as :ref:`ZE_IMAGE_BINDLESS_EXP_FLAG_BINDLESS ` This extension is complimentary to and may be used in conjunction with the `ZE_extension_image_view `_ extension Programming example with Bindless images ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. parsed-literal:: // Assumed image data on host std::vector imageDataHost; // 2D image dimensions size_t imageWidth = 1024; size_t imageHeight = 1024; // Single-precision float image format with one channel :ref:`ze-image-format-t` imageFormat = { ZE_IMAGE_FORMAT_LAYOUT_32, ZE_IMAGE_FORMAT_TYPE_FLOAT, ZE_IMAGE_FORMAT_SWIZZLE_R, ZE_IMAGE_FORMAT_SWIZZLE_X, ZE_IMAGE_FORMAT_SWIZZLE_R, ZE_IMAGE_FORMAT_SWIZZLE_X } // Create an image descriptor for bindless image :ref:`ze-image-desc-t` imageDesc = { ZE_STRUCTURE_TYPE_IMAGE_DESC, nullptr, 0, ZE_IMAGE_TYPE_2D, imageFormat, 128, 128, 0, 0, 0 }; :ref:`ze-image-bindless-exp-desc-t` bindlessImageDesc = {:ref:`ZE_STRUCTURE_TYPE_BINDLESS_IMAGE_EXP_DESC `\}; bindlessImageDesc.flags = :ref:`ZE_IMAGE_BINDLESS_EXP_FLAG_BINDLESS `\; imageDesc.pNext = &bindlessImageDesc; // A bindless image is valid on both host and device and can be passed into kernels // When passing :ref:`ZE_IMAGE_BINDLESS_EXP_FLAG_BINDLESS ` to zeImageCreate, only the backing memory is allocated for Image ze_image_handle_t hImage; :ref:`zeImageCreate`\(hContext, hDevice, &imageDesc, &hImage); //Copy To new bindless image memory :ref:`zeCommandListAppendImageCopyFromMemory`\(hCommandlist, hImage, imageDataHost.data(), nullptr, nullptr, 0, nullptr); // Launch kernel and perform appropriate synchronizations // Copy back :ref:`zeCommandListAppendImageCopyToMemory`\(hCommandlist, imageDataHost.data(), hImage, nullptr, nullptr, 0, nullptr); // Further image views can be created from the existing memory allocated using bindless flags ze_image_handle_t hImageView; :ref:`zeImageViewCreateExt`\(hContext, hDevice, &imageDesc, hImage, &hImageView); // New image view can be separately used by users and destroyed // ... // Once all operations are complete we need destroy bindless image handle(s) :ref:`zeImageDestroy`\(hImageView); :ref:`zeImageDestroy`\(hImage); Programming example with pitched memory usage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. parsed-literal:: // Retrieve pitched alloc properties specific to device :ref:`ze-device-image-properties-t` deviceImageProperties = {}; :ref:`ze-device-pitched-alloc-exp-properties-t` pitchedAllocProperties = {}; pitchedAllocProperties.stype = :ref:`ZE_STRUCTURE_TYPE_PITCHED_ALLOC_DEVICE_EXP_PROPERTIES ` deviceImageProperties.pNext = &pitchedAllocProperties; :ref:`zeDeviceGetImageProperties`\(hDevice, &deviceImageProperties); // Assumed image data on host std::vector imageDataHost; // 2D image dimensions size_t imageWidth = 1024; size_t imageHeight = 1024; //Pitched memory in linear layout size_t rowPitch; unsigned int elementSize = 128; :ref:`zeMemGetPitchFor2dImage`\(hContext, hDevice, imageWidth, imageHeight, elementSize, &rowPitch); size_t allocSize = rowPitch * imageHeight; :ref:`ze-device-mem-alloc-desc-t` allocDesc = {:ref:`ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC `\}; :ref:`zeMemAllocDevice`\(hContext, &allocDesc, allocSize, allocSize, hDevice, &pitchedPtr); // Declare the copy region for copying :ref:`ze-copy-region-t` copyRegion = {0, 0, 0, imageWidth * sizeof(float), imageHeight, 0}; // Copy from host to device :ref:`zeCommandListAppendMemoryCopyRegion`\(hCommandList, pitchedPtr, ©Region, rowPitch, 0, imageDataHost.data(), ©Region, imageWidth * sizeof(float), 0, nullptr, 0, nullptr); // Single-precision float image format with one channel :ref:`ze-image-format-t` imageFormat = { ZE_IMAGE_FORMAT_LAYOUT_32, ZE_IMAGE_FORMAT_TYPE_FLOAT, ZE_IMAGE_FORMAT_SWIZZLE_R, ZE_IMAGE_FORMAT_SWIZZLE_X, ZE_IMAGE_FORMAT_SWIZZLE_R, ZE_IMAGE_FORMAT_SWIZZLE_X } // Create an image descriptor for bindless image :ref:`ze-image-desc-t` imageDesc = { ZE_STRUCTURE_TYPE_IMAGE_DESC, nullptr, 0, ZE_IMAGE_TYPE_2D, imageFormat, 128, 128, 0, 0, 0 }; :ref:`ze-image-pitched-exp-desc-t` pitchedImageDesc = {:ref:`ZE_STRUCTURE_TYPE_PITCHED_IMAGE_EXP_DESC `\}; pitchedImageDesc.ptr = pitchedPtr; imageDesc.pNext = &pitchedImageDesc; // A image created out of pitched memory is valid on both host and device and can be passed into kernels ze_image_handle_t hImage; :ref:`zeImageCreate`\(hContext, hDevice, &imageDesc, &hImage); // Launch kernel and perform appropriate synchronizations // ... // Copy from device to host :ref:`zeCommandListAppendMemoryCopyRegion`\(hCommandList, imageDataHost.data(), ©Region, imageWidth * sizeof(float), 0, pitchedPtr, ©Region, rowPitch, 0, nullptr, 0, nullptr); // Once all operations on the image are complete we need destroy image handle and free memory :ref:`zeImageDestroy`\(hImage); :ref:`zeMemFree`\(hContext, pitchedPtr);