Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 130 additions & 1 deletion src/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,35 @@ bool is_valid_device_type(cl_device_type type) {
(type == CL_DEVICE_TYPE_ALL);
}

bool is_valid_mem_flags(cl_mem_flags flags) {
// Reject unknown flags
return (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
CL_MEM_COPY_HOST_PTR | CL_MEM_HOST_WRITE_ONLY |
CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)) == 0;
}

bool is_valid_image_format(const cl_image_format* format) {
switch (format->image_channel_data_type) {
case CL_UNORM_SHORT_565:
case CL_UNORM_SHORT_555:
case CL_UNORM_INT_101010:
return format->image_channel_order == CL_RGB ||
format->image_channel_order == CL_RGBx;
case CL_UNORM_INT_101010_2:
return format->image_channel_order == CL_RGBA;
}
return true;
}

bool is_valid_image_descriptor(const cl_image_desc* desc) {
if (!cvk_mem::is_image_type(desc->image_type)) {
return false;
}
// TODO any other checks?
return true;
}

bool map_flags_are_valid(cl_map_flags flags) {
if ((flags & CL_MAP_WRITE_INVALIDATE_REGION) &&
(flags & (CL_MAP_READ | CL_MAP_WRITE))) {
Expand Down Expand Up @@ -309,6 +338,7 @@ static const std::unordered_map<std::string, void*> gExtensionEntrypoints = {
EXTENSION_ENTRYPOINT(clGetSemaphoreInfoKHR),
EXTENSION_ENTRYPOINT(clRetainSemaphoreKHR),
EXTENSION_ENTRYPOINT(clReleaseSemaphoreKHR),
EXTENSION_ENTRYPOINT(clGetImageRequirementsInfoEXT),
#undef EXTENSION_ENTRYPOINT
#undef FUNC_PTR
};
Expand Down Expand Up @@ -734,7 +764,7 @@ cl_int CLVK_API_CALL clGetDeviceInfo(cl_device_id dev,
size_ret = sizeof(val_sizet);
break;
case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE:
val_sizet = device->vulkan_limits().maxImageArrayLayers;
val_sizet = device->image_max_array_size();
copy_ptr = &val_sizet;
size_ret = sizeof(val_sizet);
break;
Expand Down Expand Up @@ -6650,3 +6680,102 @@ cl_int CLVK_API_CALL clGetKernelSuggestedLocalWorkSizeKHR(

return CL_SUCCESS;
}

cl_int clGetImageRequirementsInfoEXT(
cl_context context, const cl_mem_properties* properties, cl_mem_flags flags,
const cl_image_format* image_format, const cl_image_desc* image_desc,
cl_image_requirements_info_ext param_name, size_t param_value_size,
void* param_value, size_t* param_value_size_ret) {
LOG_API_CALL("context = %p, properties = %p, flags = %lx, image_format = "
"%p, image_desc = %p, "
"param_name = %x, param_value_size = %zu, param_value = %p, "
"param_value_size_ret = %p",
context, properties, flags, image_format, image_desc,
param_name, param_value_size, param_value,
param_value_size_ret);

if (!is_valid_context(context)) {
return CL_INVALID_CONTEXT;
}

if (!is_valid_mem_flags(flags)) {
return CL_INVALID_VALUE;
}

if ((image_format != nullptr) && !is_valid_image_format(image_format)) {
return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
}

if ((image_desc != nullptr) && !is_valid_image_descriptor(image_desc)) {
return CL_INVALID_IMAGE_DESCRIPTOR;
}

auto device = icd_downcast(context)->device();

cl_int ret = CL_SUCCESS;
size_t size_ret = 0;
const void* copy_ptr = nullptr;
cl_uint val_uint;

switch (param_name) {
case CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT:
val_uint = device->image_max_width(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == 0 ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE3D)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint = device->image_max_height(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == 0 ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE3D)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint = device->image_max_depth(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == 0 ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint =
device->image_max_array_size(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
default:
ret = CL_INVALID_VALUE;
break;
}
Comment on lines +6720 to +6766

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
switch (param_name) {
case CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT:
val_uint = device->image_max_width(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == 0 ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE3D)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint = device->image_max_height(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == 0 ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE3D)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint = device->image_max_depth(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == 0 ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint =
device->image_max_array_size(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
default:
ret = CL_INVALID_VALUE;
break;
}
switch (param_name) {
case CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT:
val_uint = device->image_max_width(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == CL_MEM_OBJECT_IMAGE2D ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE3D)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint = device->image_max_height(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == CL_MEM_OBJECT_IMAGE3D)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint = device->image_max_depth(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
case CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT:
if ((image_desc != nullptr) &&
!(image_desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY ||
image_desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY)) {
ret = CL_INVALID_IMAGE_DESCRIPTOR;
break;
}
val_uint =
device->image_max_array_size(flags, image_desc, image_format);
copy_ptr = &val_uint;
size_ret = sizeof(val_uint);
break;
default:
ret = CL_INVALID_VALUE;
break;
}

image_desc->image_type != 0 for sure because of the call to is_valid_image_descriptor earlier in the function.


if ((param_value != nullptr) && (param_value_size < size_ret)) {
ret = CL_INVALID_VALUE;
}

if ((param_value != nullptr) && (copy_ptr != nullptr)) {
memcpy(param_value, copy_ptr, param_value_size);
}

if (param_value_size_ret != nullptr) {
*param_value_size_ret = size_ret;
}

return ret;
}
160 changes: 160 additions & 0 deletions src/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ void cvk_device::build_extension_ils_list() {
MAKE_NAME_VERSION(1, 0, 0, "cl_khr_3d_image_writes"),
// MAKE_NAME_VERSION(0, 9, 0, "cl_khr_semaphore"),
MAKE_NAME_VERSION(1, 0, 0, "cl_khr_spirv_linkonce_odr"),
MAKE_NAME_VERSION(1, 0, 0, "cl_ext_image_requirements_info"),
};

if (m_properties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
Expand Down Expand Up @@ -1334,3 +1335,162 @@ cl_int cvk_device::device_timer_to_host(cl_ulong dev, cl_ulong& host) {
}
return CL_SUCCESS;
}

std::optional<VkImageFormatProperties>
cvk_device::get_vulkan_image_format_properties(
cl_mem_flags flags, const cl_image_desc* desc,
const cl_image_format* format) const {

if ((format == nullptr) || (desc == nullptr) ||
(desc != nullptr && desc->image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER)) {
return get_vulkan_image_format_properties(desc);
}

CVK_ASSERT(desc);
CVK_ASSERT(desc->image_type != CL_MEM_OBJECT_IMAGE1D_BUFFER);
CVK_ASSERT(format);

// Get Vulkan format
image_format_support fmt;
if (!cl_image_format_to_vulkan_format(*format, desc->image_type, this,
&fmt)) {
return std::nullopt;
}

// Get Vulkan image type
VkImageType image_type;
switch (desc->image_type) {
case CL_MEM_OBJECT_IMAGE1D:
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
image_type = VK_IMAGE_TYPE_1D;
break;
case CL_MEM_OBJECT_IMAGE2D:
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
image_type = VK_IMAGE_TYPE_2D;
break;
case CL_MEM_OBJECT_IMAGE3D:
image_type = VK_IMAGE_TYPE_3D;
break;
default:
CVK_ASSERT(false && "Unsupported image type");
break;
}
Comment thread
kpet marked this conversation as resolved.

// Get Vulkan image tiling
VkImageTiling tiling = cvk_image::prepare_tiling();

// Get Vulkan usage flags
VkImageUsageFlags usage_flags = cvk_image::prepare_usage_flags(flags);

// Get Vulkan image create flags;
VkImageCreateFlags create_flags = cvk_image::prepare_create_flags();

// Query limits from Vulkan
VkImageFormatProperties properties;
auto res = vkGetPhysicalDeviceImageFormatProperties(
m_pdev, fmt.vkfmt, image_type, tiling, usage_flags, create_flags,
&properties);
if (res != VK_SUCCESS) {
return std::nullopt;
}
return properties;
}

VkImageFormatProperties cvk_device::get_vulkan_image_format_properties(
const cl_image_desc* desc) const {

VkImageFormatProperties properties{};
properties.maxExtent = {1, 1, 1};
properties.maxMipLevels = 1;
properties.maxArrayLayers = vulkan_limits().maxImageArrayLayers;
properties.sampleCounts = VK_SAMPLE_COUNT_1_BIT;
properties.maxResourceSize = 1 << 31;

if ((desc == nullptr) || (desc->image_type == 0)) {
auto max1d = vulkan_limits().maxImageDimension1D;
auto max2d = vulkan_limits().maxImageDimension2D;
auto max3d = vulkan_limits().maxImageDimension3D;
auto maxbuffer = image_max_buffer_size();
cl_uint max_size = std::min(max1d, max2d);
max_size = std::min(max_size, max3d);
max_size = std::min(max_size, static_cast<cl_uint>(maxbuffer));
properties.maxExtent.width = max_size;
properties.maxExtent.height = max_size;
properties.maxExtent.depth = max_size;
return properties;
}

switch (desc->image_type) {
case CL_MEM_OBJECT_IMAGE1D_BUFFER:
properties.maxExtent.width = image_max_buffer_size();
break;
case CL_MEM_OBJECT_IMAGE1D:
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
properties.maxExtent.width = vulkan_limits().maxImageDimension1D;
break;
case CL_MEM_OBJECT_IMAGE2D:
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
properties.maxExtent.width = vulkan_limits().maxImageDimension2D;
properties.maxExtent.height = vulkan_limits().maxImageDimension2D;
break;
case CL_MEM_OBJECT_IMAGE3D:
properties.maxExtent.width = vulkan_limits().maxImageDimension3D;
properties.maxExtent.height = vulkan_limits().maxImageDimension3D;
properties.maxExtent.depth = vulkan_limits().maxImageDimension3D;
break;
default:
CVK_ASSERT(false && "Unsupported image type");
break;
}
return properties;
}

cl_uint cvk_device::image_max_width(cl_mem_flags flags,
const cl_image_desc* image_desc,
const cl_image_format* image_format) const {
auto properties =
get_vulkan_image_format_properties(flags, image_desc, image_format);
if (!properties) {
return 0;
}

return properties->maxExtent.width;
}

cl_uint
cvk_device::image_max_height(cl_mem_flags flags,
const cl_image_desc* image_desc,
const cl_image_format* image_format) const {
auto properties =
get_vulkan_image_format_properties(flags, image_desc, image_format);
if (!properties) {
return 0;
}

return properties->maxExtent.height;
}

cl_uint cvk_device::image_max_depth(cl_mem_flags flags,
const cl_image_desc* image_desc,
const cl_image_format* image_format) const {
auto properties =
get_vulkan_image_format_properties(flags, image_desc, image_format);
if (!properties) {
return 0;
}

return properties->maxExtent.depth;
}

cl_uint
cvk_device::image_max_array_size(cl_mem_flags flags,
const cl_image_desc* image_desc,
const cl_image_format* image_format) const {
auto properties =
get_vulkan_image_format_properties(flags, image_desc, image_format);
if (!properties) {
return 0;
}

return properties->maxArrayLayers;
}
24 changes: 24 additions & 0 deletions src/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <algorithm>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -425,6 +426,23 @@ struct cvk_device : public _cl_device_id,
return res;
}

cl_uint
image_max_width(cl_mem_flags flags = 0,
const cl_image_desc* image_desc = nullptr,
const cl_image_format* image_format = nullptr) const;
cl_uint
image_max_height(cl_mem_flags flags = 0,
const cl_image_desc* image_desc = nullptr,
const cl_image_format* image_format = nullptr) const;
cl_uint
image_max_depth(cl_mem_flags flags = 0,
const cl_image_desc* image_desc = nullptr,
const cl_image_format* image_format = nullptr) const;
cl_uint
image_max_array_size(cl_mem_flags flags = 0,
const cl_image_desc* image_desc = nullptr,
const cl_image_format* image_format = nullptr) const;

bool supports_images() const {
return devices_support_images() ? CL_TRUE : CL_FALSE;
}
Expand Down Expand Up @@ -762,6 +780,12 @@ struct cvk_device : public _cl_device_id,
"clvk-device_" + std::to_string((uintptr_t)this))

private:
std::optional<VkImageFormatProperties>
get_vulkan_image_format_properties(cl_mem_flags flags,
const cl_image_desc* desc,
const cl_image_format* format) const;
VkImageFormatProperties
get_vulkan_image_format_properties(const cl_image_desc* desc) const;
std::string version_desc() const {
std::string ret = "CLVK on Vulkan v";
ret += vulkan_version_string(m_properties.apiVersion);
Expand Down
Loading
Loading