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