1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 * Texture tile caching.
35 #include "util/u_inlines.h"
36 #include "util/u_memory.h"
37 #include "util/u_tile.h"
38 #include "util/u_format.h"
39 #include "util/u_math.h"
40 #include "sp_context.h"
41 #include "sp_texture.h"
42 #include "sp_tex_tile_cache.h"
46 struct softpipe_tex_tile_cache
*
47 sp_create_tex_tile_cache( struct pipe_context
*pipe
)
49 struct softpipe_tex_tile_cache
*tc
;
52 /* make sure max texture size works */
53 assert((TILE_SIZE
<< TEX_ADDR_BITS
) >= (1 << (SP_MAX_TEXTURE_2D_LEVELS
-1)));
55 tc
= CALLOC_STRUCT( softpipe_tex_tile_cache
);
58 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
59 tc
->entries
[pos
].addr
.bits
.invalid
= 1;
61 tc
->last_tile
= &tc
->entries
[0]; /* any tile */
68 sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache
*tc
)
73 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
74 /*assert(tc->entries[pos].x < 0);*/
77 tc
->pipe
->transfer_destroy(tc
->pipe
, tc
->transfer
);
80 tc
->pipe
->transfer_destroy(tc
->pipe
, tc
->tex_trans
);
91 sp_tex_tile_cache_map_transfers(struct softpipe_tex_tile_cache
*tc
)
93 if (tc
->tex_trans
&& !tc
->tex_trans_map
)
94 tc
->tex_trans_map
= tc
->pipe
->transfer_map(tc
->pipe
, tc
->tex_trans
);
99 sp_tex_tile_cache_unmap_transfers(struct softpipe_tex_tile_cache
*tc
)
101 if (tc
->tex_trans_map
) {
102 tc
->pipe
->transfer_unmap(tc
->pipe
, tc
->tex_trans
);
103 tc
->tex_trans_map
= NULL
;
108 * Invalidate all cached tiles for the cached texture.
109 * Should be called when the texture is modified.
112 sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache
*tc
)
119 for (i
= 0; i
< NUM_ENTRIES
; i
++) {
120 tc
->entries
[i
].addr
.bits
.invalid
= 1;
125 sp_tex_tile_is_compat_view(struct softpipe_tex_tile_cache
*tc
,
126 struct pipe_sampler_view
*view
)
130 return (tc
->texture
== view
->texture
&&
131 tc
->format
== view
->format
&&
132 tc
->swizzle_r
== view
->swizzle_r
&&
133 tc
->swizzle_g
== view
->swizzle_g
&&
134 tc
->swizzle_b
== view
->swizzle_b
&&
135 tc
->swizzle_a
== view
->swizzle_a
);
139 * Specify the sampler view to cache.
142 sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache
*tc
,
143 struct pipe_sampler_view
*view
)
145 struct pipe_resource
*texture
= view
? view
->texture
: NULL
;
148 assert(!tc
->transfer
);
150 if (!sp_tex_tile_is_compat_view(tc
, view
)) {
151 pipe_resource_reference(&tc
->texture
, texture
);
154 if (tc
->tex_trans_map
) {
155 tc
->pipe
->transfer_unmap(tc
->pipe
, tc
->tex_trans
);
156 tc
->tex_trans_map
= NULL
;
159 tc
->pipe
->transfer_destroy(tc
->pipe
, tc
->tex_trans
);
160 tc
->tex_trans
= NULL
;
164 tc
->swizzle_r
= view
->swizzle_r
;
165 tc
->swizzle_g
= view
->swizzle_g
;
166 tc
->swizzle_b
= view
->swizzle_b
;
167 tc
->swizzle_a
= view
->swizzle_a
;
168 tc
->format
= view
->format
;
171 /* mark as entries as invalid/empty */
172 /* XXX we should try to avoid this when the teximage hasn't changed */
173 for (i
= 0; i
< NUM_ENTRIES
; i
++) {
174 tc
->entries
[i
].addr
.bits
.invalid
= 1;
177 tc
->tex_face
= -1; /* any invalid value here */
185 * Flush the tile cache: write all dirty tiles back to the transfer.
186 * any tiles "flagged" as cleared will be "really" cleared.
189 sp_flush_tex_tile_cache(struct softpipe_tex_tile_cache
*tc
)
194 /* caching a texture, mark all entries as empty */
195 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
196 tc
->entries
[pos
].addr
.bits
.invalid
= 1;
205 * Given the texture face, level, zslice, x and y values, compute
206 * the cache entry position/index where we'd hope to find the
207 * cached texture tile.
208 * This is basically a direct-map cache.
209 * XXX There's probably lots of ways in which we can improve this.
212 tex_cache_pos( union tex_tile_address addr
)
214 uint entry
= (addr
.bits
.x
+
218 addr
.bits
.level
* 7);
220 return entry
% NUM_ENTRIES
;
224 * Similar to sp_get_cached_tile() but for textures.
225 * Tiles are read-only and indexed with more params.
227 const struct softpipe_tex_cached_tile
*
228 sp_find_cached_tile_tex(struct softpipe_tex_tile_cache
*tc
,
229 union tex_tile_address addr
)
231 struct softpipe_tex_cached_tile
*tile
;
232 boolean zs
= util_format_is_depth_or_stencil(tc
->format
);
234 tile
= tc
->entries
+ tex_cache_pos( addr
);
236 if (addr
.value
!= tile
->addr
.value
) {
238 /* cache miss. Most misses are because we've invaldiated the
239 * texture cache previously -- most commonly on binding a new
240 * texture. Currently we effectively flush the cache on texture
244 _debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n"
245 " tile %u: x=%d y=%d z=%d face=%d level=%d\n",
246 pos
, x
/TILE_SIZE
, y
/TILE_SIZE
, z
, face
, level
,
247 pos
, tile
->addr
.bits
.x
, tile
->addr
.bits
.y
, tile
->z
, tile
->face
, tile
->level
);
250 /* check if we need to get a new transfer */
251 if (!tc
->tex_trans
||
252 tc
->tex_face
!= addr
.bits
.face
||
253 tc
->tex_level
!= addr
.bits
.level
||
254 tc
->tex_z
!= addr
.bits
.z
) {
255 /* get new transfer (view into texture) */
256 unsigned width
, height
, layer
;
259 if (tc
->tex_trans_map
) {
260 tc
->pipe
->transfer_unmap(tc
->pipe
, tc
->tex_trans
);
261 tc
->tex_trans_map
= NULL
;
264 tc
->pipe
->transfer_destroy(tc
->pipe
, tc
->tex_trans
);
265 tc
->tex_trans
= NULL
;
268 width
= u_minify(tc
->texture
->width0
, addr
.bits
.level
);
269 if (tc
->texture
->target
== PIPE_TEXTURE_1D_ARRAY
) {
270 height
= tc
->texture
->array_size
;
274 height
= u_minify(tc
->texture
->height0
, addr
.bits
.level
);
275 layer
= addr
.bits
.face
+ addr
.bits
.z
;
279 pipe_get_transfer(tc
->pipe
, tc
->texture
,
282 PIPE_TRANSFER_READ
| PIPE_TRANSFER_UNSYNCHRONIZED
,
283 0, 0, width
, height
);
285 tc
->tex_trans_map
= tc
->pipe
->transfer_map(tc
->pipe
, tc
->tex_trans
);
287 tc
->tex_face
= addr
.bits
.face
;
288 tc
->tex_level
= addr
.bits
.level
;
289 tc
->tex_z
= addr
.bits
.z
;
292 /* Get tile from the transfer (view into texture), explicitly passing
295 if (!zs
&& util_format_is_pure_uint(tc
->format
)) {
296 pipe_get_tile_ui_format(tc
->pipe
,
298 addr
.bits
.x
* TILE_SIZE
,
299 addr
.bits
.y
* TILE_SIZE
,
303 (unsigned *) tile
->data
.colorui
);
304 } else if (!zs
&& util_format_is_pure_sint(tc
->format
)) {
305 pipe_get_tile_i_format(tc
->pipe
,
307 addr
.bits
.x
* TILE_SIZE
,
308 addr
.bits
.y
* TILE_SIZE
,
312 (int *) tile
->data
.colori
);
314 pipe_get_tile_rgba_format(tc
->pipe
,
316 addr
.bits
.x
* TILE_SIZE
,
317 addr
.bits
.y
* TILE_SIZE
,
321 (float *) tile
->data
.color
);
326 tc
->last_tile
= tile
;