1cdc920a0Smrg/************************************************************************** 2cdc920a0Smrg * 3cdc920a0Smrg * Copyright 2009 VMware, Inc. 4cdc920a0Smrg * All Rights Reserved. 5cdc920a0Smrg * 6cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7cdc920a0Smrg * copy of this software and associated documentation files (the 8cdc920a0Smrg * "Software"), to deal in the Software without restriction, including 9cdc920a0Smrg * without limitation the rights to use, copy, modify, merge, publish, 10cdc920a0Smrg * distribute, sub license, and/or sell copies of the Software, and to 11cdc920a0Smrg * permit persons to whom the Software is furnished to do so, subject to 12cdc920a0Smrg * the following conditions: 13cdc920a0Smrg * 14cdc920a0Smrg * The above copyright notice and this permission notice (including the 15cdc920a0Smrg * next paragraph) shall be included in all copies or substantial portions 16cdc920a0Smrg * of the Software. 17cdc920a0Smrg * 18cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20cdc920a0Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21cdc920a0Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22cdc920a0Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23cdc920a0Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24cdc920a0Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25cdc920a0Smrg * 26cdc920a0Smrg **************************************************************************/ 27cdc920a0Smrg 283464ebd5Sriastradh#include "util/u_framebuffer.h" 29cdc920a0Smrg#include "util/u_math.h" 30cdc920a0Smrg#include "util/u_memory.h" 31cdc920a0Smrg#include "util/u_inlines.h" 3201e04c3fSmrg#include "util/simple_list.h" 337ec681f3Smrg#include "util/format/u_format.h" 34cdc920a0Smrg#include "lp_scene.h" 353464ebd5Sriastradh#include "lp_fence.h" 36cdc920a0Smrg#include "lp_debug.h" 377ec681f3Smrg#include "lp_context.h" 387ec681f3Smrg#include "lp_state_fs.h" 39cdc920a0Smrg 40cdc920a0Smrg 413464ebd5Sriastradh#define RESOURCE_REF_SZ 32 423464ebd5Sriastradh 433464ebd5Sriastradh/** List of resource references */ 443464ebd5Sriastradhstruct resource_ref { 453464ebd5Sriastradh struct pipe_resource *resource[RESOURCE_REF_SZ]; 463464ebd5Sriastradh int count; 473464ebd5Sriastradh struct resource_ref *next; 483464ebd5Sriastradh}; 493464ebd5Sriastradh 507ec681f3Smrg#define SHADER_REF_SZ 32 517ec681f3Smrg/** List of shader variant references */ 527ec681f3Smrgstruct shader_ref { 537ec681f3Smrg struct lp_fragment_shader_variant *variant[SHADER_REF_SZ]; 547ec681f3Smrg int count; 557ec681f3Smrg struct shader_ref *next; 567ec681f3Smrg}; 577ec681f3Smrg 583464ebd5Sriastradh 593464ebd5Sriastradh/** 603464ebd5Sriastradh * Create a new scene object. 613464ebd5Sriastradh * \param queue the queue to put newly rendered/emptied scenes into 623464ebd5Sriastradh */ 63cdc920a0Smrgstruct lp_scene * 643464ebd5Sriastradhlp_scene_create( struct pipe_context *pipe ) 65cdc920a0Smrg{ 66cdc920a0Smrg struct lp_scene *scene = CALLOC_STRUCT(lp_scene); 67cdc920a0Smrg if (!scene) 68cdc920a0Smrg return NULL; 69cdc920a0Smrg 70cdc920a0Smrg scene->pipe = pipe; 717ec681f3Smrg scene->data.head = &scene->data.first; 72cdc920a0Smrg 7301e04c3fSmrg (void) mtx_init(&scene->mutex, mtx_plain); 74cdc920a0Smrg 75af69d88dSmrg#ifdef DEBUG 76af69d88dSmrg /* Do some scene limit sanity checks here */ 77af69d88dSmrg { 78af69d88dSmrg size_t maxBins = TILES_X * TILES_Y; 79af69d88dSmrg size_t maxCommandBytes = sizeof(struct cmd_block) * maxBins; 80af69d88dSmrg size_t maxCommandPlusData = maxCommandBytes + DATA_BLOCK_SIZE; 81af69d88dSmrg /* We'll need at least one command block per bin. Make sure that's 82af69d88dSmrg * less than the max allowed scene size. 83af69d88dSmrg */ 84af69d88dSmrg assert(maxCommandBytes < LP_SCENE_MAX_SIZE); 85af69d88dSmrg /* We'll also need space for at least one other data block */ 86af69d88dSmrg assert(maxCommandPlusData <= LP_SCENE_MAX_SIZE); 87af69d88dSmrg } 88af69d88dSmrg#endif 89af69d88dSmrg 90cdc920a0Smrg return scene; 91cdc920a0Smrg} 92cdc920a0Smrg 93cdc920a0Smrg 94cdc920a0Smrg/** 953464ebd5Sriastradh * Free all data associated with the given scene, and the scene itself. 96cdc920a0Smrg */ 97cdc920a0Smrgvoid 98cdc920a0Smrglp_scene_destroy(struct lp_scene *scene) 99cdc920a0Smrg{ 1003464ebd5Sriastradh lp_fence_reference(&scene->fence, NULL); 10101e04c3fSmrg mtx_destroy(&scene->mutex); 1027ec681f3Smrg assert(scene->data.head == &scene->data.first); 103cdc920a0Smrg FREE(scene); 104cdc920a0Smrg} 105cdc920a0Smrg 106cdc920a0Smrg 107cdc920a0Smrg/** 108cdc920a0Smrg * Check if the scene's bins are all empty. 109cdc920a0Smrg * For debugging purposes. 110cdc920a0Smrg */ 111cdc920a0Smrgboolean 112cdc920a0Smrglp_scene_is_empty(struct lp_scene *scene ) 113cdc920a0Smrg{ 114cdc920a0Smrg unsigned x, y; 115cdc920a0Smrg 1167ec681f3Smrg for (y = 0; y < scene->tiles_y; y++) { 1177ec681f3Smrg for (x = 0; x < scene->tiles_x; x++) { 118cdc920a0Smrg const struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); 1193464ebd5Sriastradh if (bin->head) { 120cdc920a0Smrg return FALSE; 121cdc920a0Smrg } 122cdc920a0Smrg } 123cdc920a0Smrg } 124cdc920a0Smrg return TRUE; 125cdc920a0Smrg} 126cdc920a0Smrg 127cdc920a0Smrg 1283464ebd5Sriastradh/* Returns true if there has ever been a failed allocation attempt in 1297ec681f3Smrg * this scene. Used in triangle/rectangle emit to avoid having to 1307ec681f3Smrg * check success at each bin. 1313464ebd5Sriastradh */ 1323464ebd5Sriastradhboolean 1333464ebd5Sriastradhlp_scene_is_oom(struct lp_scene *scene) 1343464ebd5Sriastradh{ 1353464ebd5Sriastradh return scene->alloc_failed; 1363464ebd5Sriastradh} 1373464ebd5Sriastradh 1383464ebd5Sriastradh 1393464ebd5Sriastradh/* Remove all commands from a bin. Tries to reuse some of the memory 1403464ebd5Sriastradh * allocated to the bin, however. 141cdc920a0Smrg */ 142cdc920a0Smrgvoid 143cdc920a0Smrglp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y) 144cdc920a0Smrg{ 145cdc920a0Smrg struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); 146cdc920a0Smrg 147af69d88dSmrg bin->last_state = NULL; 1483464ebd5Sriastradh bin->head = bin->tail; 1493464ebd5Sriastradh if (bin->tail) { 1503464ebd5Sriastradh bin->tail->next = NULL; 1513464ebd5Sriastradh bin->tail->count = 0; 1523464ebd5Sriastradh } 1533464ebd5Sriastradh} 1543464ebd5Sriastradh 1557ec681f3Smrgstatic void 1567ec681f3Smrginit_scene_texture(struct lp_scene_surface *ssurf, struct pipe_surface *psurf) 1577ec681f3Smrg{ 1587ec681f3Smrg if (!psurf) { 1597ec681f3Smrg ssurf->stride = 0; 1607ec681f3Smrg ssurf->layer_stride = 0; 1617ec681f3Smrg ssurf->sample_stride = 0; 1627ec681f3Smrg ssurf->nr_samples = 0; 1637ec681f3Smrg ssurf->map = NULL; 1647ec681f3Smrg return; 1657ec681f3Smrg } 1667ec681f3Smrg 1677ec681f3Smrg if (llvmpipe_resource_is_texture(psurf->texture)) { 1687ec681f3Smrg ssurf->stride = llvmpipe_resource_stride(psurf->texture, 1697ec681f3Smrg psurf->u.tex.level); 1707ec681f3Smrg ssurf->layer_stride = llvmpipe_layer_stride(psurf->texture, 1717ec681f3Smrg psurf->u.tex.level); 1727ec681f3Smrg ssurf->sample_stride = llvmpipe_sample_stride(psurf->texture); 1737ec681f3Smrg 1747ec681f3Smrg ssurf->map = llvmpipe_resource_map(psurf->texture, 1757ec681f3Smrg psurf->u.tex.level, 1767ec681f3Smrg psurf->u.tex.first_layer, 1777ec681f3Smrg LP_TEX_USAGE_READ_WRITE); 1787ec681f3Smrg ssurf->format_bytes = util_format_get_blocksize(psurf->format); 1797ec681f3Smrg ssurf->nr_samples = util_res_sample_count(psurf->texture); 1807ec681f3Smrg } 1817ec681f3Smrg else { 1827ec681f3Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(psurf->texture); 1837ec681f3Smrg unsigned pixstride = util_format_get_blocksize(psurf->format); 1847ec681f3Smrg ssurf->stride = psurf->texture->width0; 1857ec681f3Smrg ssurf->layer_stride = 0; 1867ec681f3Smrg ssurf->sample_stride = 0; 1877ec681f3Smrg ssurf->nr_samples = 1; 1887ec681f3Smrg ssurf->map = lpr->data; 1897ec681f3Smrg ssurf->map += psurf->u.buf.first_element * pixstride; 1907ec681f3Smrg ssurf->format_bytes = util_format_get_blocksize(psurf->format); 1917ec681f3Smrg } 1927ec681f3Smrg} 1933464ebd5Sriastradh 1943464ebd5Sriastradhvoid 1953464ebd5Sriastradhlp_scene_begin_rasterization(struct lp_scene *scene) 1963464ebd5Sriastradh{ 1973464ebd5Sriastradh const struct pipe_framebuffer_state *fb = &scene->fb; 1983464ebd5Sriastradh int i; 1993464ebd5Sriastradh 2003464ebd5Sriastradh //LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); 201cdc920a0Smrg 2023464ebd5Sriastradh for (i = 0; i < scene->fb.nr_cbufs; i++) { 2033464ebd5Sriastradh struct pipe_surface *cbuf = scene->fb.cbufs[i]; 2047ec681f3Smrg init_scene_texture(&scene->cbufs[i], cbuf); 205cdc920a0Smrg } 206cdc920a0Smrg 2073464ebd5Sriastradh if (fb->zsbuf) { 2083464ebd5Sriastradh struct pipe_surface *zsbuf = scene->fb.zsbuf; 2097ec681f3Smrg init_scene_texture(&scene->zsbuf, zsbuf); 2103464ebd5Sriastradh } 211cdc920a0Smrg} 212cdc920a0Smrg 213cdc920a0Smrg 2143464ebd5Sriastradh 2153464ebd5Sriastradh 216cdc920a0Smrg/** 2173464ebd5Sriastradh * Free all the temporary data in a scene. 218cdc920a0Smrg */ 219cdc920a0Smrgvoid 2203464ebd5Sriastradhlp_scene_end_rasterization(struct lp_scene *scene ) 221cdc920a0Smrg{ 2227ec681f3Smrg int i; 2233464ebd5Sriastradh 2243464ebd5Sriastradh /* Unmap color buffers */ 2253464ebd5Sriastradh for (i = 0; i < scene->fb.nr_cbufs; i++) { 2263464ebd5Sriastradh if (scene->cbufs[i].map) { 2273464ebd5Sriastradh struct pipe_surface *cbuf = scene->fb.cbufs[i]; 228af69d88dSmrg if (llvmpipe_resource_is_texture(cbuf->texture)) { 229af69d88dSmrg llvmpipe_resource_unmap(cbuf->texture, 230af69d88dSmrg cbuf->u.tex.level, 231af69d88dSmrg cbuf->u.tex.first_layer); 232af69d88dSmrg } 2333464ebd5Sriastradh scene->cbufs[i].map = NULL; 2343464ebd5Sriastradh } 2353464ebd5Sriastradh } 2363464ebd5Sriastradh 2373464ebd5Sriastradh /* Unmap z/stencil buffer */ 2383464ebd5Sriastradh if (scene->zsbuf.map) { 2393464ebd5Sriastradh struct pipe_surface *zsbuf = scene->fb.zsbuf; 2403464ebd5Sriastradh llvmpipe_resource_unmap(zsbuf->texture, 2413464ebd5Sriastradh zsbuf->u.tex.level, 2423464ebd5Sriastradh zsbuf->u.tex.first_layer); 2433464ebd5Sriastradh scene->zsbuf.map = NULL; 2443464ebd5Sriastradh } 245cdc920a0Smrg 2463464ebd5Sriastradh /* Reset all command lists: 247cdc920a0Smrg */ 2487ec681f3Smrg memset(scene->tile, 0, sizeof scene->tile); 249cdc920a0Smrg 2503464ebd5Sriastradh /* Decrement texture ref counts 2513464ebd5Sriastradh */ 2523464ebd5Sriastradh { 2533464ebd5Sriastradh struct resource_ref *ref; 2543464ebd5Sriastradh int i, j = 0; 2553464ebd5Sriastradh 2563464ebd5Sriastradh for (ref = scene->resources; ref; ref = ref->next) { 2573464ebd5Sriastradh for (i = 0; i < ref->count; i++) { 2583464ebd5Sriastradh if (LP_DEBUG & DEBUG_SETUP) 2593464ebd5Sriastradh debug_printf("resource %d: %p %dx%d sz %d\n", 2603464ebd5Sriastradh j, 2613464ebd5Sriastradh (void *) ref->resource[i], 2623464ebd5Sriastradh ref->resource[i]->width0, 2633464ebd5Sriastradh ref->resource[i]->height0, 2643464ebd5Sriastradh llvmpipe_resource_size(ref->resource[i])); 2653464ebd5Sriastradh j++; 2667ec681f3Smrg llvmpipe_resource_unmap(ref->resource[i], 0, 0); 2673464ebd5Sriastradh pipe_resource_reference(&ref->resource[i], NULL); 2683464ebd5Sriastradh } 2693464ebd5Sriastradh } 2703464ebd5Sriastradh 2713464ebd5Sriastradh if (LP_DEBUG & DEBUG_SETUP) 2723464ebd5Sriastradh debug_printf("scene %d resources, sz %d\n", 2733464ebd5Sriastradh j, scene->resource_reference_size); 2743464ebd5Sriastradh } 2753464ebd5Sriastradh 2767ec681f3Smrg /* Decrement shader variant ref counts 2777ec681f3Smrg */ 2787ec681f3Smrg { 2797ec681f3Smrg struct shader_ref *ref; 2807ec681f3Smrg int i, j = 0; 2817ec681f3Smrg 2827ec681f3Smrg for (ref = scene->frag_shaders; ref; ref = ref->next) { 2837ec681f3Smrg for (i = 0; i < ref->count; i++) { 2847ec681f3Smrg if (LP_DEBUG & DEBUG_SETUP) 2857ec681f3Smrg debug_printf("shader %d: %p\n", j, (void *) ref->variant[i]); 2867ec681f3Smrg j++; 2877ec681f3Smrg lp_fs_variant_reference(llvmpipe_context(scene->pipe), &ref->variant[i], NULL); 2887ec681f3Smrg } 2897ec681f3Smrg } 2907ec681f3Smrg } 2917ec681f3Smrg 2923464ebd5Sriastradh /* Free all scene data blocks: 293cdc920a0Smrg */ 294cdc920a0Smrg { 295cdc920a0Smrg struct data_block_list *list = &scene->data; 296cdc920a0Smrg struct data_block *block, *tmp; 297cdc920a0Smrg 2987ec681f3Smrg for (block = list->head; block; block = tmp) { 299cdc920a0Smrg tmp = block->next; 3007ec681f3Smrg if (block != &list->first) 3017ec681f3Smrg FREE(block); 302cdc920a0Smrg } 3033464ebd5Sriastradh 3047ec681f3Smrg list->head = &list->first; 3053464ebd5Sriastradh list->head->next = NULL; 306cdc920a0Smrg } 307cdc920a0Smrg 3083464ebd5Sriastradh lp_fence_reference(&scene->fence, NULL); 3093464ebd5Sriastradh 3103464ebd5Sriastradh scene->resources = NULL; 3117ec681f3Smrg scene->frag_shaders = NULL; 3123464ebd5Sriastradh scene->scene_size = 0; 3133464ebd5Sriastradh scene->resource_reference_size = 0; 3143464ebd5Sriastradh 3153464ebd5Sriastradh scene->alloc_failed = FALSE; 3163464ebd5Sriastradh 3173464ebd5Sriastradh util_unreference_framebuffer_state( &scene->fb ); 318cdc920a0Smrg} 319cdc920a0Smrg 320cdc920a0Smrg 321cdc920a0Smrg 322cdc920a0Smrg 323cdc920a0Smrg 324cdc920a0Smrg 3253464ebd5Sriastradhstruct cmd_block * 3263464ebd5Sriastradhlp_scene_new_cmd_block( struct lp_scene *scene, 3273464ebd5Sriastradh struct cmd_bin *bin ) 328cdc920a0Smrg{ 3293464ebd5Sriastradh struct cmd_block *block = lp_scene_alloc(scene, sizeof(struct cmd_block)); 3303464ebd5Sriastradh if (block) { 3313464ebd5Sriastradh if (bin->tail) { 3323464ebd5Sriastradh bin->tail->next = block; 3333464ebd5Sriastradh bin->tail = block; 3343464ebd5Sriastradh } 3353464ebd5Sriastradh else { 3363464ebd5Sriastradh bin->head = block; 3373464ebd5Sriastradh bin->tail = block; 3383464ebd5Sriastradh } 3393464ebd5Sriastradh //memset(block, 0, sizeof *block); 3403464ebd5Sriastradh block->next = NULL; 3413464ebd5Sriastradh block->count = 0; 3423464ebd5Sriastradh } 3433464ebd5Sriastradh return block; 344cdc920a0Smrg} 345cdc920a0Smrg 346cdc920a0Smrg 3473464ebd5Sriastradhstruct data_block * 3483464ebd5Sriastradhlp_scene_new_data_block( struct lp_scene *scene ) 349cdc920a0Smrg{ 3503464ebd5Sriastradh if (scene->scene_size + DATA_BLOCK_SIZE > LP_SCENE_MAX_SIZE) { 3513464ebd5Sriastradh if (0) debug_printf("%s: failed\n", __FUNCTION__); 3523464ebd5Sriastradh scene->alloc_failed = TRUE; 3533464ebd5Sriastradh return NULL; 3543464ebd5Sriastradh } 3553464ebd5Sriastradh else { 3563464ebd5Sriastradh struct data_block *block = MALLOC_STRUCT(data_block); 35701e04c3fSmrg if (!block) 3583464ebd5Sriastradh return NULL; 3593464ebd5Sriastradh 3603464ebd5Sriastradh scene->scene_size += sizeof *block; 3613464ebd5Sriastradh 3623464ebd5Sriastradh block->used = 0; 3633464ebd5Sriastradh block->next = scene->data.head; 3643464ebd5Sriastradh scene->data.head = block; 3653464ebd5Sriastradh 3663464ebd5Sriastradh return block; 3673464ebd5Sriastradh } 368cdc920a0Smrg} 369cdc920a0Smrg 370cdc920a0Smrg 3713464ebd5Sriastradh/** 3723464ebd5Sriastradh * Return number of bytes used for all bin data within a scene. 3733464ebd5Sriastradh * This does not include resources (textures) referenced by the scene. 3743464ebd5Sriastradh */ 3753464ebd5Sriastradhstatic unsigned 376cdc920a0Smrglp_scene_data_size( const struct lp_scene *scene ) 377cdc920a0Smrg{ 378cdc920a0Smrg unsigned size = 0; 379cdc920a0Smrg const struct data_block *block; 380cdc920a0Smrg for (block = scene->data.head; block; block = block->next) { 381cdc920a0Smrg size += block->used; 382cdc920a0Smrg } 383cdc920a0Smrg return size; 384cdc920a0Smrg} 385cdc920a0Smrg 386cdc920a0Smrg 387cdc920a0Smrg 388cdc920a0Smrg/** 3893464ebd5Sriastradh * Add a reference to a resource by the scene. 390cdc920a0Smrg */ 391cdc920a0Smrgboolean 3923464ebd5Sriastradhlp_scene_add_resource_reference(struct lp_scene *scene, 3933464ebd5Sriastradh struct pipe_resource *resource, 3943464ebd5Sriastradh boolean initializing_scene) 395cdc920a0Smrg{ 3963464ebd5Sriastradh struct resource_ref *ref, **last = &scene->resources; 3973464ebd5Sriastradh int i; 3983464ebd5Sriastradh 3993464ebd5Sriastradh /* Look at existing resource blocks: 4003464ebd5Sriastradh */ 4013464ebd5Sriastradh for (ref = scene->resources; ref; ref = ref->next) { 4023464ebd5Sriastradh last = &ref->next; 4033464ebd5Sriastradh 4043464ebd5Sriastradh /* Search for this resource: 4053464ebd5Sriastradh */ 4063464ebd5Sriastradh for (i = 0; i < ref->count; i++) 4073464ebd5Sriastradh if (ref->resource[i] == resource) 4083464ebd5Sriastradh return TRUE; 4093464ebd5Sriastradh 4103464ebd5Sriastradh if (ref->count < RESOURCE_REF_SZ) { 4113464ebd5Sriastradh /* If the block is half-empty, then append the reference here. 4123464ebd5Sriastradh */ 4133464ebd5Sriastradh break; 4143464ebd5Sriastradh } 415cdc920a0Smrg } 416cdc920a0Smrg 4173464ebd5Sriastradh /* Create a new block if no half-empty block was found. 4183464ebd5Sriastradh */ 4193464ebd5Sriastradh if (!ref) { 4203464ebd5Sriastradh assert(*last == NULL); 4213464ebd5Sriastradh *last = lp_scene_alloc(scene, sizeof *ref); 4223464ebd5Sriastradh if (*last == NULL) 4233464ebd5Sriastradh return FALSE; 4243464ebd5Sriastradh 4253464ebd5Sriastradh ref = *last; 4263464ebd5Sriastradh memset(ref, 0, sizeof *ref); 4273464ebd5Sriastradh } 428cdc920a0Smrg 4297ec681f3Smrg /* Map resource again to increment the map count. We likely use the 4307ec681f3Smrg * already-mapped pointer in a texture of the jit context, and that pointer 4317ec681f3Smrg * needs to stay mapped during rasterization. This map is unmap'ed when 4327ec681f3Smrg * finalizing scene rasterization. */ 4337ec681f3Smrg llvmpipe_resource_map(resource, 0, 0, LP_TEX_USAGE_READ); 4347ec681f3Smrg 4353464ebd5Sriastradh /* Append the reference to the reference block. 4363464ebd5Sriastradh */ 4373464ebd5Sriastradh pipe_resource_reference(&ref->resource[ref->count++], resource); 4383464ebd5Sriastradh scene->resource_reference_size += llvmpipe_resource_size(resource); 439cdc920a0Smrg 4403464ebd5Sriastradh /* Heuristic to advise scene flushes. This isn't helpful in the 4413464ebd5Sriastradh * initial setup of the scene, but after that point flush on the 4423464ebd5Sriastradh * next resource added which exceeds 64MB in referenced texture 4433464ebd5Sriastradh * data. 4443464ebd5Sriastradh */ 4453464ebd5Sriastradh if (!initializing_scene && 4463464ebd5Sriastradh scene->resource_reference_size >= LP_SCENE_MAX_RESOURCE_SIZE) 4473464ebd5Sriastradh return FALSE; 448cdc920a0Smrg 4493464ebd5Sriastradh return TRUE; 450cdc920a0Smrg} 451cdc920a0Smrg 452cdc920a0Smrg 4537ec681f3Smrg/** 4547ec681f3Smrg * Add a reference to a fragment shader variant 4557ec681f3Smrg */ 4567ec681f3Smrgboolean 4577ec681f3Smrglp_scene_add_frag_shader_reference(struct lp_scene *scene, 4587ec681f3Smrg struct lp_fragment_shader_variant *variant) 4597ec681f3Smrg{ 4607ec681f3Smrg struct shader_ref *ref, **last = &scene->frag_shaders; 4617ec681f3Smrg int i; 4627ec681f3Smrg 4637ec681f3Smrg /* Look at existing resource blocks: 4647ec681f3Smrg */ 4657ec681f3Smrg for (ref = scene->frag_shaders; ref; ref = ref->next) { 4667ec681f3Smrg last = &ref->next; 4677ec681f3Smrg 4687ec681f3Smrg /* Search for this resource: 4697ec681f3Smrg */ 4707ec681f3Smrg for (i = 0; i < ref->count; i++) 4717ec681f3Smrg if (ref->variant[i] == variant) 4727ec681f3Smrg return TRUE; 4737ec681f3Smrg 4747ec681f3Smrg if (ref->count < SHADER_REF_SZ) { 4757ec681f3Smrg /* If the block is half-empty, then append the reference here. 4767ec681f3Smrg */ 4777ec681f3Smrg break; 4787ec681f3Smrg } 4797ec681f3Smrg } 4807ec681f3Smrg 4817ec681f3Smrg /* Create a new block if no half-empty block was found. 4827ec681f3Smrg */ 4837ec681f3Smrg if (!ref) { 4847ec681f3Smrg assert(*last == NULL); 4857ec681f3Smrg *last = lp_scene_alloc(scene, sizeof *ref); 4867ec681f3Smrg if (*last == NULL) 4877ec681f3Smrg return FALSE; 4887ec681f3Smrg 4897ec681f3Smrg ref = *last; 4907ec681f3Smrg memset(ref, 0, sizeof *ref); 4917ec681f3Smrg } 4927ec681f3Smrg 4937ec681f3Smrg /* Append the reference to the reference block. 4947ec681f3Smrg */ 4957ec681f3Smrg lp_fs_variant_reference(llvmpipe_context(scene->pipe), &ref->variant[ref->count++], variant); 4967ec681f3Smrg 4977ec681f3Smrg return TRUE; 4987ec681f3Smrg} 4997ec681f3Smrg 500cdc920a0Smrg/** 5013464ebd5Sriastradh * Does this scene have a reference to the given resource? 502cdc920a0Smrg */ 5033464ebd5Sriastradhboolean 5043464ebd5Sriastradhlp_scene_is_resource_referenced(const struct lp_scene *scene, 5053464ebd5Sriastradh const struct pipe_resource *resource) 506cdc920a0Smrg{ 5073464ebd5Sriastradh const struct resource_ref *ref; 5083464ebd5Sriastradh int i; 5093464ebd5Sriastradh 5103464ebd5Sriastradh for (ref = scene->resources; ref; ref = ref->next) { 5113464ebd5Sriastradh for (i = 0; i < ref->count; i++) 5123464ebd5Sriastradh if (ref->resource[i] == resource) 5133464ebd5Sriastradh return TRUE; 514cdc920a0Smrg } 5153464ebd5Sriastradh 5163464ebd5Sriastradh return FALSE; 517cdc920a0Smrg} 518cdc920a0Smrg 519cdc920a0Smrg 5203464ebd5Sriastradh 5213464ebd5Sriastradh 522cdc920a0Smrg/** advance curr_x,y to the next bin */ 523cdc920a0Smrgstatic boolean 524cdc920a0Smrgnext_bin(struct lp_scene *scene) 525cdc920a0Smrg{ 526cdc920a0Smrg scene->curr_x++; 527cdc920a0Smrg if (scene->curr_x >= scene->tiles_x) { 528cdc920a0Smrg scene->curr_x = 0; 529cdc920a0Smrg scene->curr_y++; 530cdc920a0Smrg } 531cdc920a0Smrg if (scene->curr_y >= scene->tiles_y) { 532cdc920a0Smrg /* no more bins */ 533cdc920a0Smrg return FALSE; 534cdc920a0Smrg } 535cdc920a0Smrg return TRUE; 536cdc920a0Smrg} 537cdc920a0Smrg 538cdc920a0Smrg 539cdc920a0Smrgvoid 540cdc920a0Smrglp_scene_bin_iter_begin( struct lp_scene *scene ) 541cdc920a0Smrg{ 542cdc920a0Smrg scene->curr_x = scene->curr_y = -1; 543cdc920a0Smrg} 544cdc920a0Smrg 545cdc920a0Smrg 546cdc920a0Smrg/** 547cdc920a0Smrg * Return pointer to next bin to be rendered. 548cdc920a0Smrg * The lp_scene::curr_x and ::curr_y fields will be advanced. 549cdc920a0Smrg * Multiple rendering threads will call this function to get a chunk 550cdc920a0Smrg * of work (a bin) to work on. 551cdc920a0Smrg */ 552cdc920a0Smrgstruct cmd_bin * 553af69d88dSmrglp_scene_bin_iter_next( struct lp_scene *scene , int *x, int *y) 554cdc920a0Smrg{ 555cdc920a0Smrg struct cmd_bin *bin = NULL; 556cdc920a0Smrg 55701e04c3fSmrg mtx_lock(&scene->mutex); 558cdc920a0Smrg 559cdc920a0Smrg if (scene->curr_x < 0) { 560cdc920a0Smrg /* first bin */ 561cdc920a0Smrg scene->curr_x = 0; 562cdc920a0Smrg scene->curr_y = 0; 563cdc920a0Smrg } 564cdc920a0Smrg else if (!next_bin(scene)) { 565cdc920a0Smrg /* no more bins left */ 566cdc920a0Smrg goto end; 567cdc920a0Smrg } 568cdc920a0Smrg 569cdc920a0Smrg bin = lp_scene_get_bin(scene, scene->curr_x, scene->curr_y); 570af69d88dSmrg *x = scene->curr_x; 571af69d88dSmrg *y = scene->curr_y; 572cdc920a0Smrg 573cdc920a0Smrgend: 574cdc920a0Smrg /*printf("return bin %p at %d, %d\n", (void *) bin, *bin_x, *bin_y);*/ 57501e04c3fSmrg mtx_unlock(&scene->mutex); 576cdc920a0Smrg return bin; 577cdc920a0Smrg} 578cdc920a0Smrg 579cdc920a0Smrg 58001e04c3fSmrgvoid lp_scene_begin_binning(struct lp_scene *scene, 58101e04c3fSmrg struct pipe_framebuffer_state *fb) 582cdc920a0Smrg{ 583af69d88dSmrg int i; 584af69d88dSmrg unsigned max_layer = ~0; 585af69d88dSmrg 586cdc920a0Smrg assert(lp_scene_is_empty(scene)); 587cdc920a0Smrg 588cdc920a0Smrg util_copy_framebuffer_state(&scene->fb, fb); 589cdc920a0Smrg 590cdc920a0Smrg scene->tiles_x = align(fb->width, TILE_SIZE) / TILE_SIZE; 591cdc920a0Smrg scene->tiles_y = align(fb->height, TILE_SIZE) / TILE_SIZE; 5923464ebd5Sriastradh assert(scene->tiles_x <= TILES_X); 5933464ebd5Sriastradh assert(scene->tiles_y <= TILES_Y); 594af69d88dSmrg 595af69d88dSmrg /* 596af69d88dSmrg * Determine how many layers the fb has (used for clamping layer value). 597af69d88dSmrg * OpenGL (but not d3d10) permits different amount of layers per rt, however 598af69d88dSmrg * results are undefined if layer exceeds the amount of layers of ANY 599af69d88dSmrg * attachment hence don't need separate per cbuf and zsbuf max. 600af69d88dSmrg */ 601af69d88dSmrg for (i = 0; i < scene->fb.nr_cbufs; i++) { 602af69d88dSmrg struct pipe_surface *cbuf = scene->fb.cbufs[i]; 603af69d88dSmrg if (cbuf) { 604af69d88dSmrg if (llvmpipe_resource_is_texture(cbuf->texture)) { 605af69d88dSmrg max_layer = MIN2(max_layer, 606af69d88dSmrg cbuf->u.tex.last_layer - cbuf->u.tex.first_layer); 607af69d88dSmrg } 608af69d88dSmrg else { 609af69d88dSmrg max_layer = 0; 610af69d88dSmrg } 611af69d88dSmrg } 612af69d88dSmrg } 613af69d88dSmrg if (fb->zsbuf) { 614af69d88dSmrg struct pipe_surface *zsbuf = scene->fb.zsbuf; 615af69d88dSmrg max_layer = MIN2(max_layer, zsbuf->u.tex.last_layer - zsbuf->u.tex.first_layer); 616af69d88dSmrg } 617af69d88dSmrg scene->fb_max_layer = max_layer; 6187ec681f3Smrg scene->fb_max_samples = util_framebuffer_get_num_samples(fb); 6197ec681f3Smrg if (scene->fb_max_samples == 4) { 6207ec681f3Smrg for (unsigned i = 0; i < 4; i++) { 6217ec681f3Smrg scene->fixed_sample_pos[i][0] = util_iround(lp_sample_pos_4x[i][0] * FIXED_ONE); 6227ec681f3Smrg scene->fixed_sample_pos[i][1] = util_iround(lp_sample_pos_4x[i][1] * FIXED_ONE); 6237ec681f3Smrg } 6247ec681f3Smrg } 625cdc920a0Smrg} 626cdc920a0Smrg 627cdc920a0Smrg 6283464ebd5Sriastradhvoid lp_scene_end_binning( struct lp_scene *scene ) 629cdc920a0Smrg{ 6303464ebd5Sriastradh if (LP_DEBUG & DEBUG_SCENE) { 631cdc920a0Smrg debug_printf("rasterize scene:\n"); 6323464ebd5Sriastradh debug_printf(" scene_size: %u\n", 6333464ebd5Sriastradh scene->scene_size); 6343464ebd5Sriastradh debug_printf(" data size: %u\n", 6353464ebd5Sriastradh lp_scene_data_size(scene)); 636cdc920a0Smrg 6373464ebd5Sriastradh if (0) 6383464ebd5Sriastradh lp_debug_bins( scene ); 6393464ebd5Sriastradh } 640cdc920a0Smrg} 641