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]);