Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. |
||
3 | * Copyright © 2006 Intel Corporation |
||
4 | * |
||
5 | * Permission is hereby granted, free of charge, to any person obtaining |
||
6 | * a copy of this software and associated documentation files (the |
||
7 | * "Software"), to deal in the Software without restriction, including |
||
8 | * without limitation the rights to use, copy, modify, merge, publish, |
||
9 | * distribute, sublicense, and/or sell copies of the Software, and to |
||
10 | * permit persons to whom the Software is furnished to do so, subject to |
||
11 | * the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice (including the |
||
14 | * next paragraph) shall be included in all copies or substantial |
||
15 | * portions of the Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||
20 | * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
||
21 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||
22 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||
23 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
24 | */ |
||
25 | |||
26 | /** |
||
27 | * \file brw_tex_layout.cpp |
||
28 | * |
||
29 | * Code to lay out images in a mipmap tree. |
||
30 | * |
||
31 | * \author Keith Whitwell |
||
32 | * \author Michel Dänzer |
||
33 | */ |
||
34 | |||
35 | #include "intel_mipmap_tree.h" |
||
36 | #include "brw_context.h" |
||
37 | #include "main/macros.h" |
||
38 | |||
39 | #define FILE_DEBUG_FLAG DEBUG_MIPTREE |
||
40 | |||
41 | static unsigned int |
||
42 | intel_horizontal_texture_alignment_unit(struct brw_context *brw, |
||
43 | gl_format format) |
||
44 | { |
||
45 | /** |
||
46 | * From the "Alignment Unit Size" section of various specs, namely: |
||
47 | * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 |
||
48 | * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. |
||
49 | * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 |
||
50 | * - BSpec (for Ivybridge and slight variations in separate stencil) |
||
51 | * |
||
52 | * +----------------------------------------------------------------------+ |
||
53 | * | | alignment unit width ("i") | |
||
54 | * | Surface Property |-----------------------------| |
||
55 | * | | 915 | 965 | ILK | SNB | IVB | |
||
56 | * +----------------------------------------------------------------------+ |
||
57 | * | YUV 4:2:2 format | 8 | 4 | 4 | 4 | 4 | |
||
58 | * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | |
||
59 | * | FXT1 compressed format | 8 | 8 | 8 | 8 | 8 | |
||
60 | * | Depth Buffer (16-bit) | 4 | 4 | 4 | 4 | 8 | |
||
61 | * | Depth Buffer (other) | 4 | 4 | 4 | 4 | 4 | |
||
62 | * | Separate Stencil Buffer | N/A | N/A | 8 | 8 | 8 | |
||
63 | * | All Others | 4 | 4 | 4 | 4 | 4 | |
||
64 | * +----------------------------------------------------------------------+ |
||
65 | * |
||
66 | * On IVB+, non-special cases can be overridden by setting the SURFACE_STATE |
||
67 | * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8. |
||
68 | */ |
||
69 | if (_mesa_is_format_compressed(format)) { |
||
70 | /* The hardware alignment requirements for compressed textures |
||
71 | * happen to match the block boundaries. |
||
72 | */ |
||
73 | unsigned int i, j; |
||
74 | _mesa_get_format_block_size(format, &i, &j); |
||
75 | return i; |
||
76 | } |
||
77 | |||
78 | if (format == MESA_FORMAT_S8) |
||
79 | return 8; |
||
80 | |||
81 | /* The depth alignment requirements in the table above are for rendering to |
||
82 | * depth miplevels using the LOD control fields. We don't use LOD control |
||
83 | * fields, and instead use page offsets plus intra-tile x/y offsets, which |
||
84 | * require that the low 3 bits are zero. To reduce the number of x/y |
||
85 | * offset workaround blits we do, align the X to 8, which depth texturing |
||
86 | * can handle (sadly, it can't handle 8 in the Y direction). |
||
87 | */ |
||
88 | if (brw->gen >= 7 && |
||
89 | _mesa_get_format_base_format(format) == GL_DEPTH_COMPONENT) |
||
90 | return 8; |
||
91 | |||
92 | return 4; |
||
93 | } |
||
94 | |||
95 | static unsigned int |
||
96 | intel_vertical_texture_alignment_unit(struct brw_context *brw, |
||
4401 | Serge | 97 | gl_format format, bool multisampled) |
4358 | Serge | 98 | { |
99 | /** |
||
100 | * From the "Alignment Unit Size" section of various specs, namely: |
||
101 | * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 |
||
102 | * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. |
||
103 | * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 |
||
104 | * - BSpec (for Ivybridge and slight variations in separate stencil) |
||
105 | * |
||
106 | * +----------------------------------------------------------------------+ |
||
107 | * | | alignment unit height ("j") | |
||
108 | * | Surface Property |-----------------------------| |
||
109 | * | | 915 | 965 | ILK | SNB | IVB | |
||
110 | * +----------------------------------------------------------------------+ |
||
111 | * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | |
||
112 | * | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 | |
||
113 | * | Depth Buffer | 2 | 2 | 2 | 4 | 4 | |
||
114 | * | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 | |
||
115 | * | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 | |
||
116 | * | All Others | 2 | 2 | 2 | 2 | 2 | |
||
117 | * +----------------------------------------------------------------------+ |
||
118 | * |
||
119 | * On SNB+, non-special cases can be overridden by setting the SURFACE_STATE |
||
120 | * "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4. |
||
121 | */ |
||
122 | if (_mesa_is_format_compressed(format)) |
||
123 | return 4; |
||
124 | |||
125 | if (format == MESA_FORMAT_S8) |
||
126 | return brw->gen >= 7 ? 8 : 4; |
||
127 | |||
4401 | Serge | 128 | if (multisampled) |
129 | return 4; |
||
130 | |||
4358 | Serge | 131 | GLenum base_format = _mesa_get_format_base_format(format); |
132 | |||
133 | if (brw->gen >= 6 && |
||
134 | (base_format == GL_DEPTH_COMPONENT || |
||
135 | base_format == GL_DEPTH_STENCIL)) { |
||
136 | return 4; |
||
137 | } |
||
138 | |||
139 | return 2; |
||
140 | } |
||
141 | |||
142 | static void |
||
143 | brw_miptree_layout_2d(struct intel_mipmap_tree *mt) |
||
144 | { |
||
145 | unsigned x = 0; |
||
146 | unsigned y = 0; |
||
147 | unsigned width = mt->physical_width0; |
||
148 | unsigned height = mt->physical_height0; |
||
149 | unsigned depth = mt->physical_depth0; /* number of array layers. */ |
||
150 | |||
151 | mt->total_width = mt->physical_width0; |
||
152 | |||
153 | if (mt->compressed) { |
||
154 | mt->total_width = ALIGN(mt->physical_width0, mt->align_w); |
||
155 | } |
||
156 | |||
157 | /* May need to adjust width to accomodate the placement of |
||
158 | * the 2nd mipmap. This occurs when the alignment |
||
159 | * constraints of mipmap placement push the right edge of the |
||
160 | * 2nd mipmap out past the width of its parent. |
||
161 | */ |
||
162 | if (mt->first_level != mt->last_level) { |
||
163 | unsigned mip1_width; |
||
164 | |||
165 | if (mt->compressed) { |
||
166 | mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + |
||
167 | ALIGN(minify(mt->physical_width0, 2), mt->align_w); |
||
168 | } else { |
||
169 | mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + |
||
170 | minify(mt->physical_width0, 2); |
||
171 | } |
||
172 | |||
173 | if (mip1_width > mt->total_width) { |
||
174 | mt->total_width = mip1_width; |
||
175 | } |
||
176 | } |
||
177 | |||
178 | mt->total_height = 0; |
||
179 | |||
180 | for (unsigned level = mt->first_level; level <= mt->last_level; level++) { |
||
181 | unsigned img_height; |
||
182 | |||
183 | intel_miptree_set_level_info(mt, level, x, y, width, |
||
184 | height, depth); |
||
185 | |||
186 | img_height = ALIGN(height, mt->align_h); |
||
187 | if (mt->compressed) |
||
188 | img_height /= mt->align_h; |
||
189 | |||
190 | /* Because the images are packed better, the final offset |
||
191 | * might not be the maximal one: |
||
192 | */ |
||
193 | mt->total_height = MAX2(mt->total_height, y + img_height); |
||
194 | |||
195 | /* Layout_below: step right after second mipmap. |
||
196 | */ |
||
197 | if (level == mt->first_level + 1) { |
||
198 | x += ALIGN(width, mt->align_w); |
||
199 | } else { |
||
200 | y += img_height; |
||
201 | } |
||
202 | |||
203 | width = minify(width, 1); |
||
204 | height = minify(height, 1); |
||
205 | } |
||
206 | } |
||
207 | |||
208 | static void |
||
209 | align_cube(struct intel_mipmap_tree *mt) |
||
210 | { |
||
211 | /* The 965's sampler lays cachelines out according to how accesses |
||
212 | * in the texture surfaces run, so they may be "vertical" through |
||
213 | * memory. As a result, the docs say in Surface Padding Requirements: |
||
214 | * Sampling Engine Surfaces that two extra rows of padding are required. |
||
215 | */ |
||
216 | if (mt->target == GL_TEXTURE_CUBE_MAP) |
||
217 | mt->total_height += 2; |
||
218 | } |
||
219 | |||
220 | static void |
||
221 | brw_miptree_layout_texture_array(struct brw_context *brw, |
||
222 | struct intel_mipmap_tree *mt) |
||
223 | { |
||
224 | unsigned qpitch = 0; |
||
225 | int h0, h1; |
||
226 | |||
227 | h0 = ALIGN(mt->physical_height0, mt->align_h); |
||
228 | h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h); |
||
229 | if (mt->array_spacing_lod0) |
||
230 | qpitch = h0; |
||
231 | else |
||
232 | qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h); |
||
233 | if (mt->compressed) |
||
234 | qpitch /= 4; |
||
235 | |||
236 | brw_miptree_layout_2d(mt); |
||
237 | |||
238 | for (unsigned level = mt->first_level; level <= mt->last_level; level++) { |
||
239 | for (int q = 0; q < mt->physical_depth0; q++) { |
||
240 | intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch); |
||
241 | } |
||
242 | } |
||
243 | mt->total_height = qpitch * mt->physical_depth0; |
||
244 | |||
245 | align_cube(mt); |
||
246 | } |
||
247 | |||
248 | static void |
||
249 | brw_miptree_layout_texture_3d(struct brw_context *brw, |
||
250 | struct intel_mipmap_tree *mt) |
||
251 | { |
||
252 | unsigned yscale = mt->compressed ? 4 : 1; |
||
253 | |||
254 | mt->total_width = 0; |
||
255 | mt->total_height = 0; |
||
256 | |||
257 | unsigned ysum = 0; |
||
258 | for (unsigned level = mt->first_level; level <= mt->last_level; level++) { |
||
259 | unsigned WL = MAX2(mt->physical_width0 >> level, 1); |
||
260 | unsigned HL = MAX2(mt->physical_height0 >> level, 1); |
||
261 | unsigned DL = MAX2(mt->physical_depth0 >> level, 1); |
||
262 | unsigned wL = ALIGN(WL, mt->align_w); |
||
263 | unsigned hL = ALIGN(HL, mt->align_h); |
||
264 | |||
265 | if (mt->target == GL_TEXTURE_CUBE_MAP) |
||
266 | DL = 6; |
||
267 | |||
268 | intel_miptree_set_level_info(mt, level, 0, 0, WL, HL, DL); |
||
269 | |||
270 | for (unsigned q = 0; q < DL; q++) { |
||
271 | unsigned x = (q % (1 << level)) * wL; |
||
272 | unsigned y = ysum + (q >> level) * hL; |
||
273 | |||
274 | intel_miptree_set_image_offset(mt, level, q, x, y / yscale); |
||
275 | mt->total_width = MAX2(mt->total_width, x + wL); |
||
276 | mt->total_height = MAX2(mt->total_height, (y + hL) / yscale); |
||
277 | } |
||
278 | |||
279 | ysum += ALIGN(DL, 1 << level) / (1 << level) * hL; |
||
280 | } |
||
281 | |||
282 | align_cube(mt); |
||
283 | } |
||
284 | |||
285 | void |
||
286 | brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt) |
||
287 | { |
||
4401 | Serge | 288 | bool multisampled = mt->num_samples > 1; |
4358 | Serge | 289 | mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt->format); |
4401 | Serge | 290 | mt->align_h = |
291 | intel_vertical_texture_alignment_unit(brw, mt->format, multisampled); |
||
4358 | Serge | 292 | |
293 | switch (mt->target) { |
||
294 | case GL_TEXTURE_CUBE_MAP: |
||
295 | if (brw->gen == 4) { |
||
296 | /* Gen4 stores cube maps as 3D textures. */ |
||
297 | assert(mt->physical_depth0 == 6); |
||
298 | brw_miptree_layout_texture_3d(brw, mt); |
||
299 | } else { |
||
300 | /* All other hardware stores cube maps as 2D arrays. */ |
||
301 | brw_miptree_layout_texture_array(brw, mt); |
||
302 | } |
||
303 | break; |
||
304 | |||
305 | case GL_TEXTURE_3D: |
||
306 | brw_miptree_layout_texture_3d(brw, mt); |
||
307 | break; |
||
308 | |||
309 | case GL_TEXTURE_1D_ARRAY: |
||
310 | case GL_TEXTURE_2D_ARRAY: |
||
311 | case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: |
||
312 | case GL_TEXTURE_CUBE_MAP_ARRAY: |
||
313 | brw_miptree_layout_texture_array(brw, mt); |
||
314 | break; |
||
315 | |||
316 | default: |
||
317 | switch (mt->msaa_layout) { |
||
318 | case INTEL_MSAA_LAYOUT_UMS: |
||
319 | case INTEL_MSAA_LAYOUT_CMS: |
||
320 | brw_miptree_layout_texture_array(brw, mt); |
||
321 | break; |
||
322 | case INTEL_MSAA_LAYOUT_NONE: |
||
323 | case INTEL_MSAA_LAYOUT_IMS: |
||
324 | brw_miptree_layout_2d(mt); |
||
325 | break; |
||
326 | } |
||
327 | break; |
||
328 | } |
||
329 | DBG("%s: %dx%dx%d\n", __FUNCTION__, |
||
330 | mt->total_width, mt->total_height, mt->cpp); |
||
331 | }><>><>><>>=>>=>=> |
||
332 |