diff --git a/src/broadcom/vulkan/v3dv_formats.c b/src/broadcom/vulkan/v3dv_formats.c index 5f6a20a1096..f78b1d28523 100644 --- a/src/broadcom/vulkan/v3dv_formats.c +++ b/src/broadcom/vulkan/v3dv_formats.c @@ -71,6 +71,136 @@ v3dv_get_format(VkFormat format) 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 14b8b12e38b..a4a2fb864a6 100644 --- a/src/broadcom/vulkan/v3dv_image.c +++ b/src/broadcom/vulkan/v3dv_image.c @@ -244,6 +244,17 @@ v3d_setup_slices(struct v3dv_image *image) } } +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 @@ v3dv_CreateImage(VkDevice _device, 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 a37d0fc7d6c..b4a44949355 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -278,6 +278,23 @@ struct v3dv_image { 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(const char *format, ...) v3dv_printflike(1, 2); 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_HANDLE_CASTS(v3dv_queue, VkQueue) 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 ac4e1744b4a..0969c025d54 100644 --- a/src/broadcom/vulkan/vk_format_info.h +++ b/src/broadcom/vulkan/vk_format_info.h @@ -120,4 +120,10 @@ vk_format_get_blockheight(VkFormat format) 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 */