1/* 2 * Copyright © 2022 Imagination Technologies Ltd. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include <stdint.h> 25#include <vulkan/vulkan.h> 26 27#include "hwdef/rogue_hw_defs.h" 28#include "pipe/p_defines.h" 29#include "pvr_csb.h" 30#include "pvr_device_info.h" 31#include "pvr_formats.h" 32#include "pvr_private.h" 33#include "pvr_tex_state.h" 34#include "util/macros.h" 35#include "util/u_math.h" 36#include "vk_format.h" 37#include "vk_log.h" 38 39static enum ROGUE_TEXSTATE_SWIZ pvr_get_hw_swizzle(VkComponentSwizzle comp, 40 enum pipe_swizzle swz) 41{ 42 switch (swz) { 43 case PIPE_SWIZZLE_0: 44 return ROGUE_TEXSTATE_SWIZ_SRC_ZERO; 45 case PIPE_SWIZZLE_1: 46 return ROGUE_TEXSTATE_SWIZ_SRC_ONE; 47 case PIPE_SWIZZLE_X: 48 return ROGUE_TEXSTATE_SWIZ_SRCCHAN_0; 49 case PIPE_SWIZZLE_Y: 50 return ROGUE_TEXSTATE_SWIZ_SRCCHAN_1; 51 case PIPE_SWIZZLE_Z: 52 return ROGUE_TEXSTATE_SWIZ_SRCCHAN_2; 53 case PIPE_SWIZZLE_W: 54 return ROGUE_TEXSTATE_SWIZ_SRCCHAN_3; 55 case PIPE_SWIZZLE_NONE: 56 if (comp == VK_COMPONENT_SWIZZLE_A) 57 return ROGUE_TEXSTATE_SWIZ_SRC_ONE; 58 else 59 return ROGUE_TEXSTATE_SWIZ_SRC_ZERO; 60 default: 61 unreachable("Unknown enum pipe_swizzle"); 62 }; 63} 64 65VkResult 66pvr_pack_tex_state(struct pvr_device *device, 67 struct pvr_texture_state_info *info, 68 uint64_t state[static const ROGUE_NUM_TEXSTATE_IMAGE_WORDS]) 69{ 70 const struct pvr_device_info *dev_info = &device->pdevice->dev_info; 71 uint32_t texture_type; 72 73 pvr_csb_pack (&state[0], TEXSTATE_IMAGE_WORD0, word0) { 74 /* Determine texture type */ 75 if (info->is_cube && info->tex_state_type == PVR_TEXTURE_STATE_SAMPLE) { 76 word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_CUBE); 77 } else if (info->mem_layout == PVR_MEMLAYOUT_TWIDDLED || 78 info->mem_layout == PVR_MEMLAYOUT_3DTWIDDLED) { 79 if (info->type == VK_IMAGE_VIEW_TYPE_3D) { 80 word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_3D); 81 } else if (info->type == VK_IMAGE_VIEW_TYPE_1D || 82 info->type == VK_IMAGE_VIEW_TYPE_1D_ARRAY) { 83 word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_1D); 84 } else if (info->type == VK_IMAGE_VIEW_TYPE_2D || 85 info->type == VK_IMAGE_VIEW_TYPE_2D_ARRAY) { 86 word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_2D); 87 } else { 88 return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED); 89 } 90 } else if (info->mem_layout == PVR_MEMLAYOUT_LINEAR) { 91 word0.textype = texture_type = PVRX(TEXSTATE_TEXTYPE_STRIDE); 92 } else { 93 return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED); 94 } 95 96 word0.texformat = pvr_get_tex_format(info->format); 97 word0.smpcnt = util_logbase2(info->sample_count); 98 word0.swiz0 = 99 pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_R, info->swizzle[0]); 100 word0.swiz1 = 101 pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_G, info->swizzle[1]); 102 word0.swiz2 = 103 pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_B, info->swizzle[2]); 104 word0.swiz3 = 105 pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_A, info->swizzle[3]); 106 107 /* Gamma */ 108 if (vk_format_is_srgb(info->format)) { 109 /* Gamma for 2 Component Formats has to be handled differently. */ 110 if (vk_format_get_nr_components(info->format) == 2) { 111 /* Enable Gamma only for Channel 0 if Channel 1 is an Alpha 112 * Channel. 113 */ 114 if (vk_format_has_alpha(info->format)) { 115 word0.twocomp_gamma = PVRX(TEXSTATE_TWOCOMP_GAMMA_R); 116 } else { 117 /* Otherwise Enable Gamma for both the Channels. */ 118 word0.twocomp_gamma = PVRX(TEXSTATE_TWOCOMP_GAMMA_RG); 119 120 /* If Channel 0 happens to be the Alpha Channel, the 121 * ALPHA_MSB bit would not be set thereby disabling Gamma 122 * for Channel 0. 123 */ 124 } 125 } else { 126 word0.gamma = PVRX(TEXSTATE_GAMMA_ON); 127 } 128 } 129 130 word0.width = info->extent.width - 1; 131 if (info->type != VK_IMAGE_VIEW_TYPE_1D && 132 info->type != VK_IMAGE_VIEW_TYPE_1D_ARRAY) 133 word0.height = info->extent.height - 1; 134 } 135 136 /* Texture type specific stuff (word 1) */ 137 if (texture_type == PVRX(TEXSTATE_TEXTYPE_STRIDE)) { 138 pvr_csb_pack (&state[1], TEXSTATE_STRIDE_IMAGE_WORD1, word1) { 139 assert(info->stride > 0U); 140 word1.stride = info->stride - 1U; 141 word1.num_mip_levels = info->mip_levels; 142 word1.mipmaps_present = info->mipmaps_present; 143 144 word1.texaddr = PVR_DEV_ADDR_OFFSET(info->addr, info->offset); 145 146 if (vk_format_is_alpha_on_msb(info->format)) 147 word1.alpha_msb = true; 148 149 if (!PVR_HAS_FEATURE(dev_info, tpu_extended_integer_lookup) && 150 !PVR_HAS_FEATURE(dev_info, tpu_image_state_v2)) { 151 if (info->flags & PVR_TEXFLAGS_INDEX_LOOKUP || 152 info->flags & PVR_TEXFLAGS_BUFFER) 153 word1.index_lookup = true; 154 } 155 156 if (info->flags & PVR_TEXFLAGS_BUFFER) 157 word1.mipmaps_present = false; 158 159 if (PVR_HAS_FEATURE(dev_info, tpu_image_state_v2) && 160 vk_format_is_compressed(info->format)) 161 word1.tpu_image_state_v2_compression_mode = 162 PVRX(TEXSTATE_COMPRESSION_MODE_TPU); 163 } 164 } else { 165 pvr_csb_pack (&state[1], TEXSTATE_IMAGE_WORD1, word1) { 166 word1.num_mip_levels = info->mip_levels; 167 word1.mipmaps_present = info->mipmaps_present; 168 word1.baselevel = info->base_level; 169 170 if (info->extent.depth > 0) { 171 word1.depth = info->extent.depth - 1; 172 } else if (PVR_HAS_FEATURE(dev_info, tpu_array_textures)) { 173 uint32_t array_layers = info->array_size; 174 175 if (info->type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && 176 info->tex_state_type == PVR_TEXTURE_STATE_SAMPLE) 177 array_layers /= 6; 178 179 word1.depth = array_layers - 1; 180 } 181 182 word1.texaddr = PVR_DEV_ADDR_OFFSET(info->addr, info->offset); 183 184 if (!PVR_HAS_FEATURE(dev_info, tpu_extended_integer_lookup) && 185 !PVR_HAS_FEATURE(dev_info, tpu_image_state_v2)) { 186 if (info->flags & PVR_TEXFLAGS_INDEX_LOOKUP || 187 info->flags & PVR_TEXFLAGS_BUFFER) 188 word1.index_lookup = true; 189 } 190 191 if (info->flags & PVR_TEXFLAGS_BUFFER) 192 word1.mipmaps_present = false; 193 194 if (info->flags & PVR_TEXFLAGS_BORDER) 195 word1.border = true; 196 197 if (vk_format_is_alpha_on_msb(info->format)) 198 word1.alpha_msb = true; 199 200 if (PVR_HAS_FEATURE(dev_info, tpu_image_state_v2) && 201 vk_format_is_compressed(info->format)) 202 word1.tpu_image_state_v2_compression_mode = 203 PVRX(TEXSTATE_COMPRESSION_MODE_TPU); 204 } 205 } 206 207 return VK_SUCCESS; 208} 209