xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_tex_state.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 "pvr_csb.h"
29 #include "pvr_device_info.h"
30 #include "pvr_formats.h"
31 #include "pvr_private.h"
32 #include "pvr_tex_state.h"
33 #include "util/macros.h"
34 #include "util/u_math.h"
35 #include "vk_format.h"
36 #include "vk_log.h"
37 
pvr_get_hw_swizzle(VkComponentSwizzle comp,enum pipe_swizzle swz)38 static enum ROGUE_TEXSTATE_SWIZ pvr_get_hw_swizzle(VkComponentSwizzle comp,
39                                                    enum pipe_swizzle swz)
40 {
41    switch (swz) {
42    case PIPE_SWIZZLE_0:
43       return ROGUE_TEXSTATE_SWIZ_SRC_ZERO;
44    case PIPE_SWIZZLE_1:
45       return ROGUE_TEXSTATE_SWIZ_SRC_ONE;
46    case PIPE_SWIZZLE_X:
47       return ROGUE_TEXSTATE_SWIZ_SRCCHAN_0;
48    case PIPE_SWIZZLE_Y:
49       return ROGUE_TEXSTATE_SWIZ_SRCCHAN_1;
50    case PIPE_SWIZZLE_Z:
51       return ROGUE_TEXSTATE_SWIZ_SRCCHAN_2;
52    case PIPE_SWIZZLE_W:
53       return ROGUE_TEXSTATE_SWIZ_SRCCHAN_3;
54    case PIPE_SWIZZLE_NONE:
55       if (comp == VK_COMPONENT_SWIZZLE_A)
56          return ROGUE_TEXSTATE_SWIZ_SRC_ONE;
57       else
58          return ROGUE_TEXSTATE_SWIZ_SRC_ZERO;
59    default:
60       unreachable("Unknown enum pipe_swizzle");
61    };
62 }
63 
64 VkResult
pvr_pack_tex_state(struct pvr_device * device,const struct pvr_texture_state_info * info,uint64_t state[static const ROGUE_NUM_TEXSTATE_IMAGE_WORDS])65 pvr_pack_tex_state(struct pvr_device *device,
66                    const struct pvr_texture_state_info *info,
67                    uint64_t state[static const ROGUE_NUM_TEXSTATE_IMAGE_WORDS])
68 {
69    const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
70    enum pvr_memlayout mem_layout;
71    VkImageViewType iview_type;
72 
73    if (info->type == VK_IMAGE_VIEW_TYPE_1D &&
74        info->mem_layout == PVR_MEMLAYOUT_LINEAR) {
75       /* Change the memory layout to twiddled as there isn't a TEXSTATE_TEXTYPE
76        * for 1D linear and 1D twiddled is equivalent.
77        */
78       mem_layout = PVR_MEMLAYOUT_TWIDDLED;
79    } else {
80       mem_layout = info->mem_layout;
81    }
82 
83    if (info->is_cube && info->tex_state_type != PVR_TEXTURE_STATE_SAMPLE)
84       iview_type = VK_IMAGE_VIEW_TYPE_2D;
85    else
86       iview_type = info->type;
87 
88    pvr_csb_pack (&state[0], TEXSTATE_IMAGE_WORD0, word0) {
89       if (mem_layout == PVR_MEMLAYOUT_LINEAR) {
90          switch (iview_type) {
91          case VK_IMAGE_VIEW_TYPE_2D:
92          case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
93             word0.textype = PVRX(TEXSTATE_TEXTYPE_STRIDE);
94             break;
95 
96          default:
97             return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED);
98          }
99       } else if (mem_layout == PVR_MEMLAYOUT_TWIDDLED) {
100          switch (iview_type) {
101          case VK_IMAGE_VIEW_TYPE_1D:
102          case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
103             word0.textype = PVRX(TEXSTATE_TEXTYPE_1D);
104             break;
105 
106          case VK_IMAGE_VIEW_TYPE_2D:
107          case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
108             word0.textype = PVRX(TEXSTATE_TEXTYPE_2D);
109             break;
110 
111          case VK_IMAGE_VIEW_TYPE_CUBE:
112          case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
113             word0.textype = PVRX(TEXSTATE_TEXTYPE_CUBE);
114             break;
115 
116          default:
117             return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED);
118          }
119       } else if (mem_layout == PVR_MEMLAYOUT_3DTWIDDLED) {
120          switch (iview_type) {
121          case VK_IMAGE_VIEW_TYPE_3D:
122             word0.textype = PVRX(TEXSTATE_TEXTYPE_3D);
123             break;
124 
125          default:
126             return vk_error(device, VK_ERROR_FORMAT_NOT_SUPPORTED);
127          }
128       } else {
129          unreachable("Unknown memory layout");
130       }
131 
132       /* When sampling from a combined D/S image, the TPU will default to only
133        * the depth aspect.
134        * The driver must select the correct single aspect format when sampling
135        * to avoid this.
136        */
137       word0.texformat =
138          pvr_get_tex_format_aspect(info->format, info->aspect_mask);
139       word0.smpcnt = util_logbase2(info->sample_count);
140       word0.swiz0 =
141          pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_R, info->swizzle[0]);
142       word0.swiz1 =
143          pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_G, info->swizzle[1]);
144       word0.swiz2 =
145          pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_B, info->swizzle[2]);
146       word0.swiz3 =
147          pvr_get_hw_swizzle(VK_COMPONENT_SWIZZLE_A, info->swizzle[3]);
148 
149       /* Gamma */
150       if (vk_format_is_srgb(info->format)) {
151          /* Gamma for 2 Component Formats has to be handled differently. */
152          if (vk_format_get_nr_components(info->format) == 2) {
153             /* Enable Gamma only for Channel 0 if Channel 1 is an Alpha
154              * Channel.
155              */
156             if (vk_format_has_alpha(info->format)) {
157                word0.twocomp_gamma = PVRX(TEXSTATE_TWOCOMP_GAMMA_R);
158             } else {
159                /* Otherwise Enable Gamma for both the Channels. */
160                word0.twocomp_gamma = PVRX(TEXSTATE_TWOCOMP_GAMMA_RG);
161 
162                /* If Channel 0 happens to be the Alpha Channel, the
163                 * ALPHA_MSB bit would not be set thereby disabling Gamma
164                 * for Channel 0.
165                 */
166             }
167          } else {
168             word0.gamma = PVRX(TEXSTATE_GAMMA_ON);
169          }
170       }
171 
172       word0.width = info->extent.width - 1;
173       if (iview_type != VK_IMAGE_VIEW_TYPE_1D &&
174           iview_type != VK_IMAGE_VIEW_TYPE_1D_ARRAY)
175          word0.height = info->extent.height - 1;
176    }
177 
178    if (mem_layout == PVR_MEMLAYOUT_LINEAR) {
179       pvr_csb_pack (&state[1], TEXSTATE_STRIDE_IMAGE_WORD1, word1) {
180          assert(info->stride > 0U);
181          word1.stride = info->stride - 1U;
182          word1.num_mip_levels = info->mip_levels;
183          word1.mipmaps_present = info->mipmaps_present;
184 
185          word1.texaddr = PVR_DEV_ADDR_OFFSET(info->addr, info->offset);
186 
187          if (vk_format_is_alpha_on_msb(info->format))
188             word1.alpha_msb = true;
189 
190          if (!PVR_HAS_FEATURE(dev_info, tpu_extended_integer_lookup) &&
191              !PVR_HAS_FEATURE(dev_info, tpu_image_state_v2)) {
192             if (info->flags & PVR_TEXFLAGS_INDEX_LOOKUP ||
193                 info->flags & PVR_TEXFLAGS_BUFFER)
194                word1.index_lookup = true;
195          }
196 
197          if (info->flags & PVR_TEXFLAGS_BUFFER)
198             word1.mipmaps_present = false;
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    } else {
206       pvr_csb_pack (&state[1], TEXSTATE_IMAGE_WORD1, word1) {
207          word1.num_mip_levels = info->mip_levels;
208          word1.mipmaps_present = info->mipmaps_present;
209          word1.baselevel = info->base_level;
210 
211          if (iview_type == VK_IMAGE_VIEW_TYPE_3D) {
212             if (info->extent.depth > 0)
213                word1.depth = info->extent.depth - 1;
214          } else if (PVR_HAS_FEATURE(dev_info, tpu_array_textures)) {
215             uint32_t array_layers = info->array_size;
216 
217             if (iview_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
218                array_layers /= 6;
219 
220             if (array_layers > 0)
221                word1.depth = array_layers - 1;
222          }
223 
224          word1.texaddr = PVR_DEV_ADDR_OFFSET(info->addr, info->offset);
225 
226          if (!PVR_HAS_FEATURE(dev_info, tpu_extended_integer_lookup) &&
227              !PVR_HAS_FEATURE(dev_info, tpu_image_state_v2)) {
228             if (info->flags & PVR_TEXFLAGS_INDEX_LOOKUP ||
229                 info->flags & PVR_TEXFLAGS_BUFFER)
230                word1.index_lookup = true;
231          }
232 
233          if (info->flags & PVR_TEXFLAGS_BUFFER)
234             word1.mipmaps_present = false;
235 
236          if (info->flags & PVR_TEXFLAGS_BORDER)
237             word1.border = true;
238 
239          if (vk_format_is_alpha_on_msb(info->format))
240             word1.alpha_msb = true;
241 
242          if (PVR_HAS_FEATURE(dev_info, tpu_image_state_v2) &&
243              vk_format_is_compressed(info->format))
244             word1.tpu_image_state_v2_compression_mode =
245                PVRX(TEXSTATE_COMPRESSION_MODE_TPU);
246       }
247    }
248 
249    return VK_SUCCESS;
250 }
251