Skip to content

Commit

Permalink
WIP texel buffers
Browse files Browse the repository at this point in the history
Change-Id: I4eef91af393b5487bbc208bdc96d43daa4c5c462
  • Loading branch information
kpet authored and rjodinchr committed Oct 13, 2023
1 parent 7c824fe commit c849f79
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 51 deletions.
80 changes: 50 additions & 30 deletions src/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ cl_int CLVK_API_CALL clGetDeviceInfo(cl_device_id dev,
size_ret = sizeof(val_uint);
break;
case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE:
val_sizet = device->vulkan_limits().maxImageDimension1D;
val_sizet = device->vulkan_limits().maxTexelBufferElements;
copy_ptr = &val_sizet;
size_ret = sizeof(val_sizet);
break;
Expand Down Expand Up @@ -4718,22 +4718,13 @@ std::unordered_map<cl_image_format, image_format_support, ClFormatMapHash,
{{CL_BGRA, CL_SIGNED_INT8}, VK_FORMAT_B8G8R8A8_SINT},
};

bool cl_image_format_to_vulkan_format(const cl_image_format& clformat,
VkFormat* format,
VkComponentMapping* components_sampled,
VkComponentMapping* components_storage) {
auto m = gFormatMaps.find(clformat);
bool success = false;

if (m != gFormatMaps.end()) {
*format = (*m).second.vkfmt;
success = true;
}

if (clformat.image_channel_order == CL_LUMINANCE) {
static void get_component_mappings_for_channel_order(
cl_channel_order order, VkComponentMapping* components_sampled,
VkComponentMapping* components_storage) {
if (order == CL_LUMINANCE) {
*components_sampled = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A};
} else if (clformat.image_channel_order == CL_INTENSITY) {
} else if (order == CL_INTENSITY) {
*components_sampled = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R};
} else {
Expand All @@ -4745,10 +4736,30 @@ bool cl_image_format_to_vulkan_format(const cl_image_format& clformat,
*components_storage = {
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
}

bool cl_image_format_to_vulkan_format(const cl_image_format& clformat,
VkFormat* format,
VkComponentMapping* components_sampled,
VkComponentMapping* components_storage) {
auto m = gFormatMaps.find(clformat);
bool success = false;

if (m != gFormatMaps.end()) {
*format = (*m).second.vkfmt;
success = true;
}

get_component_mappings_for_channel_order(
clformat.image_channel_order, components_sampled, components_storage);

return success;
}

bool operator!=(const VkComponentMapping& lhs, const VkComponentMapping& rhs) {
return lhs.r != rhs.r || lhs.g != rhs.g || lhs.b != rhs.b || lhs.a != rhs.a;
}

cl_int CLVK_API_CALL clGetSupportedImageFormats(cl_context context,
cl_mem_flags flags,
cl_mem_object_type image_type,
Expand Down Expand Up @@ -4809,29 +4820,38 @@ cl_int CLVK_API_CALL clGetSupportedImageFormats(cl_context context,
" buffer : %s",
vulkan_format_features_string(properties.bufferFeatures).c_str());

cvk_debug(" required format features %s",
vulkan_format_features_string(required_format_feature_flags)
.c_str());
cvk_debug(
"Required format features %s",
vulkan_format_features_string(required_format_feature_flags).c_str());
VkFormatFeatureFlags features;
// TODO support linear tiling
features = properties.optimalTilingFeatures;

auto channel_order_str =
cl_channel_order_to_string(clfmt.image_channel_order);
auto channel_type_str =
cl_channel_type_to_string(clfmt.image_channel_data_type);
if (image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER) {
features = properties.bufferFeatures;
} else {
// TODO support linear tiling
features = properties.optimalTilingFeatures;
}
if ((features & required_format_feature_flags) ==
required_format_feature_flags) {
const cl_image_format& clfmt = clvkfmt.first;
VkComponentMapping components_sampled, components_storage;
get_component_mappings_for_channel_order(
clfmt.image_channel_order, &components_sampled,
&components_storage);
if ((components_sampled != components_storage) &&
(image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER)) {
continue;
}
if ((image_formats != nullptr) &&
(num_formats_found < num_entries)) {
image_formats[num_formats_found] = clfmt;
cvk_debug(" reporting image format {%s, %s}",
channel_order_str.c_str(), channel_type_str.c_str());
cvk_debug_fn(
"reporting image format {%s, %s}",
cl_channel_order_to_string(clfmt.image_channel_order)
.c_str(),
cl_channel_type_to_string(clfmt.image_channel_data_type)
.c_str());
}
num_formats_found++;
} else {
cvk_debug(" no support for image format {%s, %s}",
channel_order_str.c_str(), channel_type_str.c_str());
}
}

Expand Down
1 change: 1 addition & 0 deletions src/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,7 @@ bool cvk_device::supports_capability(spv::Capability capability) const {
case spv::CapabilityImage1D:
case spv::CapabilityImageQuery:
case spv::CapabilityImageBuffer:
case spv::CapabilitySampledBuffer:
return true;
// Optional capabilities:
case spv::CapabilityFloat16:
Expand Down
36 changes: 35 additions & 1 deletion src/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ cl_int cvk_kernel::set_arg(cl_uint index, size_t size, const void* value) {
// if the argument is an image, we need to set its metadata
// (channel_order/channel_data_type).
if (arg.kind == kernel_argument_kind::sampled_image ||
arg.kind == kernel_argument_kind::storage_image) {
arg.kind == kernel_argument_kind::storage_image ||
arg.kind == kernel_argument_kind::storage_texel_buffer ||
arg.kind == kernel_argument_kind::uniform_texel_buffer) {
set_image_metadata(index, value);
}

Expand Down Expand Up @@ -155,9 +157,11 @@ bool cvk_kernel_argument_values::setup_descriptor_sets() {
std::vector<VkWriteDescriptorSet> descriptor_writes;
std::vector<VkDescriptorBufferInfo> buffer_info;
std::vector<VkDescriptorImageInfo> image_info;
std::vector<VkBufferView> buffer_views;
descriptor_writes.reserve(max_descriptor_writes);
buffer_info.reserve(max_descriptor_writes);
image_info.reserve(max_descriptor_writes);
buffer_views.reserve(max_descriptor_writes);

// Setup module-scope variables
if (program->module_constant_data_buffer() != nullptr &&
Expand Down Expand Up @@ -324,6 +328,36 @@ bool cvk_kernel_argument_values::setup_descriptor_sets() {
descriptor_writes.push_back(writeDescriptorSet);
break;
}
case kernel_argument_kind::storage_texel_buffer:
case kernel_argument_kind::uniform_texel_buffer: {
auto image = static_cast<cvk_image*>(get_arg_value(arg));
bool uniform =
arg.kind == kernel_argument_kind::uniform_texel_buffer;
auto view = image->vulkan_buffer_view();
buffer_views.push_back(view);

cvk_debug_fn("buffer view %p @ set = %u, binding = %u", view,
arg.descriptorSet, arg.binding);

VkDescriptorType dtype =
uniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;

VkWriteDescriptorSet writeDescriptorSet = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
ds[arg.descriptorSet],
arg.binding, // dstBinding
0, // dstArrayElement
1, // descriptorCount
dtype,
nullptr, // pImageInfo
nullptr, // pBufferInfo
&buffer_views.back(), // pTexelBufferView
};
descriptor_writes.push_back(writeDescriptorSet);
break;
}
case kernel_argument_kind::pod: // skip POD arguments
case kernel_argument_kind::pod_ubo:
case kernel_argument_kind::pod_pushconstant:
Expand Down
81 changes: 70 additions & 11 deletions src/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,22 +243,33 @@ bool cvk_sampler::init() {
VkFormatFeatureFlags
cvk_image::required_format_feature_flags_for(cl_mem_object_type type,
cl_mem_flags flags) {
UNUSED(type); // TODO will be required for 1D buffer images
// All images require TRANSFER_SRC, TRANSFER_DST
// 1Dbuffer requires
// RW / RaW: STORAGE_TEXEL_BUFFER
// RO: UNIFORM_TEXEL_BUFFER
// All other images require TRANSFER_SRC, TRANSFER_DST
// read-only: SAMPLED_IMAGE, SAMPLED_IMAGE_FILTER_LINEAR
// write-only: STORAGE_IMAGE
// read-write: STORAGE_IMAGE, SAMPLED_IMAGE, SAMPLED_IMAGE_FILTER_LINEAR
// read-and-write: STORAGE_IMAGE
VkFormatFeatureFlags format_feature_flags = 0;
format_feature_flags =
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;

if (type != CL_MEM_OBJECT_IMAGE1D_BUFFER) {
format_feature_flags = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
}
VkFormatFeatureFlags format_feature_flags_RO;
format_feature_flags_RO = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;

if (type == CL_MEM_OBJECT_IMAGE1D_BUFFER) {
format_feature_flags_RO = VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
} else {
format_feature_flags_RO =
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
}
VkFormatFeatureFlags format_feature_flags_WO;
format_feature_flags_WO = VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
if (type == CL_MEM_OBJECT_IMAGE1D_BUFFER) {
format_feature_flags_WO = VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
} else {
format_feature_flags_WO = VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
}

if (flags & (CL_MEM_KERNEL_READ_AND_WRITE | CL_MEM_WRITE_ONLY)) {
format_feature_flags |= format_feature_flags_WO;
Expand Down Expand Up @@ -292,7 +303,7 @@ cl_image_format_to_vulkan_format(const cl_image_format& clfmt,
VkComponentMapping* components_sampled,
VkComponentMapping* components_storage);

bool cvk_image::init() {
bool cvk_image::init_vulkan_image() {
// Translate image type and size
VkImageType image_type;
VkImageViewType view_type;
Expand Down Expand Up @@ -320,7 +331,6 @@ bool cvk_image::init() {
size_t host_ptr_size = 0;

switch (m_desc.image_type) {
case CL_MEM_OBJECT_IMAGE1D_BUFFER:
case CL_MEM_OBJECT_IMAGE1D:
image_type = VK_IMAGE_TYPE_1D;
view_type = VK_IMAGE_VIEW_TYPE_1D;
Expand Down Expand Up @@ -485,6 +495,55 @@ bool cvk_image::init() {
return true;
}

bool cvk_image::init_vulkan_texel_buffer() {
VkResult res;

auto device = m_context->device();
auto vkdev = device->vulkan_device();

VkFormat format;
VkComponentMapping components_sampled, components_storage;

auto success = cl_image_format_to_vulkan_format(
m_format, &format, &components_sampled, &components_storage);
if (!success) {
return false;
}

CVK_ASSERT(buffer());
CVK_ASSERT(buffer()->is_buffer_type());

auto vkbuf = static_cast<cvk_buffer*>(buffer())->vulkan_buffer();

VkBufferViewCreateInfo createInfo = {
VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
nullptr,
0, // flags
vkbuf, // buffer
format, // format
0, // offset
VK_WHOLE_SIZE // range
};

res = vkCreateBufferView(vkdev, &createInfo, nullptr, &m_buffer_view);
if (res != VK_SUCCESS) {
cvk_error_fn("Could not create buffer view");
return false;
}

buffer()->retain();

return true;
}

bool cvk_image::init() {
if (is_backed_by_buffer_view()) {
return init_vulkan_texel_buffer();
} else {
return init_vulkan_image();
}
}

void cvk_image::prepare_fill_pattern(const void* input_pattern,
fill_pattern_array& pattern,
size_t* size_ret) const {
Expand Down
45 changes: 38 additions & 7 deletions src/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,9 @@ struct cvk_buffer : public cvk_mem {
VkBufferUsageFlags usage_flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
if (m_context->device()->uses_physical_addressing()) {
usage_flags |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
}
Expand Down Expand Up @@ -485,10 +487,16 @@ struct cvk_image : public cvk_mem {
/* FIXME parent_offset */ 0, std::move(properties),
desc->image_type),
m_desc(*desc), m_format(*format), m_image(VK_NULL_HANDLE),
m_sampled_view(VK_NULL_HANDLE), m_storage_view(VK_NULL_HANDLE) {
m_sampled_view(VK_NULL_HANDLE), m_storage_view(VK_NULL_HANDLE),
m_buffer_view(VK_NULL_HANDLE) {
// All images require asynchronous initialiation for the initial
// layout transition (and copy/use host ptr init)
m_init_tracker.set_state(cvk_mem_init_state::required);
// layout transition (and copy/use host ptr init) apart from
// those backed by a texel buffer
if (is_backed_by_buffer_view()) {
m_init_tracker.set_state(cvk_mem_init_state::completed);
} else {
m_init_tracker.set_state(cvk_mem_init_state::required);
}
}

~cvk_image() {
Expand All @@ -502,6 +510,9 @@ struct cvk_image : public cvk_mem {
if (m_storage_view != VK_NULL_HANDLE) {
vkDestroyImageView(vkdev, m_storage_view, nullptr);
}
if (m_buffer_view != VK_NULL_HANDLE) {
vkDestroyBufferView(vkdev, m_buffer_view, nullptr);
}
if (buffer() != nullptr) {
buffer()->release();
}
Expand Down Expand Up @@ -530,9 +541,26 @@ struct cvk_image : public cvk_mem {
const cl_image_format* format, void* host_ptr,
std::vector<cl_mem_properties>&& properties);

VkImage vulkan_image() const { return m_image; }
VkImageView vulkan_sampled_view() const { return m_sampled_view; }
VkImageView vulkan_storage_view() const { return m_storage_view; }
bool is_backed_by_buffer_view() const {
return type() == CL_MEM_OBJECT_IMAGE1D_BUFFER;
}

VkImage vulkan_image() const {
CVK_ASSERT(!is_backed_by_buffer_view());
return m_image;
}
VkImageView vulkan_sampled_view() const {
CVK_ASSERT(!is_backed_by_buffer_view());
return m_sampled_view;
}
VkImageView vulkan_storage_view() const {
CVK_ASSERT(!is_backed_by_buffer_view());
return m_storage_view;
}
VkBufferView vulkan_buffer_view() const {
CVK_ASSERT(is_backed_by_buffer_view());
return m_buffer_view;
}
const cl_image_format& format() const { return m_format; }
size_t element_size() const {
switch (m_format.image_channel_data_type) {
Expand Down Expand Up @@ -693,6 +721,8 @@ struct cvk_image : public cvk_mem {
size_t* size_ret) const;

private:
bool init_vulkan_image();
bool init_vulkan_texel_buffer();
bool init();

size_t num_channels() const {
Expand Down Expand Up @@ -746,6 +776,7 @@ struct cvk_image : public cvk_mem {
VkImage m_image;
VkImageView m_sampled_view;
VkImageView m_storage_view;
VkBufferView m_buffer_view;
std::unordered_map<void*, std::list<cvk_image_mapping>> m_mappings;
std::mutex m_mappings_lock;
std::unique_ptr<cvk_buffer> m_init_data;
Expand Down
Loading

0 comments on commit c849f79

Please sign in to comment.