2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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
16 portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **********************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "brw_state.h"
35 #include "intel_batchbuffer.h"
38 /* XXX: Fixme - have to include these to get the sizes of the prog_key
48 /***********************************************************************
49 * Check cache for uploaded version of struct, else upload new one.
50 * Fail when memory is exhausted.
52 * XXX: FIXME: Currently search is so slow it would be quicker to
53 * regenerate the data every time...
56 static GLuint
hash_key( const void *key
, GLuint key_size
)
58 GLuint
*ikey
= (GLuint
*)key
;
61 assert(key_size
% 4 == 0);
63 /* I'm sure this can be improved on:
65 for (i
= 0; i
< key_size
/4; i
++)
71 static struct brw_cache_item
*search_cache( struct brw_cache
*cache
,
76 struct brw_cache_item
*c
;
78 for (c
= cache
->items
[hash
% cache
->size
]; c
; c
= c
->next
) {
79 if (c
->hash
== hash
&&
80 c
->key_size
== key_size
&&
81 memcmp(c
->key
, key
, key_size
) == 0)
89 static void rehash( struct brw_cache
*cache
)
91 struct brw_cache_item
**items
;
92 struct brw_cache_item
*c
, *next
;
95 size
= cache
->size
* 3;
96 items
= (struct brw_cache_item
**) _mesa_malloc(size
* sizeof(*items
));
97 _mesa_memset(items
, 0, size
* sizeof(*items
));
99 for (i
= 0; i
< cache
->size
; i
++)
100 for (c
= cache
->items
[i
]; c
; c
= next
) {
102 c
->next
= items
[c
->hash
% size
];
103 items
[c
->hash
% size
] = c
;
107 cache
->items
= items
;
112 GLboolean
brw_search_cache( struct brw_cache
*cache
,
116 GLuint
*offset_return
)
118 struct brw_cache_item
*item
;
120 GLuint hash
= hash_key(key
, key_size
);
122 item
= search_cache(cache
, hash
, key
, key_size
);
126 *(void **)aux_return
= (void *)((char *)item
->key
+ item
->key_size
);
128 *offset_return
= addr
= item
->offset
;
131 if (item
== NULL
|| addr
!= cache
->last_addr
) {
132 cache
->brw
->state
.dirty
.cache
|= 1<<cache
->id
;
133 cache
->last_addr
= addr
;
139 GLuint
brw_upload_cache( struct brw_cache
*cache
,
148 struct brw_cache_item
*item
= CALLOC_STRUCT(brw_cache_item
);
149 GLuint hash
= hash_key(key
, key_size
);
150 void *tmp
= _mesa_malloc(key_size
+ cache
->aux_size
);
152 if (!brw_pool_alloc(cache
->pool
, data_size
, 6, &offset
)) {
153 /* Should not be possible:
155 _mesa_printf("brw_pool_alloc failed\n");
159 memcpy(tmp
, key
, key_size
);
162 memcpy(tmp
+key_size
, aux
, cache
->aux_size
);
166 item
->key_size
= key_size
;
167 item
->offset
= offset
;
168 item
->data_size
= data_size
;
170 if (++cache
->n_items
> cache
->size
* 1.5)
174 item
->next
= cache
->items
[hash
];
175 cache
->items
[hash
] = item
;
178 assert(cache
->aux_size
);
179 *(void **)aux_return
= (void *)((char *)item
->key
+ item
->key_size
);
182 if (INTEL_DEBUG
& DEBUG_STATE
)
183 _mesa_printf("upload %s: %d bytes to pool buffer %d offset %x\n",
189 /* Copy data to the buffer:
191 bmBufferSubDataAUB(&cache
->brw
->intel
,
197 cache
->aub_sub_type
);
200 cache
->brw
->state
.dirty
.cache
|= 1<<cache
->id
;
201 cache
->last_addr
= offset
;
206 /* This doesn't really work with aux data. Use search/upload instead
208 GLuint
brw_cache_data_sz(struct brw_cache
*cache
,
214 if (!brw_search_cache(cache
, data
, data_size
, NULL
, &addr
)) {
215 addr
= brw_upload_cache(cache
,
224 GLuint
brw_cache_data(struct brw_cache
*cache
,
227 return brw_cache_data_sz(cache
, data
, cache
->key_size
);
234 static void brw_init_cache( struct brw_context
*brw
,
240 GLuint aub_sub_type
)
242 struct brw_cache
*cache
= &brw
->cache
[id
];
250 cache
->items
= (struct brw_cache_item
**)
251 _mesa_calloc(cache
->size
*
252 sizeof(struct brw_cache_item
));
255 cache
->key_size
= key_size
;
256 cache
->aux_size
= aux_size
;
257 cache
->aub_type
= aub_type
;
258 cache
->aub_sub_type
= aub_sub_type
;
260 case DW_GENERAL_STATE
: cache
->pool
= &brw
->pool
[BRW_GS_POOL
]; break;
261 case DW_SURFACE_STATE
: cache
->pool
= &brw
->pool
[BRW_SS_POOL
]; break;
262 default: assert(0); break;
266 void brw_init_caches( struct brw_context
*brw
)
272 sizeof(struct brw_cc_viewport
),
275 DWGS_COLOR_CALC_VIEWPORT_STATE
);
280 sizeof(struct brw_cc_unit_state
),
283 DWGS_COLOR_CALC_STATE
);
288 sizeof(struct brw_wm_prog_key
),
289 sizeof(struct brw_wm_prog_data
),
291 DWGS_KERNEL_INSTRUCTIONS
);
294 "SAMPLER_DEFAULT_COLOR",
295 BRW_SAMPLER_DEFAULT_COLOR
,
296 sizeof(struct brw_sampler_default_color
),
299 DWGS_SAMPLER_DEFAULT_COLOR
);
304 0, /* variable key/data size */
312 sizeof(struct brw_wm_unit_state
),
315 DWGS_WINDOWER_IZ_STATE
);
320 sizeof(struct brw_sf_prog_key
),
321 sizeof(struct brw_sf_prog_data
),
323 DWGS_KERNEL_INSTRUCTIONS
);
328 sizeof(struct brw_sf_viewport
),
331 DWGS_STRIPS_FANS_VIEWPORT_STATE
);
336 sizeof(struct brw_sf_unit_state
),
339 DWGS_STRIPS_FANS_STATE
);
344 sizeof(struct brw_vs_unit_state
),
347 DWGS_VERTEX_SHADER_STATE
);
352 sizeof(struct brw_vs_prog_key
),
353 sizeof(struct brw_vs_prog_data
),
355 DWGS_KERNEL_INSTRUCTIONS
);
360 sizeof(struct brw_clip_unit_state
),
368 sizeof(struct brw_clip_prog_key
),
369 sizeof(struct brw_clip_prog_data
),
371 DWGS_KERNEL_INSTRUCTIONS
);
376 sizeof(struct brw_gs_unit_state
),
379 DWGS_GEOMETRY_SHADER_STATE
);
384 sizeof(struct brw_gs_prog_key
),
385 sizeof(struct brw_gs_prog_data
),
387 DWGS_KERNEL_INSTRUCTIONS
);
392 sizeof(struct brw_surface_state
),
400 sizeof(struct brw_surface_binding_table
),
403 DWSS_BINDING_TABLE_STATE
);
407 /* When we lose hardware context, need to invalidate the surface cache
408 * as these structs must be explicitly re-uploaded. They are subject
409 * to fixup by the memory manager as they contain absolute agp
410 * offsets, so we need to ensure there is a fresh version of the
411 * struct available to receive the fixup.
413 * XXX: Need to ensure that there aren't two versions of a surface or
414 * bufferobj with different backing data active in the same buffer at
415 * once? Otherwise the cache could confuse them. Maybe better not to
418 * --> Isn't this the same as saying need to ensure batch is flushed
419 * before new data is uploaded to an existing buffer? We
420 * already try to make sure of that.
422 static void clear_cache( struct brw_cache
*cache
)
424 struct brw_cache_item
*c
, *next
;
427 for (i
= 0; i
< cache
->size
; i
++) {
428 for (c
= cache
->items
[i
]; c
; c
= next
) {
430 free((void *)c
->key
);
433 cache
->items
[i
] = NULL
;
439 void brw_clear_all_caches( struct brw_context
*brw
)
443 if (INTEL_DEBUG
& DEBUG_STATE
)
444 _mesa_printf("%s\n", __FUNCTION__
);
446 for (i
= 0; i
< BRW_MAX_CACHE
; i
++)
447 clear_cache(&brw
->cache
[i
]);
449 if (brw
->curbe
.last_buf
) {
450 _mesa_free(brw
->curbe
.last_buf
);
451 brw
->curbe
.last_buf
= NULL
;
454 brw
->state
.dirty
.mesa
|= ~0;
455 brw
->state
.dirty
.brw
|= ~0;
456 brw
->state
.dirty
.cache
|= ~0;
463 void brw_destroy_caches( struct brw_context
*brw
)
467 for (i
= 0; i
< BRW_MAX_CACHE
; i
++)
468 clear_cache(&brw
->cache
[i
]);