diff --git a/src/imagination/vulkan/pvr_formats.c b/src/imagination/vulkan/pvr_formats.c index 9ef8710100c..9364de7b6f0 100644 --- a/src/imagination/vulkan/pvr_formats.c +++ b/src/imagination/vulkan/pvr_formats.c @@ -47,6 +47,8 @@ [VK_FORMAT_##vk] = { \ .vk_format = VK_FORMAT_##vk, \ .tex_format = ROGUE_TEXSTATE_FORMAT_##tex_fmt, \ + .depth_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ + .stencil_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ .pbe_packmode = ROGUE_PBESTATE_PACKMODE_##pack_mode, \ .pbe_accum_format = PVR_PBE_ACCUM_FORMAT_##accum_format, \ .supported = true, \ @@ -56,14 +58,29 @@ [VK_FORMAT_##vk] = { \ .vk_format = VK_FORMAT_##vk, \ .tex_format = ROGUE_TEXSTATE_FORMAT_COMPRESSED_##tex_fmt, \ + .depth_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ + .stencil_tex_format = ROGUE_TEXSTATE_FORMAT_INVALID, \ .pbe_packmode = ROGUE_PBESTATE_PACKMODE_INVALID, \ .pbe_accum_format = PVR_PBE_ACCUM_FORMAT_INVALID, \ .supported = true, \ } +#define FORMAT_DEPTH_STENCIL(vk, combined_fmt, d_fmt, s_fmt) \ + [VK_FORMAT_##vk] = { \ + .vk_format = VK_FORMAT_##vk, \ + .tex_format = ROGUE_TEXSTATE_FORMAT_##combined_fmt, \ + .depth_tex_format = ROGUE_TEXSTATE_FORMAT_##d_fmt, \ + .stencil_tex_format = ROGUE_TEXSTATE_FORMAT_##s_fmt, \ + .pbe_packmode = ROGUE_PBESTATE_PACKMODE_INVALID, \ + .pbe_accum_format = PVR_PBE_ACCUM_FORMAT_INVALID, \ + .supported = true, \ + } + struct pvr_format { VkFormat vk_format; uint32_t tex_format; + uint32_t depth_tex_format; + uint32_t stencil_tex_format; uint32_t pbe_packmode; enum pvr_pbe_accum_format pbe_accum_format; bool supported; @@ -179,11 +196,11 @@ static const struct pvr_format pvr_format_table[] = { /* VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123. */ FORMAT(E5B9G9R9_UFLOAT_PACK32, SE9995, SE9995, INVALID), /* VK_FORMAT_D16_UNORM = 124. */ - FORMAT(D16_UNORM, U16, U16, F16), + FORMAT_DEPTH_STENCIL(D16_UNORM, U16, U16, INVALID), /* VK_FORMAT_D32_SFLOAT = 126. */ - FORMAT(D32_SFLOAT, F32, F32, F16), + FORMAT_DEPTH_STENCIL(D32_SFLOAT, F32, F32, INVALID), /* VK_FORMAT_D24_UNORM_S8_UINT = 129. */ - FORMAT(D24_UNORM_S8_UINT, ST8U24, ST8U24, F16), + FORMAT_DEPTH_STENCIL(D24_UNORM_S8_UINT, ST8U24, X8U24, U8X24), /* VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147. */ FORMAT_COMPRESSED(ETC2_R8G8B8_UNORM_BLOCK, ETC2_RGB), /* VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148. */ @@ -232,6 +249,22 @@ uint32_t pvr_get_tex_format(VkFormat vk_format) return ROGUE_TEXSTATE_FORMAT_INVALID; } +uint32_t pvr_get_tex_format_aspect(VkFormat vk_format, + VkImageAspectFlags aspect_mask) +{ + const struct pvr_format *pvr_format = pvr_get_format(vk_format); + if (pvr_format) { + if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) + return pvr_format->depth_tex_format; + else if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) + return pvr_format->stencil_tex_format; + + return pvr_format->tex_format; + } + + return PVRX(TEXSTATE_FORMAT_INVALID); +} + uint32_t pvr_get_pbe_packmode(VkFormat vk_format) { const struct pvr_format *pvr_format = pvr_get_format(vk_format); diff --git a/src/imagination/vulkan/pvr_formats.h b/src/imagination/vulkan/pvr_formats.h index ba6e490f196..f7d011bb3e1 100644 --- a/src/imagination/vulkan/pvr_formats.h +++ b/src/imagination/vulkan/pvr_formats.h @@ -59,6 +59,8 @@ enum pvr_pbe_accum_format { const uint8_t *pvr_get_format_swizzle(VkFormat vk_format); uint32_t pvr_get_tex_format(VkFormat vk_format); +uint32_t pvr_get_tex_format_aspect(VkFormat vk_format, + VkImageAspectFlags aspect_mask); uint32_t pvr_get_pbe_packmode(VkFormat vk_format); uint32_t pvr_get_pbe_accum_format(VkFormat vk_format); uint32_t pvr_get_pbe_accum_format_size_in_bytes(VkFormat vk_format); diff --git a/src/imagination/vulkan/pvr_image.c b/src/imagination/vulkan/pvr_image.c index 8f43682d0f0..19d5240b2ad 100644 --- a/src/imagination/vulkan/pvr_image.c +++ b/src/imagination/vulkan/pvr_image.c @@ -286,6 +286,7 @@ VkResult pvr_CreateImageView(VkDevice _device, info.base_level = iview->vk.base_mip_level; info.mip_levels = iview->vk.level_count; info.extent = image->vk.extent; + info.aspect_mask = image->vk.aspects; info.is_cube = (info.type == VK_IMAGE_VIEW_TYPE_CUBE || info.type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY); info.array_size = iview->vk.layer_count; @@ -299,10 +300,7 @@ VkResult pvr_CreateImageView(VkDevice _device, info.sample_count = image->vk.samples; info.addr = image->dev_addr; - /* TODO: if ERN_46863 is supported, Depth and stencil are sampled separately - * from images with combined depth+stencil. Add logic here to handle it. - */ - info.format = iview->vk.format; + info.format = pCreateInfo->format; vk_component_mapping_to_pipe_swizzle(iview->vk.swizzle, input_swizzle); format_swizzle = pvr_get_format_swizzle(info.format); diff --git a/src/imagination/vulkan/pvr_tex_state.c b/src/imagination/vulkan/pvr_tex_state.c index c2a2f7601d7..4ef771a3363 100644 --- a/src/imagination/vulkan/pvr_tex_state.c +++ b/src/imagination/vulkan/pvr_tex_state.c @@ -130,7 +130,13 @@ pvr_pack_tex_state(struct pvr_device *device, unreachable("Unknown memory layout"); } - word0.texformat = pvr_get_tex_format(info->format); + /* When sampling from a combined D/S image, the TPU will default to only + * the depth aspect. + * The driver must select the correct single aspect format when sampling + * to avoid this. + */ + word0.texformat = + pvr_get_tex_format_aspect(info->format, info->aspect_mask); word0.smpcnt = util_logbase2(info->sample_count); word0.swiz0 = pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_R, info->swizzle[0]); diff --git a/src/imagination/vulkan/pvr_tex_state.h b/src/imagination/vulkan/pvr_tex_state.h index 24e199b1014..6cd617ce877 100644 --- a/src/imagination/vulkan/pvr_tex_state.h +++ b/src/imagination/vulkan/pvr_tex_state.h @@ -52,6 +52,7 @@ struct pvr_texture_state_info { enum pvr_memlayout mem_layout; uint32_t flags; VkImageViewType type; + VkImageAspectFlags aspect_mask; bool is_cube; enum pvr_texture_state tex_state_type; VkExtent3D extent;