v3dv: implement vkCreateImageView
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_formats.c b/src/broadcom/vulkan/v3dv_formats.c
index 5f6a20a..f78b1d2 100644
--- a/src/broadcom/vulkan/v3dv_formats.c
+++ b/src/broadcom/vulkan/v3dv_formats.c
@@ -71,6 +71,136 @@
return NULL;
}
+void
+v3dv_get_internal_type_bpp_for_output_format(uint32_t format,
+ uint32_t *type,
+ uint32_t *bpp)
+{
+ switch (format) {
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA8:
+ case V3D_OUTPUT_IMAGE_FORMAT_RGB8:
+ case V3D_OUTPUT_IMAGE_FORMAT_RG8:
+ case V3D_OUTPUT_IMAGE_FORMAT_R8:
+ case V3D_OUTPUT_IMAGE_FORMAT_ABGR4444:
+ case V3D_OUTPUT_IMAGE_FORMAT_BGR565:
+ case V3D_OUTPUT_IMAGE_FORMAT_ABGR1555:
+ *type = V3D_INTERNAL_TYPE_8;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA8I:
+ case V3D_OUTPUT_IMAGE_FORMAT_RG8I:
+ case V3D_OUTPUT_IMAGE_FORMAT_R8I:
+ *type = V3D_INTERNAL_TYPE_8I;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA8UI:
+ case V3D_OUTPUT_IMAGE_FORMAT_RG8UI:
+ case V3D_OUTPUT_IMAGE_FORMAT_R8UI:
+ *type = V3D_INTERNAL_TYPE_8UI;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_SRGB8_ALPHA8:
+ case V3D_OUTPUT_IMAGE_FORMAT_SRGB:
+ case V3D_OUTPUT_IMAGE_FORMAT_RGB10_A2:
+ case V3D_OUTPUT_IMAGE_FORMAT_R11F_G11F_B10F:
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA16F:
+ /* Note that sRGB RTs are stored in the tile buffer at 16F,
+ * and the conversion to sRGB happens at tilebuffer load/store.
+ */
+ *type = V3D_INTERNAL_TYPE_16F;
+ *bpp = V3D_INTERNAL_BPP_64;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RG16F:
+ case V3D_OUTPUT_IMAGE_FORMAT_R16F:
+ *type = V3D_INTERNAL_TYPE_16F;
+ /* Use 64bpp to make sure the TLB doesn't throw away the alpha
+ * channel before alpha test happens.
+ */
+ *bpp = V3D_INTERNAL_BPP_64;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA16I:
+ *type = V3D_INTERNAL_TYPE_16I;
+ *bpp = V3D_INTERNAL_BPP_64;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RG16I:
+ case V3D_OUTPUT_IMAGE_FORMAT_R16I:
+ *type = V3D_INTERNAL_TYPE_16I;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RGB10_A2UI:
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA16UI:
+ *type = V3D_INTERNAL_TYPE_16UI;
+ *bpp = V3D_INTERNAL_BPP_64;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RG16UI:
+ case V3D_OUTPUT_IMAGE_FORMAT_R16UI:
+ *type = V3D_INTERNAL_TYPE_16UI;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA32I:
+ *type = V3D_INTERNAL_TYPE_32I;
+ *bpp = V3D_INTERNAL_BPP_128;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RG32I:
+ *type = V3D_INTERNAL_TYPE_32I;
+ *bpp = V3D_INTERNAL_BPP_64;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_R32I:
+ *type = V3D_INTERNAL_TYPE_32I;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA32UI:
+ *type = V3D_INTERNAL_TYPE_32UI;
+ *bpp = V3D_INTERNAL_BPP_128;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RG32UI:
+ *type = V3D_INTERNAL_TYPE_32UI;
+ *bpp = V3D_INTERNAL_BPP_64;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_R32UI:
+ *type = V3D_INTERNAL_TYPE_32UI;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RGBA32F:
+ *type = V3D_INTERNAL_TYPE_32F;
+ *bpp = V3D_INTERNAL_BPP_128;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_RG32F:
+ *type = V3D_INTERNAL_TYPE_32F;
+ *bpp = V3D_INTERNAL_BPP_64;
+ break;
+
+ case V3D_OUTPUT_IMAGE_FORMAT_R32F:
+ *type = V3D_INTERNAL_TYPE_32F;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+
+ default:
+ /* Provide some default values, as we'll be called at RB
+ * creation time, even if an RB with this format isn't supported.
+ */
+ *type = V3D_INTERNAL_TYPE_8;
+ *bpp = V3D_INTERNAL_BPP_32;
+ break;
+ }
+}
+
static VkFormatFeatureFlags
image_format_features(VkFormat vk_format,
const struct v3dv_format *v3dv_format,
diff --git a/src/broadcom/vulkan/v3dv_image.c b/src/broadcom/vulkan/v3dv_image.c
index 14b8b12..a4a2fb8 100644
--- a/src/broadcom/vulkan/v3dv_image.c
+++ b/src/broadcom/vulkan/v3dv_image.c
@@ -244,6 +244,17 @@
}
}
+static uint32_t
+layer_offset(struct v3dv_image *image, uint32_t level, uint32_t layer)
+{
+ struct v3d_resource_slice *slice = &image->slices[level];
+
+ if (image->type == VK_IMAGE_TYPE_3D)
+ return slice->offset + layer * slice->size;
+ else
+ return slice->offset + layer * image->cube_map_stride;
+}
+
VkResult
v3dv_CreateImage(VkDevice _device,
const VkImageCreateInfo *pCreateInfo,
@@ -297,3 +308,76 @@
return VK_SUCCESS;
}
+
+VkResult
+v3dv_CreateImageView(VkDevice _device,
+ const VkImageViewCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkImageView *pView)
+{
+ V3DV_FROM_HANDLE(v3dv_device, device, _device);
+ V3DV_FROM_HANDLE(v3dv_image, image, pCreateInfo->image);
+ struct v3dv_image_view *iview;
+
+ iview = vk_zalloc2(&device->alloc, pAllocator, sizeof(*iview), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (iview == NULL)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
+
+ assert(range->layerCount > 0);
+ assert(range->baseMipLevel < image->levels);
+
+ /* FIXME: we don't handle depth/stencil yet */
+ assert((range->aspectMask &
+ (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0);
+
+#ifdef DEBUG
+ switch (image->type) {
+ case VK_IMAGE_TYPE_1D:
+ case VK_IMAGE_TYPE_2D:
+ assert(range->baseArrayLayer + v3dv_layer_count(image, range) - 1 <=
+ image->array_size);
+ break;
+ case VK_IMAGE_TYPE_3D:
+ assert(range->baseArrayLayer + v3dv_layer_count(image, range) - 1
+ <= u_minify(image->extent.depth, range->baseMipLevel));
+ break;
+ default:
+ unreachable("bad VkImageType");
+ }
+#endif
+
+ iview->image = image;
+ iview->aspects = range->aspectMask;
+ iview->extent = (VkExtent3D) {
+ .width = u_minify(image->extent.width , range->baseMipLevel),
+ .height = u_minify(image->extent.height, range->baseMipLevel),
+ .depth = u_minify(image->extent.depth , range->baseMipLevel),
+ };
+
+ iview->first_layer = range->baseArrayLayer;
+ iview->last_layer = range->baseArrayLayer +
+ v3dv_layer_count(image, range) - 1;
+ iview->offset = layer_offset(image, range->baseMipLevel, iview->first_layer);
+
+ iview->tiling = image->slices[0].tiling;
+
+ iview->vk_format = pCreateInfo->format;
+ iview->format = v3dv_get_format(pCreateInfo->format);
+ assert(iview->format && iview->format->supported);
+
+ const struct util_format_description *desc =
+ vk_format_description(iview->vk_format);
+ iview->swap_rb = desc->swizzle[0] == PIPE_SWIZZLE_Z &&
+ iview->vk_format != VK_FORMAT_B5G6R5_UNORM_PACK16;
+
+ v3dv_get_internal_type_bpp_for_output_format(iview->format->rt_type,
+ &iview->internal_type,
+ &iview->internal_bpp);
+
+ *pView = v3dv_image_view_to_handle(iview);
+
+ return VK_SUCCESS;
+}
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index a37d0fc..b4a4494 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -278,6 +278,23 @@
VkDeviceSize mem_offset;
};
+struct v3dv_image_view {
+ const struct v3dv_image *image;
+ VkImageAspectFlags aspects;
+ VkExtent3D extent;
+
+ VkFormat vk_format;
+ const struct v3dv_format *format;
+ bool swap_rb;
+ enum v3d_tiling_mode tiling;
+ uint32_t internal_bpp;
+ uint32_t internal_type;
+
+ uint32_t first_layer;
+ uint32_t last_layer;
+ uint32_t offset;
+};
+
struct v3dv_shader_module {
unsigned char sha1[20];
uint32_t size;
@@ -321,6 +338,7 @@
void v3dv_loge_v(const char *format, va_list va);
const struct v3dv_format *v3dv_get_format(VkFormat);
+void v3dv_get_internal_type_bpp_for_output_format(uint32_t format, uint32_t *type, uint32_t *bpp);
uint32_t v3d_utile_width(int cpp);
uint32_t v3d_utile_height(int cpp);
@@ -376,8 +394,16 @@
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_device_memory, VkDeviceMemory)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_image, VkImage)
+V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_image_view, VkImageView)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_shader_module, VkShaderModule)
+/* This is defined as a macro so that it works for both
+ * VkImageSubresourceRange and VkImageSubresourceLayers
+ */
+#define v3dv_layer_count(_image, _range) \
+ ((_range)->layerCount == VK_REMAINING_ARRAY_LAYERS ? \
+ (_image)->array_size - (_range)->baseArrayLayer : (_range)->layerCount)
+
static inline int
v3dv_ioctl(int fd, unsigned long request, void *arg)
{
diff --git a/src/broadcom/vulkan/vk_format_info.h b/src/broadcom/vulkan/vk_format_info.h
index ac4e174..0969c02 100644
--- a/src/broadcom/vulkan/vk_format_info.h
+++ b/src/broadcom/vulkan/vk_format_info.h
@@ -120,4 +120,10 @@
return util_format_get_blockheight(vk_format_to_pipe_format(format));
}
+static inline const struct util_format_description *
+vk_format_description(VkFormat format)
+{
+ return util_format_description(vk_format_to_pipe_format(format));
+}
+
#endif /* VK_FORMAT_INFO_H */