From fdf85f10a17f5889a8f42c9ff6ee4021a913ba95 Mon Sep 17 00:00:00 2001 From: Frank Binns Date: Tue, 23 Aug 2022 11:55:33 +0100 Subject: [PATCH] pvr: cube map tex state packing fixes A VK_ERROR_FORMAT_NOT_SUPPORTED error was being returned when setting up the image view tex state for images with the VK_IMAGE_USAGE_STORAGE_BIT and/or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT bit(s) set due to missing handling in pvr_pack_tex_state(). Resolve this by handling these cases, while taking the opportunity to simplify how the tex type is determined when packing TEXSTATE_IMAGE_WORD0. It was also found that the depth field in TEXSTATE_IMAGE_WORD1 was being set up incorrectly, as it was relying on the image depth being 0 for 1D and 2D images, but the image depth will always be 1 in these cases. Partial fix for dEQP-VK.image.qualifiers.volatile.cube.r32f. This now goes from failing to seg faulting when VK_FORMAT_R32_SFLOAT is added to the format table, as the test is now getting further. Signed-off-by: Frank Binns Reviewed-by: Rajnesh Kanwal Part-of: --- src/imagination/vulkan/pvr_device.c | 1 - src/imagination/vulkan/pvr_formats.c | 6 ++ src/imagination/vulkan/pvr_image.c | 11 +++- src/imagination/vulkan/pvr_tex_state.c | 88 ++++++++++++++++++-------- 4 files changed, 78 insertions(+), 28 deletions(-) diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 05d69f56338..283fe10831d 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -1388,7 +1388,6 @@ static VkResult pvr_device_init_compute_idfwdf_state(struct pvr_device *device) .format = VK_FORMAT_R32G32B32A32_SFLOAT, .mem_layout = PVR_MEMLAYOUT_LINEAR, .flags = PVR_TEXFLAGS_INDEX_LOOKUP, - /* TODO: Is this correct? Is it 2D, 3D, or 2D_ARRAY? */ .type = VK_IMAGE_VIEW_TYPE_2D, .extent = { .width = 4, .height = 2, .depth = 0 }, .mip_levels = 1, diff --git a/src/imagination/vulkan/pvr_formats.c b/src/imagination/vulkan/pvr_formats.c index c84985e508d..9de590b51e6 100644 --- a/src/imagination/vulkan/pvr_formats.c +++ b/src/imagination/vulkan/pvr_formats.c @@ -163,6 +163,12 @@ pvr_get_image_format_properties(struct pvr_physical_device *pdevice, return VK_SUCCESS; } +/* FIXME: Should this be returning VK_ERROR_FORMAT_NOT_SUPPORTED when tiling is + * linear and the image type is 3D or flags contains + * VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT? This should avoid well behaved apps + * attempting to create invalid image views, as pvr_pack_tex_state() will return + * VK_ERROR_FORMAT_NOT_SUPPORTED in these cases. + */ VkResult pvr_GetPhysicalDeviceImageFormatProperties2( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, diff --git a/src/imagination/vulkan/pvr_image.c b/src/imagination/vulkan/pvr_image.c index d6f9239b4db..8616305b033 100644 --- a/src/imagination/vulkan/pvr_image.c +++ b/src/imagination/vulkan/pvr_image.c @@ -309,10 +309,11 @@ VkResult pvr_CreateImageView(VkDevice _device, goto err_vk_image_view_destroy; /* Create an additional texture state for cube type if storage - * usage flat is set. + * usage flag is set. */ if (info.is_cube && image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) { info.tex_state_type = PVR_TEXTURE_STATE_STORAGE; + result = pvr_pack_tex_state(device, &info, iview->texture_state[info.tex_state_type]); @@ -335,6 +336,13 @@ VkResult pvr_CreateImageView(VkDevice _device, info.base_level = 0; info.tex_state_type = PVR_TEXTURE_STATE_ATTACHMENT; + if (iview->vk.image->image_type == VK_IMAGE_TYPE_3D && + iview->vk.view_type == VK_IMAGE_VIEW_TYPE_2D) { + info.type = VK_IMAGE_VIEW_TYPE_3D; + } else { + info.type = iview->vk.view_type; + } + result = pvr_pack_tex_state(device, &info, iview->texture_state[info.tex_state_type]); @@ -408,6 +416,7 @@ VkResult pvr_CreateBufferView(VkDevice _device, info.addr = PVR_DEV_ADDR_OFFSET(buffer->dev_addr, pCreateInfo->offset); info.mem_layout = PVR_MEMLAYOUT_LINEAR; info.is_cube = false; + info.type = VK_IMAGE_VIEW_TYPE_2D; info.tex_state_type = PVR_TEXTURE_STATE_SAMPLE; info.format = bview->format; info.flags = PVR_TEXFLAGS_INDEX_LOOKUP; diff --git a/src/imagination/vulkan/pvr_tex_state.c b/src/imagination/vulkan/pvr_tex_state.c index aeb981ccea5..1d99200f70f 100644 --- a/src/imagination/vulkan/pvr_tex_state.c +++ b/src/imagination/vulkan/pvr_tex_state.c @@ -68,29 +68,66 @@ pvr_pack_tex_state(struct pvr_device *device, uint64_t state[static const ROGUE_NUM_TEXSTATE_IMAGE_WORDS]) { const struct pvr_device_info *dev_info = &device->pdevice->dev_info; - uint32_t texture_type; + enum pvr_memlayout mem_layout; + VkImageViewType iview_type; + + if (info->type == VK_IMAGE_VIEW_TYPE_1D && + info->mem_layout == PVR_MEMLAYOUT_LINEAR) { + /* Change the memory layout to twiddled as there isn't a TEXSTATE_TEXTYPE + * for 1D linear and 1D twiddled is equivalent. + */ + mem_layout = PVR_MEMLAYOUT_TWIDDLED; + } else { + mem_layout = info->mem_layout; + } + + if (info->is_cube && info->tex_state_type != PVR_TEXTURE_STATE_SAMPLE) + iview_type = VK_IMAGE_VIEW_TYPE_2D; + else + iview_type = info->type; pvr_csb_pack (&state[0], TEXSTATE_IMAGE_WORD0, word0) { - /* Determine texture type */ - if (info->is_cube && info->tex_state_type == PVR_TEXTURE_STATE_SAMPLE) { - word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_CUBE); - } else if (info->mem_layout == PVR_MEMLAYOUT_TWIDDLED || - info->mem_layout == PVR_MEMLAYOUT_3DTWIDDLED) { - if (info->type == VK_IMAGE_VIEW_TYPE_3D) { - word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_3D); - } else if (info->type == VK_IMAGE_VIEW_TYPE_1D || - info->type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) { - word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_1D); - } else if (info->type == VK_IMAGE_VIEW_TYPE_2D || - info->type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) { - word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_2D); - } else { + if (mem_layout == PVR_MEMLAYOUT_LINEAR) { + switch (iview_type) { + case VK_IMAGE_VIEW_TYPE_2D: + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + word0.textype = PVRX(TEXSTATE_TEXTYPE_STRIDE); + break; + + default: + return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED); + } + } else if (mem_layout == PVR_MEMLAYOUT_TWIDDLED) { + switch (iview_type) { + case VK_IMAGE_VIEW_TYPE_1D: + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: + word0.textype = PVRX(TEXSTATE_TEXTYPE_1D); + break; + + case VK_IMAGE_VIEW_TYPE_2D: + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + word0.textype = PVRX(TEXSTATE_TEXTYPE_2D); + break; + + case VK_IMAGE_VIEW_TYPE_CUBE: + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: + word0.textype = PVRX(TEXSTATE_TEXTYPE_CUBE); + break; + + default: + return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED); + } + } else if (mem_layout == PVR_MEMLAYOUT_3DTWIDDLED) { + switch (iview_type) { + case VK_IMAGE_VIEW_TYPE_3D: + word0.textype = PVRX(TEXSTATE_TEXTYPE_3D); + break; + + default: return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED); } - } else if (info->mem_layout == PVR_MEMLAYOUT_LINEAR) { - word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_STRIDE); } else { - return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED); + unreachable("Unknown memory layout"); } word0.texformat = pvr_get_tex_format(info->format); @@ -128,13 +165,12 @@ pvr_pack_tex_state(struct pvr_device *device, } word0.width = info->extent.width - 1; - if (info->type != VK_IMAGE_VIEW_TYPE_1D && - info->type != VK_IMAGE_VIEW_TYPE_1D_ARRAY) + if (iview_type != VK_IMAGE_VIEW_TYPE_1D && + iview_type != VK_IMAGE_VIEW_TYPE_1D_ARRAY) word0.height = info->extent.height - 1; } - /* Texture type specific stuff (word 1) */ - if (texture_type == PVRX(TEXSTATE_TEXTYPE_STRIDE)) { + if (mem_layout == PVR_MEMLAYOUT_LINEAR) { pvr_csb_pack (&state[1], TEXSTATE_STRIDE_IMAGE_WORD1, word1) { assert(info->stride > 0U); word1.stride = info->stride - 1U; @@ -167,13 +203,13 @@ pvr_pack_tex_state(struct pvr_device *device, word1.mipmaps_present = info->mipmaps_present; word1.baselevel = info->base_level; - if (info->extent.depth > 0) { - word1.depth = info->extent.depth - 1; + if (iview_type == VK_IMAGE_VIEW_TYPE_3D) { + if (info->extent.depth > 0) + word1.depth = info->extent.depth - 1; } else if (PVR_HAS_FEATURE(dev_info, tpu_array_textures)) { uint32_t array_layers = info->array_size; - if (info->type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && - info->tex_state_type == PVR_TEXTURE_STATE_SAMPLE) + if (iview_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) array_layers /= 6; word1.depth = array_layers - 1;