blob: 03bf26119b980c617d0f990cd042098402155ccb [file] [log] [blame]
Chia-I Wu4bc47012014-08-14 13:03:25 +08001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu4bc47012014-08-14 13:03:25 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
Chia-I Wu44e42362014-09-02 08:32:09 +080025 * Chia-I Wu <olv@lunarg.com>
Chia-I Wu4bc47012014-08-14 13:03:25 +080026 */
27
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080028#ifndef LAYOUT_H
29#define LAYOUT_H
Chia-I Wu4bc47012014-08-14 13:03:25 +080030
Chia-I Wud1eb90c2015-03-07 06:01:45 +080031#include "genhw/genhw.h"
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080032#include "intel.h"
Chia-I Wu4bc47012014-08-14 13:03:25 +080033
Chia-I Wu457d0a62014-08-18 13:02:26 +080034#define INTEL_LAYOUT_MAX_LEVELS 16
35
Chia-I Wucca7acf2014-08-27 10:37:43 +080036struct intel_dev;
37
Chia-I Wu457d0a62014-08-18 13:02:26 +080038enum intel_layout_walk_type {
39 /*
40 * Array layers of an LOD are packed together vertically. This maps to
41 * ARYSPC_LOD0 for non-mipmapped 2D textures, and is extended to support
42 * mipmapped stencil textures and HiZ on GEN6.
43 */
44 INTEL_LAYOUT_WALK_LOD,
45
46 /*
47 * LODs of an array layer are packed together. This maps to ARYSPC_FULL
48 * and is used for mipmapped 2D textures.
49 */
50 INTEL_LAYOUT_WALK_LAYER,
51
52 /*
53 * 3D slices of an LOD are packed together, horizontally with wrapping.
54 * Used for 3D textures.
55 */
56 INTEL_LAYOUT_WALK_3D,
57};
Chia-I Wu4bc47012014-08-14 13:03:25 +080058
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080059enum intel_layout_aux_type {
60 INTEL_LAYOUT_AUX_NONE,
61 INTEL_LAYOUT_AUX_HIZ,
62 INTEL_LAYOUT_AUX_MCS,
Chia-I Wu4bc47012014-08-14 13:03:25 +080063};
64
Chia-I Wu457d0a62014-08-18 13:02:26 +080065struct intel_layout_lod {
66 /* physical position */
67 unsigned x;
68 unsigned y;
69
70 /*
71 * Physical size of an LOD slice. There may be multiple slices when the
72 * walk type is not INTEL_LAYOUT_WALK_LAYER.
73 */
74 unsigned slice_width;
75 unsigned slice_height;
76};
77
Chia-I Wu4bc47012014-08-14 13:03:25 +080078/**
79 * Texture layout.
80 */
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080081struct intel_layout {
Chia-I Wu457d0a62014-08-18 13:02:26 +080082 enum intel_layout_aux_type aux;
83
84 /* physical width0, height0, and format */
85 unsigned width0;
86 unsigned height0;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060087 VkFormat format;
Chia-I Wu4bc47012014-08-14 13:03:25 +080088 bool separate_stencil;
89
90 /*
91 * width, height, and size of pixel blocks, for conversion between 2D
92 * coordinates and memory offsets
93 */
94 unsigned block_width;
95 unsigned block_height;
96 unsigned block_size;
97
Chia-I Wu457d0a62014-08-18 13:02:26 +080098 enum intel_layout_walk_type walk;
Chia-I Wu4bc47012014-08-14 13:03:25 +080099 bool interleaved_samples;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800100
101 /* bitmask of valid tiling modes */
102 unsigned valid_tilings;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800103 enum gen_surface_tiling tiling;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800104
105 /* mipmap alignments */
106 unsigned align_i;
107 unsigned align_j;
108
Chia-I Wu457d0a62014-08-18 13:02:26 +0800109 struct intel_layout_lod lods[INTEL_LAYOUT_MAX_LEVELS];
Chia-I Wu4bc47012014-08-14 13:03:25 +0800110
Chia-I Wu457d0a62014-08-18 13:02:26 +0800111 /* physical height of layers for INTEL_LAYOUT_WALK_LAYER */
Chia-I Wu4bc47012014-08-14 13:03:25 +0800112 unsigned layer_height;
113
114 /* distance in bytes between two pixel block rows */
115 unsigned bo_stride;
116 /* number of pixel block rows */
117 unsigned bo_height;
118
Chia-I Wu457d0a62014-08-18 13:02:26 +0800119 /* bitmask of levels that can use aux */
120 unsigned aux_enables;
121 unsigned aux_offsets[INTEL_LAYOUT_MAX_LEVELS];
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800122 unsigned aux_layer_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800123 unsigned aux_stride;
124 unsigned aux_height;
125};
126
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800127void intel_layout_init(struct intel_layout *layout,
Chia-I Wuc94f3e52014-10-07 14:45:05 +0800128 struct intel_dev *dev,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600129 const VkImageCreateInfo *info,
Chia-I Wu794d12a2014-09-15 14:55:25 +0800130 bool scanout);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800131
Chia-I Wu4bc47012014-08-14 13:03:25 +0800132/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800133 * Convert from pixel position to 2D memory offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800134 */
135static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800136intel_layout_pos_to_mem(const struct intel_layout *layout,
Chia-I Wu457d0a62014-08-18 13:02:26 +0800137 unsigned pos_x, unsigned pos_y,
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800138 unsigned *mem_x, unsigned *mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800139{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800140 assert(pos_x % layout->block_width == 0);
141 assert(pos_y % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800142
Chia-I Wu457d0a62014-08-18 13:02:26 +0800143 *mem_x = pos_x / layout->block_width * layout->block_size;
144 *mem_y = pos_y / layout->block_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800145}
146
147/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800148 * Convert from 2D memory offset to linear offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800149 */
150static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800151intel_layout_mem_to_linear(const struct intel_layout *layout,
152 unsigned mem_x, unsigned mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800153{
154 return mem_y * layout->bo_stride + mem_x;
155}
156
157/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800158 * Convert from 2D memory offset to raw offset.
159 */
160static inline unsigned
161intel_layout_mem_to_raw(const struct intel_layout *layout,
162 unsigned mem_x, unsigned mem_y)
163{
Chia-I Wu08cd6e92015-02-11 13:44:50 -0700164 unsigned tile_w U_ASSERT_ONLY;
165 unsigned tile_h;
Chia-I Wu457d0a62014-08-18 13:02:26 +0800166
167 switch (layout->tiling) {
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800168 case GEN6_TILING_NONE:
169 tile_w = 1;
170 tile_h = 1;
Chia-I Wu457d0a62014-08-18 13:02:26 +0800171 break;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800172 case GEN6_TILING_X:
Chia-I Wu457d0a62014-08-18 13:02:26 +0800173 tile_w = 512;
174 tile_h = 8;
175 break;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800176 case GEN6_TILING_Y:
Chia-I Wu457d0a62014-08-18 13:02:26 +0800177 tile_w = 128;
178 tile_h = 32;
179 break;
Chia-I Wud1eb90c2015-03-07 06:01:45 +0800180 case GEN8_TILING_W:
181 tile_w = 64;
182 tile_h = 64;
183 break;
Chia-I Wu457d0a62014-08-18 13:02:26 +0800184 default:
185 assert(!"unknown tiling");
186 tile_w = 1;
187 tile_h = 1;
188 break;
189 }
190
191 assert(mem_x % tile_w == 0);
192 assert(mem_y % tile_h == 0);
193
194 return mem_y * layout->bo_stride + mem_x * tile_h;
195}
196
197/**
Chia-I Wu4bc47012014-08-14 13:03:25 +0800198 * Return the stride, in bytes, between slices within a level.
199 */
200static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800201intel_layout_get_slice_stride(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800202{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800203 unsigned h;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800204
Chia-I Wu457d0a62014-08-18 13:02:26 +0800205 switch (layout->walk) {
206 case INTEL_LAYOUT_WALK_LOD:
207 h = layout->lods[level].slice_height;
208 break;
209 case INTEL_LAYOUT_WALK_LAYER:
210 h = layout->layer_height;
211 break;
212 case INTEL_LAYOUT_WALK_3D:
213 if (level == 0) {
214 h = layout->lods[0].slice_height;
215 break;
216 }
217 /* fall through */
218 default:
219 assert(!"no single stride to walk across slices");
220 h = 0;
221 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800222 }
223
Chia-I Wu457d0a62014-08-18 13:02:26 +0800224 assert(h % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800225
Chia-I Wu457d0a62014-08-18 13:02:26 +0800226 return (h / layout->block_height) * layout->bo_stride;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800227}
228
229/**
230 * Return the physical size, in bytes, of a slice in a level.
231 */
232static inline unsigned
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800233intel_layout_get_slice_size(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800234{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800235 const unsigned w = layout->lods[level].slice_width;
236 const unsigned h = layout->lods[level].slice_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800237
238 assert(w % layout->block_width == 0);
239 assert(h % layout->block_height == 0);
240
241 return (w / layout->block_width * layout->block_size) *
242 (h / layout->block_height);
243}
244
245/**
246 * Return the pixel position of a slice.
247 */
248static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800249intel_layout_get_slice_pos(const struct intel_layout *layout,
250 unsigned level, unsigned slice,
251 unsigned *x, unsigned *y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800252{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800253 switch (layout->walk) {
254 case INTEL_LAYOUT_WALK_LOD:
255 *x = layout->lods[level].x;
256 *y = layout->lods[level].y + layout->lods[level].slice_height * slice;
257 break;
258 case INTEL_LAYOUT_WALK_LAYER:
259 *x = layout->lods[level].x;
260 *y = layout->lods[level].y + layout->layer_height * slice;
261 break;
262 case INTEL_LAYOUT_WALK_3D:
263 {
264 /* slices are packed horizontally with wrapping */
265 const unsigned sx = slice & ((1 << level) - 1);
266 const unsigned sy = slice >> level;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800267
Chia-I Wu457d0a62014-08-18 13:02:26 +0800268 *x = layout->lods[level].x + layout->lods[level].slice_width * sx;
269 *y = layout->lods[level].y + layout->lods[level].slice_height * sy;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800270
Chia-I Wu457d0a62014-08-18 13:02:26 +0800271 /* should not overlap with the next level */
272 if (level + 1 < ARRAY_SIZE(layout->lods) &&
273 layout->lods[level + 1].y) {
274 assert(*y + layout->lods[level].slice_height <=
275 layout->lods[level + 1].y);
276 }
277 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800278 }
Chia-I Wu457d0a62014-08-18 13:02:26 +0800279 default:
280 assert(!"unknown layout walk type");
Chia-I Wu9a056dd2015-02-11 13:19:39 -0700281 *x = 0;
282 *y = 0;
Chia-I Wu457d0a62014-08-18 13:02:26 +0800283 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800284 }
285
286 /* should not exceed the bo size */
Chia-I Wu457d0a62014-08-18 13:02:26 +0800287 assert(*y + layout->lods[level].slice_height <=
Chia-I Wu4bc47012014-08-14 13:03:25 +0800288 layout->bo_height * layout->block_height);
289}
290
Chia-I Wu63a53972014-12-04 12:51:54 +0800291unsigned
292intel_layout_get_slice_tile_offset(const struct intel_layout *layout,
293 unsigned level, unsigned slice,
294 unsigned *x_offset, unsigned *y_offset);
295
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800296#endif /* LAYOUT_H */