diff options
Diffstat (limited to 'src/gallium/drivers')
217 files changed, 5798 insertions, 3558 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index 143eca848f1..b6b3a700cda 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -100,8 +100,8 @@ static const struct debug_named_value cell_debug_flags[] = { static unsigned int cell_is_resource_referenced( struct pipe_context *pipe, - struct pipe_resource *texture, - unsigned face, unsigned level) + struct pipe_resource *texture, + unsigned level, int layer) { /** * FIXME: Optimize. diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index b3042df7792..946a7050e5f 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -304,47 +304,34 @@ untwiddle_image_uint(uint w, uint h, uint tile_size, uint *dst, static struct pipe_surface * -cell_get_tex_surface(struct pipe_screen *screen, - struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned usage) +cell_create_surface(struct pipe_context *ctx, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { struct cell_resource *ct = cell_resource(pt); struct pipe_surface *ps; + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); ps = CALLOC_STRUCT(pipe_surface); if (ps) { pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = u_minify(pt->width0, level); - ps->height = u_minify(pt->height0, level); - ps->offset = ct->level_offset[level]; + ps->format = surf_tmpl->format; + ps->context = ctx; + ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); + ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); /* XXX may need to override usage flags (see sp_texture.c) */ - ps->usage = usage; - ps->face = face; - ps->level = level; - ps->zslice = zslice; - - if (pt->target == PIPE_TEXTURE_CUBE) { - unsigned h_tile = align(ps->height, TILE_SIZE); - ps->offset += face * util_format_get_nblocksy(ps->format, h_tile) * ct->stride[level]; - } - else if (pt->target == PIPE_TEXTURE_3D) { - unsigned h_tile = align(ps->height, TILE_SIZE); - ps->offset += zslice * util_format_get_nblocksy(ps->format, h_tile) * ct->stride[level]; - } - else { - assert(face == 0); - assert(zslice == 0); - } + ps->usage = surf_tmpl->usage; + ps->u.tex.level = surf_tmpl->u.tex.level; + ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; + ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; } return ps; } static void -cell_tex_surface_destroy(struct pipe_surface *surf) +cell_surface_destroy(struct pipe_context *ctx, struct pipe_surface *surf) { pipe_resource_reference(&surf->texture, NULL); FREE(surf); @@ -358,44 +345,39 @@ cell_tex_surface_destroy(struct pipe_surface *surf) */ static struct pipe_transfer * cell_get_transfer(struct pipe_context *ctx, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct cell_resource *ct = cell_resource(resource); struct cell_transfer *ctrans; enum pipe_format format = resource->format; assert(resource); - assert(sr.level <= resource->last_level); + assert(level <= resource->last_level); /* make sure the requested region is in the image bounds */ - assert(box->x + box->width <= u_minify(resource->width0, sr.level)); - assert(box->y + box->height <= u_minify(resource->height0, sr.level)); - assert(box->z + box->depth <= u_minify(resource->depth0, sr.level)); + assert(box->x + box->width <= u_minify(resource->width0, level)); + assert(box->y + box->height <= u_minify(resource->height0, level)); + assert(box->z + box->depth <= (u_minify(resource->depth0, level) + resource->array_size - 1)); ctrans = CALLOC_STRUCT(cell_transfer); if (ctrans) { struct pipe_transfer *pt = &ctrans->base; pipe_resource_reference(&pt->resource, resource); - pt->sr = sr; + pt->level = level; pt->usage = usage; pt->box = *box; - pt->stride = ct->stride[sr.level]; + pt->stride = ct->stride[level]; - ctrans->offset = ct->level_offset[sr.level]; + ctrans->offset = ct->level_offset[level]; - if (resource->target == PIPE_TEXTURE_CUBE) { - unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE); - ctrans->offset += sr.face * util_format_get_nblocksy(format, h_tile) * pt->stride; - } - else if (resource->target == PIPE_TEXTURE_3D) { - unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE); + if (resource->target == PIPE_TEXTURE_CUBE || resource->target == PIPE_TEXTURE_3D) { + unsigned h_tile = align(u_minify(resource->height0, level), TILE_SIZE); ctrans->offset += box->z * util_format_get_nblocksy(format, h_tile) * pt->stride; } else { - assert(sr.face == 0); assert(box->z == 0); } @@ -439,7 +421,7 @@ cell_transfer_map(struct pipe_context *ctx, struct pipe_transfer *transfer) /* Better test would be resource->is_linear */ if (transfer->resource->target != PIPE_BUFFER) { - const uint level = ctrans->base.sr.level; + const uint level = ctrans->base.level; const uint texWidth = u_minify(pt->width0, level); const uint texHeight = u_minify(pt->height0, level); unsigned size; @@ -500,7 +482,7 @@ cell_transfer_unmap(struct pipe_context *ctx, struct cell_transfer *ctrans = cell_transfer(transfer); struct pipe_resource *pt = transfer->resource; struct cell_resource *ct = cell_resource(pt); - const uint level = ctrans->base.sr.level; + const uint level = ctrans->base.level; const uint texWidth = u_minify(pt->width0, level); const uint texHeight = u_minify(pt->height0, level); const uint stride = ct->stride[level]; @@ -548,12 +530,13 @@ cell_transfer_unmap(struct pipe_context *ctx, */ static void cell_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_surface *surface, + struct pipe_resource *resource, + unsigned level, unsigned layer, void *context_private) { struct cell_screen *screen = cell_screen(_screen); struct sw_winsys *winsys = screen->winsys; - struct cell_resource *ct = cell_resource(surface->texture); + struct cell_resource *ct = cell_resource(resource); if (!ct->dt) return; @@ -564,10 +547,10 @@ cell_flush_frontbuffer(struct pipe_screen *_screen, unsigned *map = winsys->displaytarget_map(winsys, ct->dt, (PIPE_TRANSFER_READ | PIPE_TRANSFER_WRITE)); - unsigned *src = (unsigned *)(ct->data + ct->level_offset[surface->level]); + unsigned *src = (unsigned *)(ct->data + ct->level_offset[level]); - untwiddle_image_uint(surface->width, - surface->height, + untwiddle_image_uint(u_minify(resource->width0, level), + u_minify(resource->height0, level), TILE_SIZE, map, ct->dt_stride, @@ -605,6 +588,7 @@ cell_user_buffer_create(struct pipe_screen *screen, buffer->base.width0 = bytes; buffer->base.height0 = 1; buffer->base.depth0 = 1; + buffer->base.array_size = 1; buffer->userBuffer = TRUE; buffer->data = ptr; @@ -641,9 +625,6 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen) screen->resource_get_handle = cell_resource_get_handle; screen->user_buffer_create = cell_user_buffer_create; - screen->get_tex_surface = cell_get_tex_surface; - screen->tex_surface_destroy = cell_tex_surface_destroy; - screen->flush_frontbuffer = cell_flush_frontbuffer; } @@ -657,4 +638,7 @@ cell_init_texture_transfer_funcs(struct cell_context *cell) cell->pipe.transfer_flush_region = u_default_transfer_flush_region; cell->pipe.transfer_inline_write = u_default_transfer_inline_write; + + cell->pipe.create_surface = cell_create_surface; + cell->pipe.surface_destroy = cell_surface_destroy; } diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c index ec3609291e9..e4d289c8a4d 100644 --- a/src/gallium/drivers/failover/fo_context.c +++ b/src/gallium/drivers/failover/fo_context.c @@ -89,14 +89,14 @@ static void failover_draw_vbo( struct pipe_context *pipe, static unsigned int failover_is_resource_referenced( struct pipe_context *_pipe, - struct pipe_resource *resource, - unsigned face, unsigned level) + struct pipe_resource *resource, + unsigned level, int layer) { struct failover_context *failover = failover_context( _pipe ); struct pipe_context *pipe = (failover->mode == FO_HW) ? failover->hw : failover->sw; - return pipe->is_resource_referenced(pipe, resource, face, level); + return pipe->is_resource_referenced(pipe, resource, level, layer); } struct pipe_context *failover_create( struct pipe_context *hw, @@ -137,10 +137,10 @@ struct pipe_context *failover_create( struct pipe_context *hw, failover->pipe.resource_copy_region = hw->resource_copy_region; #if 0 - failover->pipe.texture_create = hw->texture_create; - failover->pipe.texture_destroy = hw->texture_destroy; - failover->pipe.get_tex_surface = hw->get_tex_surface; - failover->pipe.texture_update = hw->texture_update; + failover->pipe.resource_create = hw->resource_create; + failover->pipe.resource_destroy = hw->resource_destroy; + failover->pipe.create_surface = hw->create_surface; + failover->pipe.surface_destroy = hw->surface_destroy; #endif failover->pipe.flush = hw->flush; diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c index 50f66079c2a..a572ad22bd0 100644 --- a/src/gallium/drivers/galahad/glhd_context.c +++ b/src/gallium/drivers/galahad/glhd_context.c @@ -662,17 +662,13 @@ galahad_set_index_buffer(struct pipe_context *_pipe, static void galahad_resource_copy_region(struct pipe_context *_pipe, struct pipe_resource *_dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *_src, - struct pipe_subresource subsrc, - unsigned srcx, - unsigned srcy, - unsigned srcz, - unsigned width, - unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { struct galahad_context *glhd_pipe = galahad_context(_pipe); struct galahad_resource *glhd_resource_dst = galahad_resource(_dst); @@ -689,17 +685,13 @@ galahad_resource_copy_region(struct pipe_context *_pipe, pipe->resource_copy_region(pipe, dst, - subdst, + dst_level, dstx, dsty, dstz, src, - subsrc, - srcx, - srcy, - srcz, - width, - height); + src_level, + src_box); } static void @@ -781,8 +773,8 @@ galahad_flush(struct pipe_context *_pipe, static unsigned int galahad_is_resource_referenced(struct pipe_context *_pipe, struct pipe_resource *_resource, - unsigned face, - unsigned level) + unsigned level, + int layer) { struct galahad_context *glhd_pipe = galahad_context(_pipe); struct galahad_resource *glhd_resource = galahad_resource(_resource); @@ -791,8 +783,8 @@ galahad_is_resource_referenced(struct pipe_context *_pipe, return pipe->is_resource_referenced(pipe, resource, - face, - level); + level, + layer); } static struct pipe_sampler_view * @@ -823,10 +815,40 @@ galahad_context_sampler_view_destroy(struct pipe_context *_pipe, galahad_sampler_view(_view)); } +static struct pipe_surface * +galahad_context_create_surface(struct pipe_context *_pipe, + struct pipe_resource *_resource, + const struct pipe_surface *templ) +{ + struct galahad_context *glhd_context = galahad_context(_pipe); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_context *pipe = glhd_context->pipe; + struct pipe_resource *resource = glhd_resource->resource; + struct pipe_surface *result; + + result = pipe->create_surface(pipe, + resource, + templ); + + if (result) + return galahad_surface_create(glhd_context, glhd_resource, result); + return NULL; +} + +static void +galahad_context_surface_destroy(struct pipe_context *_pipe, + struct pipe_surface *_surface) +{ + galahad_surface_destroy(galahad_context(_pipe), + galahad_surface(_surface)); +} + + + static struct pipe_transfer * galahad_context_get_transfer(struct pipe_context *_context, struct pipe_resource *_resource, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box) { @@ -838,7 +860,7 @@ galahad_context_get_transfer(struct pipe_context *_context, result = context->get_transfer(context, resource, - sr, + level, usage, box); @@ -915,7 +937,7 @@ galahad_context_transfer_unmap(struct pipe_context *_context, static void galahad_context_transfer_inline_write(struct pipe_context *_context, struct pipe_resource *_resource, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box, const void *data, @@ -929,7 +951,7 @@ galahad_context_transfer_inline_write(struct pipe_context *_context, context->transfer_inline_write(context, resource, - sr, + level, usage, box, data, @@ -1004,6 +1026,8 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) glhd_pipe->base.is_resource_referenced = galahad_is_resource_referenced; glhd_pipe->base.create_sampler_view = galahad_context_create_sampler_view; glhd_pipe->base.sampler_view_destroy = galahad_context_sampler_view_destroy; + glhd_pipe->base.create_surface = galahad_context_create_surface; + glhd_pipe->base.surface_destroy = galahad_context_surface_destroy; glhd_pipe->base.get_transfer = galahad_context_get_transfer; glhd_pipe->base.transfer_destroy = galahad_context_transfer_destroy; glhd_pipe->base.transfer_map = galahad_context_transfer_map; diff --git a/src/gallium/drivers/galahad/glhd_objects.c b/src/gallium/drivers/galahad/glhd_objects.c index 6c5a21ae704..b50d85655e8 100644 --- a/src/gallium/drivers/galahad/glhd_objects.c +++ b/src/gallium/drivers/galahad/glhd_objects.c @@ -71,7 +71,8 @@ galahad_resource_destroy(struct galahad_resource *glhd_resource) struct pipe_surface * -galahad_surface_create(struct galahad_resource *glhd_resource, +galahad_surface_create(struct galahad_context *glhd_context, + struct galahad_resource *glhd_resource, struct pipe_surface *surface) { struct galahad_surface *glhd_surface; @@ -100,10 +101,11 @@ error: } void -galahad_surface_destroy(struct galahad_surface *glhd_surface) +galahad_surface_destroy(struct galahad_context *glhd_context, + struct galahad_surface *glhd_surface) { pipe_resource_reference(&glhd_surface->base.texture, NULL); - pipe_surface_reference(&glhd_surface->surface, NULL); + glhd_context->pipe->surface_destroy(glhd_context->pipe, glhd_surface->surface); FREE(glhd_surface); } diff --git a/src/gallium/drivers/galahad/glhd_objects.h b/src/gallium/drivers/galahad/glhd_objects.h index dc74c5bebc9..13dc7485887 100644 --- a/src/gallium/drivers/galahad/glhd_objects.h +++ b/src/gallium/drivers/galahad/glhd_objects.h @@ -149,11 +149,13 @@ void galahad_resource_destroy(struct galahad_resource *glhd_resource); struct pipe_surface * -galahad_surface_create(struct galahad_resource *glhd_resource, +galahad_surface_create(struct galahad_context *glhd_context, + struct galahad_resource *glhd_resource, struct pipe_surface *surface); void -galahad_surface_destroy(struct galahad_surface *glhd_surface); +galahad_surface_destroy(struct galahad_context *glhd_context, + struct galahad_surface *glhd_surface); struct pipe_sampler_view * galahad_sampler_view_create(struct galahad_context *glhd_context, diff --git a/src/gallium/drivers/galahad/glhd_screen.c b/src/gallium/drivers/galahad/glhd_screen.c index b6cc41d908b..b4825bef66d 100644 --- a/src/gallium/drivers/galahad/glhd_screen.c +++ b/src/gallium/drivers/galahad/glhd_screen.c @@ -223,39 +223,6 @@ galahad_screen_resource_destroy(struct pipe_screen *screen, galahad_resource_destroy(galahad_resource(_resource)); } -static struct pipe_surface * -galahad_screen_get_tex_surface(struct pipe_screen *_screen, - struct pipe_resource *_resource, - unsigned face, - unsigned level, - unsigned zslice, - unsigned usage) -{ - struct galahad_screen *glhd_screen = galahad_screen(_screen); - struct galahad_resource *glhd_resource = galahad_resource(_resource); - struct pipe_screen *screen = glhd_screen->screen; - struct pipe_resource *resource = glhd_resource->resource; - struct pipe_surface *result; - - result = screen->get_tex_surface(screen, - resource, - face, - level, - zslice, - usage); - - if (result) - return galahad_surface_create(glhd_resource, result); - return NULL; -} - -static void -galahad_screen_tex_surface_destroy(struct pipe_surface *_surface) -{ - galahad_surface_destroy(galahad_surface(_surface)); -} - - static struct pipe_resource * galahad_screen_user_buffer_create(struct pipe_screen *_screen, @@ -281,16 +248,18 @@ galahad_screen_user_buffer_create(struct pipe_screen *_screen, static void galahad_screen_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_surface *_surface, + struct pipe_resource *_resource, + unsigned level, unsigned layer, void *context_private) { struct galahad_screen *glhd_screen = galahad_screen(_screen); - struct galahad_surface *glhd_surface = galahad_surface(_surface); + struct galahad_resource *glhd_resource = galahad_resource(_resource); struct pipe_screen *screen = glhd_screen->screen; - struct pipe_surface *surface = glhd_surface->surface; + struct pipe_resource *resource = glhd_resource->resource; screen->flush_frontbuffer(screen, - surface, + resource, + level, layer, context_private); } @@ -360,8 +329,6 @@ galahad_screen_create(struct pipe_screen *screen) glhd_screen->base.resource_from_handle = galahad_screen_resource_from_handle; glhd_screen->base.resource_get_handle = galahad_screen_resource_get_handle; glhd_screen->base.resource_destroy = galahad_screen_resource_destroy; - glhd_screen->base.get_tex_surface = galahad_screen_get_tex_surface; - glhd_screen->base.tex_surface_destroy = galahad_screen_tex_surface_destroy; glhd_screen->base.user_buffer_create = galahad_screen_user_buffer_create; glhd_screen->base.flush_frontbuffer = galahad_screen_flush_frontbuffer; glhd_screen->base.fence_reference = galahad_screen_fence_reference; diff --git a/src/gallium/drivers/i915/TODO b/src/gallium/drivers/i915/TODO new file mode 100644 index 00000000000..94c428bebf8 --- /dev/null +++ b/src/gallium/drivers/i915/TODO @@ -0,0 +1,25 @@ +Random list of problems with i915g: + +- Dies with BadDrawable on GLXFBconfig changes/destruction. Makes piglit totally + unusable :( Upgrading xserver helped here, it doesn't crash anymore. Still + broken, it doesn't update the viewport/get new buffers. + +- Tends to hang the chip after a few minutes of openarena. Looks tiling related, + at the last frame rendered has tiling corruption over the complete frame. + +- Kills the chip in 3D_PRIMITIVE LINELIST with mesa-demos/fbotexture in + wireframe mode. + +- Tiling is funny: If unlucky, it renders/samples all black. No clue yet what's + going on. Seems to depend on tiny details like whethever the sampler + relocation is fenced/unfenced (broken _with_ fenced reloc using tiling bits!). + +- Y-tiling is even more fun. i915c doesn't use it, maybe there's a reason? + Texture sampling from Y-tiled buffers seems to work, though (save above + problems). + +- Need to validate buffers before usage. Currently do_exec on the batchbuffer + can fail with -ENOSPC. + +Other bugs can be found here: +https://bugs.freedesktop.org/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&component=Drivers/Gallium/i915g diff --git a/src/gallium/drivers/i915/i915_batch.h b/src/gallium/drivers/i915/i915_batch.h index c411b84ccd4..6e93da76209 100644 --- a/src/gallium/drivers/i915/i915_batch.h +++ b/src/gallium/drivers/i915/i915_batch.h @@ -38,7 +38,10 @@ i915_winsys_batchbuffer_dword(i915->batch, dword) #define OUT_RELOC(buf, usage, offset) \ - i915_winsys_batchbuffer_reloc(i915->batch, buf, usage, offset) + i915_winsys_batchbuffer_reloc(i915->batch, buf, usage, offset, false) + +#define OUT_RELOC_FENCED(buf, usage, offset) \ + i915_winsys_batchbuffer_reloc(i915->batch, buf, usage, offset, true) #define FLUSH_BATCH(fence) \ i915_flush(i915, fence) diff --git a/src/gallium/drivers/i915/i915_batchbuffer.h b/src/gallium/drivers/i915/i915_batchbuffer.h index c1cd314e7b8..d92b2ccb31e 100644 --- a/src/gallium/drivers/i915/i915_batchbuffer.h +++ b/src/gallium/drivers/i915/i915_batchbuffer.h @@ -29,42 +29,47 @@ #define I915_BATCHBUFFER_H #include "i915_winsys.h" +#include "util/u_debug.h" struct i915_context; +static INLINE size_t +i915_winsys_batchbuffer_space(struct i915_winsys_batchbuffer *batch) +{ + return batch->size - (batch->ptr - batch->map); +} + static INLINE boolean i915_winsys_batchbuffer_check(struct i915_winsys_batchbuffer *batch, size_t dwords, size_t relocs) { - return dwords * 4 <= batch->size - (batch->ptr - batch->map) && + return dwords * 4 <= i915_winsys_batchbuffer_space(batch) && relocs <= (batch->max_relocs - batch->relocs); } -static INLINE size_t -i915_winsys_batchbuffer_space(struct i915_winsys_batchbuffer *batch) +static INLINE void +i915_winsys_batchbuffer_dword_unchecked(struct i915_winsys_batchbuffer *batch, + unsigned dword) { - return batch->size - (batch->ptr - batch->map); + *(unsigned *)batch->ptr = dword; + batch->ptr += 4; } static INLINE void i915_winsys_batchbuffer_dword(struct i915_winsys_batchbuffer *batch, unsigned dword) { - if (i915_winsys_batchbuffer_space(batch) < 4) - return; - - *(unsigned *)batch->ptr = dword; - batch->ptr += 4; + assert (i915_winsys_batchbuffer_space(batch) >= 4); + i915_winsys_batchbuffer_dword_unchecked(batch, dword); } static INLINE void i915_winsys_batchbuffer_write(struct i915_winsys_batchbuffer *batch, - void *data, - size_t size) + void *data, + size_t size) { - if (i915_winsys_batchbuffer_space(batch) < size) - return; + assert (i915_winsys_batchbuffer_space(batch) >= size); memcpy(data, batch->ptr, size); batch->ptr += size; @@ -74,9 +79,9 @@ static INLINE int i915_winsys_batchbuffer_reloc(struct i915_winsys_batchbuffer *batch, struct i915_winsys_buffer *buffer, enum i915_winsys_buffer_usage usage, - size_t offset) + size_t offset, bool fenced) { - return batch->iws->batchbuffer_reloc(batch, buffer, usage, offset); + return batch->iws->batchbuffer_reloc(batch, buffer, usage, offset, fenced); } #endif diff --git a/src/gallium/drivers/i915/i915_blit.c b/src/gallium/drivers/i915/i915_blit.c index cdf20c0055a..97c25665156 100644 --- a/src/gallium/drivers/i915/i915_blit.c +++ b/src/gallium/drivers/i915/i915_blit.c @@ -74,7 +74,7 @@ i915_fill_blit(struct i915_context *i915, OUT_BATCH(BR13); OUT_BATCH((y << 16) | x); OUT_BATCH(((y + h) << 16) | (x + w)); - OUT_RELOC(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); + OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); OUT_BATCH(color); } @@ -138,8 +138,8 @@ i915_copy_blit(struct i915_context *i915, OUT_BATCH(BR13); OUT_BATCH((dst_y << 16) | dst_x); OUT_BATCH((dst_y2 << 16) | dst_x2); - OUT_RELOC(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); + OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); OUT_BATCH((src_y << 16) | src_x); OUT_BATCH(((int) src_pitch & 0xffff)); - OUT_RELOC(src_buffer, I915_USAGE_2D_SOURCE, src_offset); + OUT_RELOC_FENCED(src_buffer, I915_USAGE_2D_SOURCE, src_offset); } diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index 3ae61d0ea70..d15e1723d83 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -193,8 +193,7 @@ struct i915_velems_state { }; -struct i915_context -{ +struct i915_context { struct pipe_context base; struct i915_winsys *iws; @@ -273,7 +272,7 @@ struct i915_context #define I915_HW_PROGRAM (1<<I915_CACHE_PROGRAM) #define I915_HW_CONSTANTS (1<<I915_CACHE_CONSTANTS) #define I915_HW_IMMEDIATE (1<<(I915_MAX_CACHE+0)) -#define I915_HW_INVARIENT (1<<(I915_MAX_CACHE+1)) +#define I915_HW_INVARIANT (1<<(I915_MAX_CACHE+1)) /*********************************************************************** diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c index 57d3390dea3..87c435a2f36 100644 --- a/src/gallium/drivers/i915/i915_debug.c +++ b/src/gallium/drivers/i915/i915_debug.c @@ -46,10 +46,12 @@ static const struct debug_named_value debug_options[] = { }; unsigned i915_debug = 0; +boolean i915_tiling = TRUE; void i915_debug_init(struct i915_screen *screen) { i915_debug = debug_get_flags_option("I915_DEBUG", debug_options, 0); + i915_tiling = !debug_get_bool_option("I915_NO_TILING", FALSE); } @@ -974,7 +976,7 @@ i915_dump_hardware_dirty(struct i915_context *i915, const char *func) {I915_HW_PROGRAM, "program"}, {I915_HW_CONSTANTS, "constants"}, {I915_HW_IMMEDIATE, "immediate"}, - {I915_HW_INVARIENT, "invarient"}, + {I915_HW_INVARIANT, "invariant"}, {0, NULL}, }; int i; diff --git a/src/gallium/drivers/i915/i915_debug.h b/src/gallium/drivers/i915/i915_debug.h index fa60799d0c5..11af7662f0a 100644 --- a/src/gallium/drivers/i915/i915_debug.h +++ b/src/gallium/drivers/i915/i915_debug.h @@ -46,6 +46,7 @@ struct i915_winsys_batchbuffer; #define DBG_CONSTANTS 0x20 extern unsigned i915_debug; +extern boolean i915_tiling; #ifdef DEBUG static INLINE boolean diff --git a/src/gallium/drivers/i915/i915_prim_vbuf.c b/src/gallium/drivers/i915/i915_prim_vbuf.c index bd046bd9058..baebbc7bae3 100644 --- a/src/gallium/drivers/i915/i915_prim_vbuf.c +++ b/src/gallium/drivers/i915/i915_prim_vbuf.c @@ -172,6 +172,7 @@ i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size) * * Side effects: * Updates hw_offset, sw_offset, index and allocates a new buffer. + * Will set i915->vbo to null on buffer allocation. */ static void i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) @@ -179,8 +180,16 @@ i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) struct i915_context *i915 = i915_render->i915; struct i915_winsys *iws = i915->iws; - if (i915_render->vbo) + if (i915_render->vbo) { iws->buffer_destroy(iws, i915_render->vbo); + /* + * XXX If buffers where referenced then this should be done in + * update_vbo_state but since they arn't and malloc likes to reuse + * memory we need to set it to null + */ + i915->vbo = NULL; + i915_render->vbo = NULL; + } i915->vbo_flushed = 0; @@ -198,7 +207,7 @@ i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) #endif i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, - 64, I915_NEW_VERTEX); + I915_NEW_VERTEX); } /** @@ -726,7 +735,7 @@ i915_vbuf_render_create(struct i915_context *i915) i915_render->pool_fifo = u_fifo_create(6); for (i = 0; i < 6; i++) u_fifo_add(i915_render->pool_fifo, - iws->buffer_create(iws, i915_render->pool_buffer_size, 64, + iws->buffer_create(iws, i915_render->pool_buffer_size, I915_NEW_VERTEX)); #else (void)i; diff --git a/src/gallium/drivers/i915/i915_reg.h b/src/gallium/drivers/i915/i915_reg.h index 04620fec681..5e4e80ddf6b 100644 --- a/src/gallium/drivers/i915/i915_reg.h +++ b/src/gallium/drivers/i915/i915_reg.h @@ -753,7 +753,7 @@ #define MT_COMPRESS_DXT1_RGB (4<<3) #define MS3_USE_FENCE_REGS (1<<2) #define MS3_TILED_SURFACE (1<<1) -#define MS3_TILE_WALK (1<<0) +#define MS3_TILE_WALK_Y (1<<0) #define MS4_PITCH_SHIFT 21 #define MS4_CUBE_FACE_ENA_NEGX (1<<20) @@ -851,6 +851,7 @@ #define MI_FLUSH ((0<<29)|(4<<23)) #define FLUSH_MAP_CACHE (1<<0) #define INHIBIT_FLUSH_RENDER_CACHE (1<<2) +#define MI_NOOP 0 #define CMD_3D (0x3<<29) @@ -973,6 +974,8 @@ #define PCI_CHIP_G33_G 0x29C2 #define PCI_CHIP_Q35_G 0x29B2 #define PCI_CHIP_Q33_G 0x29D2 +#define PCI_CHIP_PINEVIEW_G 0xA001 +#define PCI_CHIP_PINEVIEW_M 0xA011 #endif diff --git a/src/gallium/drivers/i915/i915_resource.h b/src/gallium/drivers/i915/i915_resource.h index 1093e8f41f9..86620e6a123 100644 --- a/src/gallium/drivers/i915/i915_resource.h +++ b/src/gallium/drivers/i915/i915_resource.h @@ -32,6 +32,7 @@ struct i915_screen; #include "util/u_transfer.h" #include "util/u_debug.h" +#include "i915_winsys.h" struct i915_context; @@ -48,29 +49,36 @@ struct i915_buffer { #define I915_MAX_TEXTURE_3D_LEVELS 8 /* max 128x128x128 */ +struct offset_pair { + unsigned short nblocksx; + unsigned short nblocksy; +}; struct i915_texture { struct u_resource b; + /* tiling flags */ + enum i915_winsys_buffer_tile tiling; unsigned stride; unsigned depth_stride; /* per-image on i945? */ unsigned total_nblocksy; - unsigned sw_tiled; /**< tiled with software flags */ - unsigned hw_tiled; /**< tiled with hardware fences */ - unsigned nr_images[I915_MAX_TEXTURE_2D_LEVELS]; /* Explicitly store the offset of each image for each cube face or * depth value. + * + * Array [depth] off offsets. */ - unsigned *image_offset[I915_MAX_TEXTURE_2D_LEVELS]; /**< array [depth] of offsets */ + struct offset_pair *image_offset[I915_MAX_TEXTURE_2D_LEVELS]; /* The data is held here: */ struct i915_winsys_buffer *buffer; }; +unsigned i915_texture_offset(struct i915_texture *tex, + unsigned level, unsigned layer); void i915_init_screen_resource_functions(struct i915_screen *is); void i915_init_resource_functions(struct i915_context *i915); diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c index 0d379497dfc..450203d60a9 100644 --- a/src/gallium/drivers/i915/i915_resource_buffer.c +++ b/src/gallium/drivers/i915/i915_resource_buffer.c @@ -62,7 +62,7 @@ i915_buffer_destroy(struct pipe_screen *screen, static void * i915_buffer_transfer_map( struct pipe_context *pipe, - struct pipe_transfer *transfer ) + struct pipe_transfer *transfer ) { struct i915_buffer *buffer = i915_buffer(transfer->resource); return buffer->data + transfer->box.x; @@ -71,19 +71,19 @@ i915_buffer_transfer_map( struct pipe_context *pipe, static void i915_buffer_transfer_inline_write( struct pipe_context *rm_ctx, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box, - const void *data, - unsigned stride, - unsigned slice_stride) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) { struct i915_buffer *buffer = i915_buffer(resource); memcpy(buffer->data + box->x, - data, - box->width); + data, + box->width); } @@ -115,7 +115,7 @@ i915_buffer_create(struct pipe_screen *screen, buf->b.vtbl = &i915_buffer_vtbl; pipe_reference_init(&buf->b.b.reference, 1); buf->b.b.screen = screen; - + buf->data = MALLOC(template->width0); buf->free_on_destroy = TRUE; @@ -135,7 +135,7 @@ struct pipe_resource * i915_user_buffer_create(struct pipe_screen *screen, void *ptr, unsigned bytes, - unsigned bind) + unsigned bind) { struct i915_buffer *buf = CALLOC_STRUCT(i915_buffer); @@ -152,6 +152,7 @@ i915_user_buffer_create(struct pipe_screen *screen, buf->b.b.width0 = bytes; buf->b.b.height0 = 1; buf->b.b.depth0 = 1; + buf->b.b.array_size = 1; buf->data = ptr; buf->free_on_destroy = FALSE; diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index c5c6179b169..f19106f3414 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -106,6 +106,23 @@ get_pot_stride(enum pipe_format format, unsigned width) return util_next_power_of_two(util_format_get_stride(format, width)); } +static INLINE const char* +get_tiling_string(enum i915_winsys_buffer_tile tile) +{ + switch(tile) { + case I915_TILE_NONE: + return "none"; + case I915_TILE_X: + return "x"; + case I915_TILE_Y: + return "y"; + default: + assert(FALSE); + return "?"; + } +} + + /* * More advanced helper funcs */ @@ -120,28 +137,56 @@ i915_texture_set_level_info(struct i915_texture *tex, assert(!tex->image_offset[level]); tex->nr_images[level] = nr_images; - tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned)); - tex->image_offset[level][0] = 0; + tex->image_offset[level] = MALLOC(nr_images * sizeof(struct offset_pair)); + tex->image_offset[level][0].nblocksx = 0; + tex->image_offset[level][0].nblocksy = 0; +} + +INLINE unsigned i915_texture_offset(struct i915_texture *tex, + unsigned level, unsigned layer) +{ + unsigned x, y; + x = tex->image_offset[level][layer].nblocksx + * util_format_get_blocksize(tex->b.b.format); + y = tex->image_offset[level][layer].nblocksy; + + return y * tex->stride + x; } static void i915_texture_set_image_offset(struct i915_texture *tex, unsigned level, unsigned img, - unsigned x, unsigned y) + unsigned nblocksx, unsigned nblocksy) { /* for the first image and level make sure offset is zero */ - assert(!(img == 0 && level == 0) || (x == 0 && y == 0)); + assert(!(img == 0 && level == 0) || (nblocksx == 0 && nblocksy == 0)); assert(img < tex->nr_images[level]); - tex->image_offset[level][img] = y * tex->stride + x * util_format_get_blocksize(tex->b.b.format); + tex->image_offset[level][img].nblocksx = nblocksx; + tex->image_offset[level][img].nblocksy = nblocksy; #if DEBUG_TEXTURES - debug_printf("%s: %p level %u, img %u (%u, %u) %p\n", __FUNCTION__, - tex, level, img, x, y, - (void*)(uintptr_t)tex->image_offset[level][img]); + debug_printf("%s: %p level %u, img %u (%u, %u)\n", __FUNCTION__, + tex, level, img, x, y); #endif } +static enum i915_winsys_buffer_tile +i915_texture_tiling(struct pipe_resource *pt) +{ + if (!i915_tiling) + return I915_TILE_NONE; + + if (pt->target == PIPE_TEXTURE_1D) + return I915_TILE_NONE; + + if (util_format_is_s3tc(pt->format)) + /* XXX X-tiling might make sense */ + return I915_TILE_NONE; + + return I915_TILE_X; +} + /* * Shared layout functions @@ -163,9 +208,10 @@ i9x5_scanout_layout(struct i915_texture *tex) i915_texture_set_image_offset(tex, 0, 0, 0, 0); if (pt->width0 >= 240) { - tex->stride = get_pot_stride(pt->format, pt->width0); + tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); - tex->hw_tiled = I915_TILE_X; + tex->tiling = I915_TILE_X; + /* special case for cursors */ } else if (pt->width0 == 64 && pt->height0 == 64) { tex->stride = get_pot_stride(pt->format, pt->width0); tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); @@ -200,9 +246,9 @@ i9x5_display_target_layout(struct i915_texture *tex) i915_texture_set_level_info(tex, 0, 1); i915_texture_set_image_offset(tex, 0, 0, 0, 0); - tex->stride = get_pot_stride(pt->format, pt->width0); + tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); - tex->hw_tiled = I915_TILE_X; + tex->tiling = I915_TILE_X; #if DEBUG_TEXTURE debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, @@ -357,6 +403,8 @@ i915_texture_layout(struct i915_texture * tex) { struct pipe_resource *pt = &tex->b.b; + tex->tiling = i915_texture_tiling(pt); + switch (pt->target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: @@ -603,6 +651,8 @@ i945_texture_layout(struct i915_texture * tex) { struct pipe_resource *pt = &tex->b.b; + tex->tiling = i915_texture_tiling(pt); + switch (pt->target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: @@ -650,7 +700,7 @@ i915_texture_get_handle(struct pipe_screen * screen, static void i915_texture_destroy(struct pipe_screen *screen, - struct pipe_resource *pt) + struct pipe_resource *pt) { struct i915_texture *tex = i915_texture(pt); struct i915_winsys *iws = i915_screen(screen)->iws; @@ -667,10 +717,10 @@ i915_texture_destroy(struct pipe_screen *screen, static struct pipe_transfer * i915_texture_get_transfer(struct pipe_context *context, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct i915_texture *tex = i915_texture(resource); struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer); @@ -678,37 +728,31 @@ i915_texture_get_transfer(struct pipe_context *context, return NULL; transfer->resource = resource; - transfer->sr = sr; + transfer->level = level; transfer->usage = usage; transfer->box = *box; transfer->stride = tex->stride; + /* FIXME: layer_stride */ return transfer; } - static void * i915_texture_transfer_map(struct pipe_context *pipe, - struct pipe_transfer *transfer) + struct pipe_transfer *transfer) { struct pipe_resource *resource = transfer->resource; struct i915_texture *tex = i915_texture(resource); struct i915_winsys *iws = i915_screen(pipe->screen)->iws; - struct pipe_subresource sr = transfer->sr; struct pipe_box *box = &transfer->box; enum pipe_format format = resource->format; unsigned offset; char *map; - if (resource->target == PIPE_TEXTURE_CUBE) { - offset = tex->image_offset[sr.level][sr.face]; - } else if (resource->target == PIPE_TEXTURE_3D) { - offset = tex->image_offset[sr.level][box->z]; - } else { - offset = tex->image_offset[sr.level][0]; - assert(sr.face == 0); + if (resource->target != PIPE_TEXTURE_3D && + resource->target != PIPE_TEXTURE_CUBE) assert(box->z == 0); - } + offset = i915_texture_offset(tex, transfer->level, box->z); map = iws->buffer_map(iws, tex->buffer, (transfer->usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE); @@ -754,7 +798,6 @@ i915_texture_create(struct pipe_screen *screen, struct i915_screen *is = i915_screen(screen); struct i915_winsys *iws = is->iws; struct i915_texture *tex = CALLOC_STRUCT(i915_texture); - size_t tex_size; unsigned buf_usage = 0; if (!tex) @@ -773,8 +816,6 @@ i915_texture_create(struct pipe_screen *screen, goto fail; } - tex_size = tex->stride * tex->total_nblocksy; - /* for scanouts and cursors, cursors arn't scanouts */ /* XXX: use a custom flag for cursors, don't rely on magically @@ -785,28 +826,15 @@ i915_texture_create(struct pipe_screen *screen, else buf_usage = I915_NEW_TEXTURE; - tex->buffer = iws->buffer_create(iws, tex_size, 64, buf_usage); + tex->buffer = iws->buffer_create_tiled(iws, &tex->stride, tex->total_nblocksy, + &tex->tiling, buf_usage); if (!tex->buffer) goto fail; - /* setup any hw fences */ - if (tex->hw_tiled) { - assert(tex->sw_tiled == I915_TILE_NONE); - iws->buffer_set_fence_reg(iws, tex->buffer, tex->stride, tex->hw_tiled); - } - - -#if 0 - void *ptr = ws->buffer_map(ws, tex->buffer, - PIPE_BUFFER_USAGE_CPU_WRITE); - memset(ptr, 0x80, tex_size); - ws->buffer_unmap(ws, tex->buffer); -#endif - - I915_DBG(DBG_TEXTURE, "%s: %p size %u, stride %u, blocks (%u, %u)\n", __func__, - tex, (unsigned int)tex_size, tex->stride, + I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", __func__, + tex, tex->stride, tex->stride / util_format_get_blocksize(tex->b.b.format), - tex->total_nblocksy); + tex->total_nblocksy, get_tiling_string(tex->tiling)); return &tex->b.b; @@ -825,10 +853,11 @@ i915_texture_from_handle(struct pipe_screen * screen, struct i915_winsys *iws = is->iws; struct i915_winsys_buffer *buffer; unsigned stride; + enum i915_winsys_buffer_tile tiling; assert(screen); - buffer = iws->buffer_from_handle(iws, whandle, &stride); + buffer = iws->buffer_from_handle(iws, whandle, &tiling, &stride); /* Only supports one type */ if ((template->target != PIPE_TEXTURE_2D && @@ -848,6 +877,7 @@ i915_texture_from_handle(struct pipe_screen * screen, tex->b.b.screen = screen; tex->stride = stride; + tex->tiling = tiling; tex->total_nblocksy = align_nblocksy(tex->b.b.format, tex->b.b.height0, 8); i915_texture_set_level_info(tex, 0, 1); @@ -855,10 +885,10 @@ i915_texture_from_handle(struct pipe_screen * screen, tex->buffer = buffer; - I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%ux%u)\n", __func__, + I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", __func__, tex, tex->stride, tex->stride / util_format_get_blocksize(tex->b.b.format), - tex->total_nblocksy); + tex->total_nblocksy, get_tiling_string(tex->tiling)); return &tex->b.b; } diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index 312847fba9e..f66478e729c 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -83,6 +83,12 @@ i915_get_name(struct pipe_screen *screen) case PCI_CHIP_Q33_G: chipset = "Q33"; break; + case PCI_CHIP_PINEVIEW_G: + chipset = "Pineview G"; + break; + case PCI_CHIP_PINEVIEW_M: + chipset = "Pineview M"; + break; default: chipset = "unknown"; break; @@ -183,6 +189,8 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; default: assert(0); return 0; @@ -225,10 +233,6 @@ i915_is_format_supported(struct pipe_screen *screen, static const enum pipe_format tex_supported[] = { PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_B8G8R8X8_UNORM, - PIPE_FORMAT_R8G8B8A8_UNORM, -#if 0 - PIPE_FORMAT_R8G8B8X8_UNORM, -#endif PIPE_FORMAT_B5G6R5_UNORM, PIPE_FORMAT_L8_UNORM, PIPE_FORMAT_A8_UNORM, @@ -351,6 +355,8 @@ i915_screen_create(struct i915_winsys *iws) case PCI_CHIP_G33_G: case PCI_CHIP_Q33_G: case PCI_CHIP_Q35_G: + case PCI_CHIP_PINEVIEW_G: + case PCI_CHIP_PINEVIEW_M: is->is_i945 = TRUE; break; @@ -381,7 +387,6 @@ i915_screen_create(struct i915_winsys *iws) is->base.fence_finish = i915_fence_finish; i915_init_screen_resource_functions(is); - i915_init_screen_surface_functions(is); i915_debug_init(is); diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index bd059d5716c..86c02976495 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -86,6 +86,22 @@ framebuffer_size(const struct pipe_framebuffer_state *fb, } } +static inline uint32_t +buf_3d_tiling_bits(enum i915_winsys_buffer_tile tiling) +{ + uint32_t tiling_bits = 0; + + switch (tiling) { + case I915_TILE_Y: + tiling_bits |= BUF_3D_TILE_WALK_Y; + case I915_TILE_X: + tiling_bits |= BUF_3D_TILED_SURFACE; + case I915_TILE_NONE: + break; + } + + return tiling_bits; +} /* Push the state into the sarea and/or texture memory. */ @@ -126,7 +142,7 @@ i915_emit_hardware_state(struct i915_context *i915 ) save_relocs = i915->batch->relocs; /* 14 dwords, 0 relocs */ - if (i915->hardware_dirty & I915_HW_INVARIENT) + if (i915->hardware_dirty & I915_HW_INVARIANT) { OUT_BATCH(_3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | @@ -220,46 +236,39 @@ i915_emit_hardware_state(struct i915_context *i915 ) struct pipe_surface *depth_surface = i915->framebuffer.zsbuf; if (cbuf_surface) { - unsigned ctile = BUF_3D_USE_FENCE; struct i915_texture *tex = i915_texture(cbuf_surface->texture); assert(tex); - if (tex && tex->sw_tiled) { - ctile = BUF_3D_TILED_SURFACE; - } - OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(tex->stride) | /* pitch in bytes */ - ctile); + buf_3d_tiling_bits(tex->tiling)); OUT_RELOC(tex->buffer, I915_USAGE_RENDER, - cbuf_surface->offset); + 0); } /* What happens if no zbuf?? */ if (depth_surface) { - unsigned ztile = BUF_3D_USE_FENCE; struct i915_texture *tex = i915_texture(depth_surface->texture); + unsigned offset = i915_texture_offset(tex, depth_surface->u.tex.level, + depth_surface->u.tex.first_layer); assert(tex); - - if (tex && tex->sw_tiled) { - ztile = BUF_3D_TILED_SURFACE; - } + assert(offset == 0); OUT_BATCH(_3DSTATE_BUF_INFO_CMD); assert(tex); OUT_BATCH(BUF_3D_ID_DEPTH | BUF_3D_PITCH(tex->stride) | /* pitch in bytes */ - ztile); + buf_3d_tiling_bits(tex->tiling)); OUT_RELOC(tex->buffer, I915_USAGE_RENDER, - depth_surface->offset); + 0); } { @@ -301,12 +310,11 @@ i915_emit_hardware_state(struct i915_context *i915 ) if (enabled & (1 << unit)) { struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture); struct i915_winsys_buffer *buf = texture->buffer; - uint offset = 0; assert(buf); count++; - OUT_RELOC(buf, I915_USAGE_SAMPLER, offset); + OUT_RELOC(buf, I915_USAGE_SAMPLER, 0); OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */ OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */ } @@ -399,18 +407,33 @@ i915_emit_hardware_state(struct i915_context *i915 ) #if 01 /* drawing surface size */ /* 6 dwords, 0 relocs */ + if (i915->hardware_dirty & I915_HW_STATIC) { uint w, h; - boolean k = framebuffer_size(&i915->framebuffer, &w, &h); - (void)k; - assert(k); + struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0]; + struct i915_texture *tex = i915_texture(cbuf_surface->texture); + unsigned x, y; + int layer; + uint32_t draw_offset; + boolean ret; + + ret = framebuffer_size(&i915->framebuffer, &w, &h); + assert(ret); + + layer = cbuf_surface->u.tex.first_layer; + + x = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksx; + y = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksy; + + draw_offset = x | (y << 16); + /* XXX flush only required when the draw_offset changes! */ + OUT_BATCH(MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE); OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(((w - 1) & 0xffff) | ((h - 1) << 16)); - OUT_BATCH(0); - OUT_BATCH(0); + OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS); + OUT_BATCH(draw_offset); + OUT_BATCH((w - 1 + x) | ((h - 1 + y) << 16)); + OUT_BATCH(draw_offset); } #endif diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index 4667e0b78d4..916cb767536 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -243,6 +243,23 @@ static uint translate_texture_format(enum pipe_format pipeFormat) } } +static inline uint32_t +ms3_tiling_bits(enum i915_winsys_buffer_tile tiling) +{ + uint32_t tiling_bits = 0; + + switch (tiling) { + case I915_TILE_Y: + tiling_bits |= MS3_TILE_WALK_Y; + case I915_TILE_X: + tiling_bits |= MS3_TILED_SURFACE; + case I915_TILE_NONE: + break; + } + + return tiling_bits; +} + static void update_map(struct i915_context *i915, uint unit, const struct i915_texture *tex, @@ -254,7 +271,6 @@ static void update_map(struct i915_context *i915, const uint width = pt->width0, height = pt->height0, depth = pt->depth0; const uint num_levels = pt->last_level; unsigned max_lod = num_levels * 4; - unsigned tiled = MS3_USE_FENCE_REGS; assert(tex); assert(width); @@ -267,17 +283,12 @@ static void update_map(struct i915_context *i915, assert(format); assert(pitch); - if (tex->sw_tiled) { - assert(!((pitch - 1) & pitch)); - tiled = MS3_TILED_SURFACE; - } - /* MS3 state */ state[0] = (((height - 1) << MS3_HEIGHT_SHIFT) | ((width - 1) << MS3_WIDTH_SHIFT) | format - | tiled); + | ms3_tiling_bits(tex->tiling)); /* * XXX When min_filter != mag_filter and there's just one mipmap level, diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c index f40876e708e..becc6e93c2d 100644 --- a/src/gallium/drivers/i915/i915_surface.c +++ b/src/gallium/drivers/i915/i915_surface.c @@ -43,11 +43,10 @@ */ static void i915_surface_copy(struct pipe_context *pipe, - struct pipe_resource *dst, struct pipe_subresource subdst, + struct pipe_resource *dst, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource *src, struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + struct pipe_resource *src, unsigned src_level, + const struct pipe_box *src_box) { struct i915_texture *dst_tex = i915_texture(dst); struct i915_texture *src_tex = i915_texture(src); @@ -55,29 +54,17 @@ i915_surface_copy(struct pipe_context *pipe, struct pipe_resource *spt = &src_tex->b.b; unsigned dst_offset, src_offset; /* in bytes */ - if (dst->target == PIPE_TEXTURE_CUBE) { - dst_offset = dst_tex->image_offset[subdst.level][subdst.face]; - } - else if (dst->target == PIPE_TEXTURE_3D) { - dst_offset = dst_tex->image_offset[subdst.level][dstz]; - } - else { - dst_offset = dst_tex->image_offset[subdst.level][0]; - assert(subdst.face == 0); + /* XXX cannot copy 3d regions at this time */ + assert(src_box->depth == 1); + if (dst->target != PIPE_TEXTURE_CUBE && + dst->target != PIPE_TEXTURE_3D) assert(dstz == 0); - } - if (src->target == PIPE_TEXTURE_CUBE) { - src_offset = src_tex->image_offset[subsrc.level][subsrc.face]; - } - else if (src->target == PIPE_TEXTURE_3D) { - src_offset = src_tex->image_offset[subsrc.level][srcz]; - } - else { - src_offset = src_tex->image_offset[subsrc.level][0]; - assert(subsrc.face == 0); - assert(srcz == 0); - } + dst_offset = i915_texture_offset(dst_tex, dst_level, dstz); + if (src->target != PIPE_TEXTURE_CUBE && + src->target != PIPE_TEXTURE_3D) + assert(src_box->z == 0); + src_offset = i915_texture_offset(src_tex, src_level, src_box->z); assert( dst != src ); assert( util_format_get_blocksize(dpt->format) == util_format_get_blocksize(spt->format) ); @@ -90,7 +77,8 @@ i915_surface_copy(struct pipe_context *pipe, util_format_get_blocksize(dpt->format), (unsigned short) src_tex->stride, src_tex->buffer, src_offset, (unsigned short) dst_tex->stride, dst_tex->buffer, dst_offset, - (short) srcx, (short) srcy, (short) dstx, (short) dsty, (short) width, (short) height ); + (short) src_box->x, (short) src_box->y, (short) dstx, (short) dsty, + (short) src_box->width, (short) src_box->height ); } @@ -104,6 +92,7 @@ i915_clear_render_target(struct pipe_context *pipe, struct i915_texture *tex = i915_texture(dst->texture); struct pipe_resource *pt = &tex->b.b; union util_color uc; + unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer); assert(util_format_get_blockwidth(pt->format) == 1); assert(util_format_get_blockheight(pt->format) == 1); @@ -113,7 +102,7 @@ i915_clear_render_target(struct pipe_context *pipe, util_format_get_blocksize(pt->format), XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB, (unsigned short) tex->stride, - tex->buffer, dst->offset, + tex->buffer, offset, (short) dstx, (short) dsty, (short) width, (short) height, uc.ui ); @@ -132,6 +121,7 @@ i915_clear_depth_stencil(struct pipe_context *pipe, struct pipe_resource *pt = &tex->b.b; unsigned packedds; unsigned mask = 0; + unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer); assert(util_format_get_blockwidth(pt->format) == 1); assert(util_format_get_blockheight(pt->format) == 1); @@ -151,7 +141,7 @@ i915_clear_depth_stencil(struct pipe_context *pipe, util_format_get_blocksize(pt->format), mask, (unsigned short) tex->stride, - tex->buffer, dst->offset, + tex->buffer, offset, (short) dstx, (short) dsty, (short) width, (short) height, packedds ); @@ -163,42 +153,37 @@ i915_clear_depth_stencil(struct pipe_context *pipe, static struct pipe_surface * -i915_get_tex_surface(struct pipe_screen *screen, - struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) +i915_create_surface(struct pipe_context *ctx, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { - struct i915_texture *tex = i915_texture(pt); struct pipe_surface *ps; - unsigned offset; /* in bytes */ - if (pt->target == PIPE_TEXTURE_CUBE) { - offset = tex->image_offset[level][face]; - } - else if (pt->target == PIPE_TEXTURE_3D) { - offset = tex->image_offset[level][zslice]; - } - else { - offset = tex->image_offset[level][0]; - assert(face == 0); - assert(zslice == 0); - } + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); + if (pt->target != PIPE_TEXTURE_CUBE && + pt->target != PIPE_TEXTURE_3D) + assert(surf_tmpl->u.tex.first_layer == 0); ps = CALLOC_STRUCT(pipe_surface); if (ps) { + /* could subclass pipe_surface and store offset as it used to do */ pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = u_minify(pt->width0, level); - ps->height = u_minify(pt->height0, level); - ps->offset = offset; - ps->usage = flags; + ps->format = surf_tmpl->format; + ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); + ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); + ps->u.tex.level = surf_tmpl->u.tex.level; + ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; + ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; + ps->usage = surf_tmpl->usage; + ps->context = ctx; } return ps; } static void -i915_tex_surface_destroy(struct pipe_surface *surf) +i915_surface_destroy(struct pipe_context *ctx, + struct pipe_surface *surf) { pipe_resource_reference(&surf->texture, NULL); FREE(surf); @@ -211,13 +196,6 @@ i915_init_surface_functions(struct i915_context *i915) i915->base.resource_copy_region = i915_surface_copy; i915->base.clear_render_target = i915_clear_render_target; i915->base.clear_depth_stencil = i915_clear_depth_stencil; -} - -/* No good reason for these to be in the screen. - */ -void -i915_init_screen_surface_functions(struct i915_screen *is) -{ - is->base.get_tex_surface = i915_get_tex_surface; - is->base.tex_surface_destroy = i915_tex_surface_destroy; + i915->base.create_surface = i915_create_surface; + i915->base.surface_destroy = i915_surface_destroy; } diff --git a/src/gallium/drivers/i915/i915_surface.h b/src/gallium/drivers/i915/i915_surface.h index 448106d5662..70b61de80f2 100644 --- a/src/gallium/drivers/i915/i915_surface.h +++ b/src/gallium/drivers/i915/i915_surface.h @@ -32,7 +32,6 @@ struct i915_context; struct i915_screen; void i915_init_surface_functions( struct i915_context *i915 ); -void i915_init_screen_surface_functions( struct i915_screen *is ); #endif /* I915_SCREEN_H */ diff --git a/src/gallium/drivers/i915/i915_winsys.h b/src/gallium/drivers/i915/i915_winsys.h index 5385e403d22..24ea416f015 100644 --- a/src/gallium/drivers/i915/i915_winsys.h +++ b/src/gallium/drivers/i915/i915_winsys.h @@ -53,6 +53,7 @@ enum i915_winsys_buffer_type I915_NEW_VERTEX }; +/* These need to be in sync with the definitions of libdrm-intel! */ enum i915_winsys_buffer_tile { I915_TILE_NONE, @@ -106,7 +107,7 @@ struct i915_winsys { int (*batchbuffer_reloc)(struct i915_winsys_batchbuffer *batch, struct i915_winsys_buffer *reloc, enum i915_winsys_buffer_usage usage, - unsigned offset); + unsigned offset, bool fenced); /** * Flush a bufferbatch. @@ -130,10 +131,24 @@ struct i915_winsys { */ struct i915_winsys_buffer * (*buffer_create)(struct i915_winsys *iws, - unsigned size, unsigned alignment, + unsigned size, enum i915_winsys_buffer_type type); /** + * Create a tiled buffer. + * + * *stride, height are in bytes. The winsys tries to allocate the buffer with + * the tiling mode provide in *tiling. If tiling is no possible, *tiling will + * be set to I915_TILE_NONE. The calculated stride (incorporateing hw/kernel + * requirements) is always returned in *stride. + */ + struct i915_winsys_buffer * + (*buffer_create_tiled)(struct i915_winsys *iws, + unsigned *stride, unsigned height, + enum i915_winsys_buffer_tile *tiling, + enum i915_winsys_buffer_type type); + + /** * Creates a buffer from a handle. * Used to implement pipe_screen::resource_from_handle. * Also provides the stride information needed for the @@ -142,6 +157,7 @@ struct i915_winsys { struct i915_winsys_buffer * (*buffer_from_handle)(struct i915_winsys *iws, struct winsys_handle *whandle, + enum i915_winsys_buffer_tile *tiling, unsigned *stride); /** @@ -154,15 +170,6 @@ struct i915_winsys { unsigned stride); /** - * Fence a buffer with a fence reg. - * Not to be confused with pipe_fence_handle. - */ - int (*buffer_set_fence_reg)(struct i915_winsys *iws, - struct i915_winsys_buffer *buffer, - unsigned stride, - enum i915_winsys_buffer_tile tile); - - /** * Map a buffer. */ void *(*buffer_map)(struct i915_winsys *iws, diff --git a/src/gallium/drivers/i965/Makefile b/src/gallium/drivers/i965/Makefile index b0b09703384..a0331f80581 100644 --- a/src/gallium/drivers/i965/Makefile +++ b/src/gallium/drivers/i965/Makefile @@ -33,6 +33,7 @@ C_SOURCES = \ brw_pipe_flush.c \ brw_pipe_misc.c \ brw_pipe_sampler.c \ + brw_pipe_surface.c \ brw_pipe_vertex.c \ brw_pipe_clear.c \ brw_pipe_rast.c \ @@ -66,7 +67,6 @@ C_SOURCES = \ brw_resource_buffer.c \ brw_resource_texture.c \ brw_resource_texture_layout.c \ - brw_screen_surface.c \ brw_batchbuffer.c \ brw_winsys_debug.c \ intel_decode.c diff --git a/src/gallium/drivers/i965/SConscript b/src/gallium/drivers/i965/SConscript index 019af682f68..3ef6c880305 100644 --- a/src/gallium/drivers/i965/SConscript +++ b/src/gallium/drivers/i965/SConscript @@ -36,6 +36,8 @@ i965 = env.ConvenienceLibrary( 'brw_pipe_query.c', 'brw_pipe_rast.c', 'brw_pipe_sampler.c', + 'brw_pipe_surface.c', + 'brw_pipe_surface.c', 'brw_pipe_shader.c', 'brw_pipe_vertex.c', 'brw_resource.c', @@ -43,7 +45,6 @@ i965 = env.ConvenienceLibrary( 'brw_resource_texture.c', 'brw_resource_texture_layout.c', 'brw_screen.c', - 'brw_screen_surface.c', 'brw_structs_dump.c', 'brw_sf.c', 'brw_sf_emit.c', diff --git a/src/gallium/drivers/i965/brw_context.c b/src/gallium/drivers/i965/brw_context.c index 227bc790deb..a2736f783d5 100644 --- a/src/gallium/drivers/i965/brw_context.c +++ b/src/gallium/drivers/i965/brw_context.c @@ -131,6 +131,7 @@ struct pipe_context *brw_create_context(struct pipe_screen *screen, brw_pipe_shader_init( brw ); brw_pipe_vertex_init( brw ); brw_pipe_clear_init( brw ); + brw_pipe_surface_init( brw ); brw_hw_cc_init( brw ); diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h index 56d351f97d1..d927f382d5f 100644 --- a/src/gallium/drivers/i965/brw_context.h +++ b/src/gallium/drivers/i965/brw_context.h @@ -821,6 +821,7 @@ void brw_pipe_sampler_cleanup( struct brw_context *brw ); void brw_pipe_shader_cleanup( struct brw_context *brw ); void brw_pipe_vertex_cleanup( struct brw_context *brw ); void brw_pipe_clear_cleanup( struct brw_context *brw ); +void brw_pipe_surface_init( struct brw_context *brw ); void brw_hw_cc_init( struct brw_context *brw ); void brw_hw_cc_cleanup( struct brw_context *brw ); diff --git a/src/gallium/drivers/i965/brw_misc_state.c b/src/gallium/drivers/i965/brw_misc_state.c index b5029ceb69f..c635d696617 100644 --- a/src/gallium/drivers/i965/brw_misc_state.c +++ b/src/gallium/drivers/i965/brw_misc_state.c @@ -287,11 +287,12 @@ static int emit_depthbuffer(struct brw_context *brw) OUT_BATCH(((pitch * cpp) - 1) | (format << 18) | (BRW_TILEWALK_YMAJOR << 26) | - ((surface->layout != PIPE_SURFACE_LAYOUT_LINEAR) << 27) | + /* always linear ? + ((surface->layout != PIPE_SURFACE_LAYOUT_LINEAR) << 27) |*/ (BRW_SURFACE_2D << 29)); OUT_RELOC(bo, BRW_USAGE_DEPTH_BUFFER, - surface->offset); + brw_surface(surface)->offset); OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) | ((pitch - 1) << 6) | ((surface->height - 1) << 19)); @@ -362,10 +363,10 @@ const struct brw_tracked_state brw_line_stipple = { /*********************************************************************** - * Misc invarient state packets + * Misc invariant state packets */ -static int upload_invarient_state( struct brw_context *brw ) +static int upload_invariant_state( struct brw_context *brw ) { { /* 0x61040000 Pipeline Select */ @@ -438,7 +439,7 @@ static int upload_invarient_state( struct brw_context *brw ) { struct brw_polygon_stipple_offset bpso; - /* This is invarient state in gallium: + /* This is invariant state in gallium: */ memset(&bpso, 0, sizeof(bpso)); bpso.header.opcode = CMD_POLY_STIPPLE_OFFSET; @@ -452,13 +453,13 @@ static int upload_invarient_state( struct brw_context *brw ) return 0; } -const struct brw_tracked_state brw_invarient_state = { +const struct brw_tracked_state brw_invariant_state = { .dirty = { .mesa = 0, .brw = BRW_NEW_CONTEXT, .cache = 0 }, - .emit = upload_invarient_state + .emit = upload_invariant_state }; diff --git a/src/gallium/drivers/i965/brw_pipe_clear.c b/src/gallium/drivers/i965/brw_pipe_clear.c index d5cff338a66..7bf3ea6994a 100644 --- a/src/gallium/drivers/i965/brw_pipe_clear.c +++ b/src/gallium/drivers/i965/brw_pipe_clear.c @@ -64,7 +64,7 @@ try_clear( struct brw_context *brw, debug_printf("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", __FUNCTION__, (void *)surface->bo, pitch * cpp, - surface->base.offset, + surface->offset, x1, y1, x2 - x1, y2 - y1); BR13 = 0xf0 << 16; @@ -99,7 +99,7 @@ try_clear( struct brw_context *brw, OUT_BATCH((y2 << 16) | x2); OUT_RELOC(surface->bo, BRW_USAGE_BLIT_DEST, - surface->base.offset); + surface->offset); OUT_BATCH(value); ADVANCE_BATCH(); diff --git a/src/gallium/drivers/i965/brw_screen_surface.c b/src/gallium/drivers/i965/brw_pipe_surface.c index f288fdbcd37..4deead98b19 100644 --- a/src/gallium/drivers/i965/brw_screen_surface.c +++ b/src/gallium/drivers/i965/brw_pipe_surface.c @@ -35,6 +35,7 @@ #include "pipe/p_screen.h" #include "brw_screen.h" +#include "brw_context.h" #include "brw_defines.h" #include "brw_resource.h" #include "brw_winsys.h" @@ -108,9 +109,10 @@ void brw_update_texture( struct brw_screen *brw_screen, * where it would be illegal (perhaps due to tiling constraints) to do * this in-place. * - * Currently not implmented, not sure if it's needed. + * Currently not implemented, not sure if it's needed. */ static struct brw_surface *create_linear_view( struct brw_screen *brw_screen, + struct pipe_context *pipe, struct brw_texture *tex, union brw_surface_id id, unsigned usage ) @@ -123,9 +125,10 @@ static struct brw_surface *create_linear_view( struct brw_screen *brw_screen, * texture's storage. */ static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen, - struct brw_texture *tex, - union brw_surface_id id, - unsigned usage ) + struct pipe_context *pipe, + struct brw_texture *tex, + union brw_surface_id id, + unsigned usage ) { struct brw_surface *surface; @@ -137,17 +140,18 @@ static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen, /* XXX: ignoring render-to-slice-of-3d-texture */ - assert(id.bits.zslice == 0); + assert(tex->b.b.target != PIPE_TEXTURE_3D || id.bits.layer == 0); + surface->base.context = pipe; surface->base.format = tex->b.b.format; surface->base.width = u_minify(tex->b.b.width0, id.bits.level); surface->base.height = u_minify(tex->b.b.height0, id.bits.level); - surface->base.offset = tex->image_offset[id.bits.level][id.bits.face]; surface->base.usage = usage; - surface->base.zslice = id.bits.zslice; - surface->base.face = id.bits.face; - surface->base.level = id.bits.level; + surface->base.u.tex.first_layer = id.bits.layer; + surface->base.u.tex.last_layer = surface->base.u.tex.first_layer; + surface->base.u.tex.level = id.bits.level; surface->id = id; + surface->offset = tex->image_offset[id.bits.level][id.bits.layer]; surface->cpp = tex->cpp; surface->pitch = tex->pitch; surface->tiling = tex->tiling; @@ -159,11 +163,11 @@ static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen, surface->ss.ss0.surface_type = BRW_SURFACE_2D; if (tex->tiling == BRW_TILING_NONE) { - surface->ss.ss1.base_addr = surface->base.offset; + surface->ss.ss1.base_addr = surface->offset; } else { - uint32_t tile_offset = surface->base.offset % 4096; + uint32_t tile_offset = surface->offset % 4096; - surface->ss.ss1.base_addr = surface->base.offset - tile_offset; + surface->ss.ss1.base_addr = surface->offset - tile_offset; if (brw_screen->chipset.is_g4x) { if (tex->tiling == BRW_TILING_X) { @@ -198,23 +202,21 @@ static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen, /* Get a surface which is view into a texture */ -static struct pipe_surface *brw_get_tex_surface(struct pipe_screen *screen, - struct pipe_resource *pt, - unsigned face, unsigned level, - unsigned zslice, - unsigned usage ) +static struct pipe_surface *brw_create_surface(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { struct brw_texture *tex = brw_texture(pt); - struct brw_screen *bscreen = brw_screen(screen); + struct brw_screen *bscreen = brw_screen(pipe->screen); struct brw_surface *surface; union brw_surface_id id; int type; - id.bits.face = face; - id.bits.level = level; - id.bits.zslice = zslice; + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); + id.bits.level = surf_tmpl->u.tex.level; + id.bits.layer = surf_tmpl->u.tex.first_layer; - if (need_linear_view(bscreen, tex, id, usage)) + if (need_linear_view(bscreen, tex, id, surf_tmpl->usage)) type = BRW_VIEW_LINEAR; else type = BRW_VIEW_IN_PLACE; @@ -227,10 +229,10 @@ static struct pipe_surface *brw_get_tex_surface(struct pipe_screen *screen, switch (type) { case BRW_VIEW_LINEAR: - surface = create_linear_view( bscreen, tex, id, usage ); + surface = create_linear_view( bscreen, pipe, tex, id, surf_tmpl->usage ); break; case BRW_VIEW_IN_PLACE: - surface = create_in_place_view( bscreen, tex, id, usage ); + surface = create_in_place_view( bscreen, pipe, tex, id, surf_tmpl->usage ); break; } @@ -239,7 +241,8 @@ static struct pipe_surface *brw_get_tex_surface(struct pipe_screen *screen, } -static void brw_tex_surface_destroy( struct pipe_surface *surf ) +static void brw_surface_destroy( struct pipe_context *pipe, + struct pipe_surface *surf ) { struct brw_surface *surface = brw_surface(surf); @@ -249,13 +252,12 @@ static void brw_tex_surface_destroy( struct pipe_surface *surf ) bo_reference(&surface->bo, NULL); pipe_resource_reference( &surface->base.texture, NULL ); - FREE(surface); } -void brw_screen_tex_surface_init( struct brw_screen *brw_screen ) +void brw_pipe_surface_init( struct brw_context *brw ) { - brw_screen->base.get_tex_surface = brw_get_tex_surface; - brw_screen->base.tex_surface_destroy = brw_tex_surface_destroy; + brw->base.create_surface = brw_create_surface; + brw->base.surface_destroy = brw_surface_destroy; } diff --git a/src/gallium/drivers/i965/brw_resource_buffer.c b/src/gallium/drivers/i965/brw_resource_buffer.c index 5f9e8a87c99..afb96ee3e7f 100644 --- a/src/gallium/drivers/i965/brw_resource_buffer.c +++ b/src/gallium/drivers/i965/brw_resource_buffer.c @@ -92,9 +92,9 @@ brw_buffer_transfer_unmap( struct pipe_context *pipe, static unsigned brw_buffer_is_referenced( struct pipe_context *pipe, - struct pipe_resource *resource, - unsigned face, - unsigned level) + struct pipe_resource *resource, + unsigned level, + int layer) { struct brw_context *brw = brw_context(pipe); struct brw_winsys_buffer *batch_bo = brw->batch->buf; @@ -194,6 +194,7 @@ brw_user_buffer_create(struct pipe_screen *screen, buf->b.b.width0 = bytes; buf->b.b.height0 = 1; buf->b.b.depth0 = 1; + buf->b.b.array_size = 1; buf->user_buffer = ptr; diff --git a/src/gallium/drivers/i965/brw_resource_texture.c b/src/gallium/drivers/i965/brw_resource_texture.c index 3860d18a7a2..fded2da3820 100644 --- a/src/gallium/drivers/i965/brw_resource_texture.c +++ b/src/gallium/drivers/i965/brw_resource_texture.c @@ -229,8 +229,8 @@ static void brw_texture_destroy(struct pipe_screen *screen, static unsigned brw_texture_is_referenced( struct pipe_context *pipe, struct pipe_resource *texture, - unsigned face, - unsigned level ) + unsigned level, + int layer ) { struct brw_context *brw = brw_context(pipe); struct brw_screen *bscreen = brw_screen(pipe->screen); @@ -246,7 +246,7 @@ static unsigned brw_texture_is_referenced( struct pipe_context *pipe, if (bscreen->sws->bo_references( batch_bo, tex->bo )) return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; - /* Find any view on this texture for this face/level and see if it + /* Find any view on this texture for this level/layer and see if it * is referenced: */ for (i = 0; i < 2; i++) { @@ -254,7 +254,7 @@ static unsigned brw_texture_is_referenced( struct pipe_context *pipe, if (surf->bo == tex->bo) continue; - if (surf->id.bits.face != face || + if (!(layer == -1 || surf->id.bits.layer == layer) || surf->id.bits.level != level) continue; @@ -274,10 +274,10 @@ static unsigned brw_texture_is_referenced( struct pipe_context *pipe, static struct pipe_transfer * brw_texture_get_transfer(struct pipe_context *context, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct brw_texture *tex = brw_texture(resource); struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer); @@ -285,10 +285,11 @@ brw_texture_get_transfer(struct pipe_context *context, return NULL; transfer->resource = resource; - transfer->sr = sr; + transfer->level = level; transfer->usage = usage; transfer->box = *box; transfer->stride = tex->pitch * tex->cpp; + /* FIXME: layer_stride */ return transfer; } @@ -301,24 +302,16 @@ brw_texture_transfer_map(struct pipe_context *pipe, struct pipe_resource *resource = transfer->resource; struct brw_texture *tex = brw_texture(transfer->resource); struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws; - struct pipe_subresource sr = transfer->sr; struct pipe_box *box = &transfer->box; enum pipe_format format = resource->format; unsigned usage = transfer->usage; unsigned offset; char *map; - if (resource->target == PIPE_TEXTURE_CUBE) { - offset = tex->image_offset[sr.level][sr.face]; - } - else if (resource->target == PIPE_TEXTURE_3D) { - offset = tex->image_offset[sr.level][box->z]; - } - else { - offset = tex->image_offset[sr.level][0]; - assert(sr.face == 0); + if (resource->target != PIPE_TEXTURE_3D && + resource->target != PIPE_TEXTURE_CUBE) assert(box->z == 0); - } + offset = tex->image_offset[transfer->level][box->z]; map = sws->bo_map(tex->bo, BRW_DATA_OTHER, diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c index 57160ebb297..f5b75b17e36 100644 --- a/src/gallium/drivers/i965/brw_screen.c +++ b/src/gallium/drivers/i965/brw_screen.c @@ -240,6 +240,8 @@ brw_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shad case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 1; default: assert(0); return 0; @@ -468,7 +470,6 @@ brw_screen_create(struct brw_winsys_screen *sws) bscreen->base.fence_finish = brw_fence_finish; brw_init_screen_resource_functions(bscreen); - brw_screen_tex_surface_init(bscreen); bscreen->no_tiling = debug_get_option("BRW_NO_TILING", FALSE) != NULL; diff --git a/src/gallium/drivers/i965/brw_screen.h b/src/gallium/drivers/i965/brw_screen.h index 522a3bf8995..58e293bc76f 100644 --- a/src/gallium/drivers/i965/brw_screen.h +++ b/src/gallium/drivers/i965/brw_screen.h @@ -52,9 +52,8 @@ struct brw_screen union brw_surface_id { struct { - unsigned face:3; - unsigned zslice:13; unsigned level:16; + unsigned layer:16; } bits; unsigned value; }; @@ -63,8 +62,9 @@ union brw_surface_id { struct brw_surface { struct pipe_surface base; - + union brw_surface_id id; + unsigned offset; unsigned cpp; unsigned pitch; unsigned draw_offset; @@ -96,7 +96,5 @@ brw_surface(struct pipe_surface *surface) unsigned brw_surface_pitch( const struct pipe_surface *surface ); -void brw_screen_tex_surface_init( struct brw_screen *brw_screen ); - #endif /* BRW_SCREEN_H */ diff --git a/src/gallium/drivers/i965/brw_state.h b/src/gallium/drivers/i965/brw_state.h index d2bbd0123d1..380d511f9bb 100644 --- a/src/gallium/drivers/i965/brw_state.h +++ b/src/gallium/drivers/i965/brw_state.h @@ -56,7 +56,7 @@ const struct brw_tracked_state brw_clip_prog; const struct brw_tracked_state brw_clip_unit; const struct brw_tracked_state brw_curbe_buffer; const struct brw_tracked_state brw_curbe_offsets; -const struct brw_tracked_state brw_invarient_state; +const struct brw_tracked_state brw_invariant_state; const struct brw_tracked_state brw_gs_prog; const struct brw_tracked_state brw_gs_unit; const struct brw_tracked_state brw_line_stipple; diff --git a/src/gallium/drivers/i965/brw_state_upload.c b/src/gallium/drivers/i965/brw_state_upload.c index f8b91eff816..cdbf270e06a 100644 --- a/src/gallium/drivers/i965/brw_state_upload.c +++ b/src/gallium/drivers/i965/brw_state_upload.c @@ -69,7 +69,7 @@ const struct brw_tracked_state *atoms[] = /* Command packets: */ - &brw_invarient_state, + &brw_invariant_state, &brw_state_base_address, &brw_binding_table_pointers, diff --git a/src/gallium/drivers/i965/brw_wm_fp.c b/src/gallium/drivers/i965/brw_wm_fp.c index f7ee55cc1c8..a65e16edec0 100644 --- a/src/gallium/drivers/i965/brw_wm_fp.c +++ b/src/gallium/drivers/i965/brw_wm_fp.c @@ -812,7 +812,7 @@ static void precalc_tex( struct brw_wm_compile *c, } /* XXX: add GL_EXT_texture_swizzle support to gallium -- by - * generating shader varients in mesa state tracker. + * generating shader variants in mesa state tracker. */ /* Release this temp if we ended up allocating it: diff --git a/src/gallium/drivers/identity/SConscript b/src/gallium/drivers/identity/SConscript index b364e0acc84..d24d1ec7c61 100644 --- a/src/gallium/drivers/identity/SConscript +++ b/src/gallium/drivers/identity/SConscript @@ -10,4 +10,6 @@ identity = env.ConvenienceLibrary( 'id_screen.c', ]) +env.Alias('identity', identity) + Export('identity') diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index de83c249057..3efbd6a246d 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -577,17 +577,13 @@ identity_set_index_buffer(struct pipe_context *_pipe, static void identity_resource_copy_region(struct pipe_context *_pipe, struct pipe_resource *_dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *_src, - struct pipe_subresource subsrc, - unsigned srcx, - unsigned srcy, - unsigned srcz, - unsigned width, - unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { struct identity_context *id_pipe = identity_context(_pipe); struct identity_resource *id_resource_dst = identity_resource(_dst); @@ -598,17 +594,13 @@ identity_resource_copy_region(struct pipe_context *_pipe, pipe->resource_copy_region(pipe, dst, - subdst, + dst_level, dstx, dsty, dstz, src, - subsrc, - srcx, - srcy, - srcz, - width, - height); + src_level, + src_box); } static void @@ -690,8 +682,8 @@ identity_flush(struct pipe_context *_pipe, static unsigned int identity_is_resource_referenced(struct pipe_context *_pipe, struct pipe_resource *_resource, - unsigned face, - unsigned level) + unsigned level, + int layer) { struct identity_context *id_pipe = identity_context(_pipe); struct identity_resource *id_resource = identity_resource(_resource); @@ -700,8 +692,8 @@ identity_is_resource_referenced(struct pipe_context *_pipe, return pipe->is_resource_referenced(pipe, resource, - face, - level); + level, + layer); } static struct pipe_sampler_view * @@ -732,10 +724,38 @@ identity_context_sampler_view_destroy(struct pipe_context *_pipe, identity_sampler_view(_view)); } +static struct pipe_surface * +identity_context_create_surface(struct pipe_context *_pipe, + struct pipe_resource *_resource, + const struct pipe_surface *templ) +{ + struct identity_context *id_context = identity_context(_pipe); + struct identity_resource *id_resource = identity_resource(_resource); + struct pipe_context *pipe = id_context->pipe; + struct pipe_resource *resource = id_resource->resource; + struct pipe_surface *result; + + result = pipe->create_surface(pipe, + resource, + templ); + + if (result) + return identity_surface_create(id_context, id_resource, result); + return NULL; +} + +static void +identity_context_surface_destroy(struct pipe_context *_pipe, + struct pipe_surface *_surf) +{ + identity_surface_destroy(identity_context(_pipe), + identity_surface(_surf)); +} + static struct pipe_transfer * identity_context_get_transfer(struct pipe_context *_context, struct pipe_resource *_resource, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box) { @@ -747,7 +767,7 @@ identity_context_get_transfer(struct pipe_context *_context, result = context->get_transfer(context, resource, - sr, + level, usage, box); @@ -812,12 +832,12 @@ identity_context_transfer_unmap(struct pipe_context *_context, static void identity_context_transfer_inline_write(struct pipe_context *_context, struct pipe_resource *_resource, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, - unsigned slice_stride) + unsigned layer_stride) { struct identity_context *id_context = identity_context(_context); struct identity_resource *id_resource = identity_resource(_resource); @@ -826,12 +846,12 @@ identity_context_transfer_inline_write(struct pipe_context *_context, context->transfer_inline_write(context, resource, - sr, + level, usage, box, data, stride, - slice_stride); + layer_stride); } @@ -899,6 +919,8 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.clear_depth_stencil = identity_clear_depth_stencil; id_pipe->base.flush = identity_flush; id_pipe->base.is_resource_referenced = identity_is_resource_referenced; + id_pipe->base.create_surface = identity_context_create_surface; + id_pipe->base.surface_destroy = identity_context_surface_destroy; id_pipe->base.create_sampler_view = identity_context_create_sampler_view; id_pipe->base.sampler_view_destroy = identity_context_sampler_view_destroy; id_pipe->base.get_transfer = identity_context_get_transfer; diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c index 593928f399c..63454410525 100644 --- a/src/gallium/drivers/identity/id_objects.c +++ b/src/gallium/drivers/identity/id_objects.c @@ -71,7 +71,8 @@ identity_resource_destroy(struct identity_resource *id_resource) struct pipe_surface * -identity_surface_create(struct identity_resource *id_resource, +identity_surface_create(struct identity_context *id_context, + struct identity_resource *id_resource, struct pipe_surface *surface) { struct identity_surface *id_surface; @@ -100,10 +101,12 @@ error: } void -identity_surface_destroy(struct identity_surface *id_surface) +identity_surface_destroy(struct identity_context *id_context, + struct identity_surface *id_surface) { pipe_resource_reference(&id_surface->base.texture, NULL); - pipe_surface_reference(&id_surface->surface, NULL); + id_context->pipe->surface_destroy(id_context->pipe, + id_surface->surface); FREE(id_surface); } diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h index e8deabf4fc7..181f2d6623e 100644 --- a/src/gallium/drivers/identity/id_objects.h +++ b/src/gallium/drivers/identity/id_objects.h @@ -147,11 +147,13 @@ void identity_resource_destroy(struct identity_resource *id_resource); struct pipe_surface * -identity_surface_create(struct identity_resource *id_resource, +identity_surface_create(struct identity_context *id_context, + struct identity_resource *id_resource, struct pipe_surface *surface); void -identity_surface_destroy(struct identity_surface *id_surface); +identity_surface_destroy(struct identity_context *id_context, + struct identity_surface *id_surface); struct pipe_sampler_view * identity_sampler_view_create(struct identity_context *id_context, diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c index 5fb464b4148..644481bb748 100644 --- a/src/gallium/drivers/identity/id_screen.c +++ b/src/gallium/drivers/identity/id_screen.c @@ -189,39 +189,6 @@ identity_screen_resource_destroy(struct pipe_screen *screen, identity_resource_destroy(identity_resource(_resource)); } -static struct pipe_surface * -identity_screen_get_tex_surface(struct pipe_screen *_screen, - struct pipe_resource *_resource, - unsigned face, - unsigned level, - unsigned zslice, - unsigned usage) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_resource *id_resource = identity_resource(_resource); - struct pipe_screen *screen = id_screen->screen; - struct pipe_resource *resource = id_resource->resource; - struct pipe_surface *result; - - result = screen->get_tex_surface(screen, - resource, - face, - level, - zslice, - usage); - - if (result) - return identity_surface_create(id_resource, result); - return NULL; -} - -static void -identity_screen_tex_surface_destroy(struct pipe_surface *_surface) -{ - identity_surface_destroy(identity_surface(_surface)); -} - - static struct pipe_resource * identity_screen_user_buffer_create(struct pipe_screen *_screen, @@ -247,16 +214,18 @@ identity_screen_user_buffer_create(struct pipe_screen *_screen, static void identity_screen_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_surface *_surface, + struct pipe_resource *_resource, + unsigned level, unsigned layer, void *context_private) { struct identity_screen *id_screen = identity_screen(_screen); - struct identity_surface *id_surface = identity_surface(_surface); + struct identity_resource *id_resource = identity_resource(_resource); struct pipe_screen *screen = id_screen->screen; - struct pipe_surface *surface = id_surface->surface; + struct pipe_resource *resource = id_resource->resource; screen->flush_frontbuffer(screen, - surface, + resource, + level, layer, context_private); } @@ -323,8 +292,6 @@ identity_screen_create(struct pipe_screen *screen) id_screen->base.resource_from_handle = identity_screen_resource_from_handle; id_screen->base.resource_get_handle = identity_screen_resource_get_handle; id_screen->base.resource_destroy = identity_screen_resource_destroy; - id_screen->base.get_tex_surface = identity_screen_get_tex_surface; - id_screen->base.tex_surface_destroy = identity_screen_tex_surface_destroy; id_screen->base.user_buffer_create = identity_screen_user_buffer_create; id_screen->base.flush_frontbuffer = identity_screen_flush_frontbuffer; id_screen->base.fence_reference = identity_screen_fence_reference; diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile index 669e42e3003..4068bed393c 100644 --- a/src/gallium/drivers/llvmpipe/Makefile +++ b/src/gallium/drivers/llvmpipe/Makefile @@ -3,8 +3,6 @@ include $(TOP)/configs/current LIBNAME = llvmpipe -DEFINES += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS - C_SOURCES = \ lp_bld_alpha.c \ lp_bld_blend_aos.c \ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c index e50643790c8..518969c3202 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c @@ -43,7 +43,7 @@ void -lp_build_alpha_test(LLVMBuilderRef builder, +lp_build_alpha_test(struct gallivm_state *gallivm, unsigned func, struct lp_type type, struct lp_build_mask_context *mask, @@ -54,7 +54,7 @@ lp_build_alpha_test(LLVMBuilderRef builder, struct lp_build_context bld; LLVMValueRef test; - lp_build_context_init(&bld, builder, type); + lp_build_context_init(&bld, gallivm, type); test = lp_build_cmp(&bld, func, alpha, ref); diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h index 27ca8aad4d4..5c9392504f1 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h @@ -43,7 +43,7 @@ struct lp_build_mask_context; void -lp_build_alpha_test(LLVMBuilderRef builder, +lp_build_alpha_test(struct gallivm_state *gallivm, unsigned func, struct lp_type type, struct lp_build_mask_context *mask, diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend.h b/src/gallium/drivers/llvmpipe/lp_bld_blend.h index 5cecec3d7f9..f82ae30bb7d 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend.h @@ -30,6 +30,7 @@ #include "gallivm/lp_bld.h" +#include "gallivm/lp_bld_init.h" #include "pipe/p_format.h" @@ -61,7 +62,7 @@ lp_build_blend_func(struct lp_build_context *bld, LLVMValueRef -lp_build_blend_aos(LLVMBuilderRef builder, +lp_build_blend_aos(struct gallivm_state *gallivm, const struct pipe_blend_state *blend, struct lp_type type, unsigned rt, @@ -72,7 +73,7 @@ lp_build_blend_aos(LLVMBuilderRef builder, void -lp_build_blend_soa(LLVMBuilderRef builder, +lp_build_blend_soa(struct gallivm_state *gallivm, const struct pipe_blend_state *blend, struct lp_type type, unsigned rt, diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c index d1c9b88f9bb..c342346a36e 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c @@ -301,7 +301,7 @@ lp_build_blend_func(struct lp_build_context *bld, LLVMValueRef -lp_build_blend_aos(LLVMBuilderRef builder, +lp_build_blend_aos(struct gallivm_state *gallivm, const struct pipe_blend_state *blend, struct lp_type type, unsigned rt, @@ -322,7 +322,7 @@ lp_build_blend_aos(LLVMBuilderRef builder, /* Setup build context */ memset(&bld, 0, sizeof bld); - lp_build_context_init(&bld.base, builder, type); + lp_build_context_init(&bld.base, gallivm, type); bld.src = src; bld.dst = dst; bld.const_ = const_; diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c index 30d261e979f..4d5bc9642d9 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c @@ -73,6 +73,7 @@ #include "gallivm/lp_bld_type.h" #include "gallivm/lp_bld_arit.h" +#include "gallivm/lp_bld_init.h" #include "lp_bld_blend.h" @@ -211,7 +212,7 @@ lp_build_blend_factor_complementary(unsigned src_factor, unsigned dst_factor) * \param res the result/output */ void -lp_build_blend_soa(LLVMBuilderRef builder, +lp_build_blend_soa(struct gallivm_state *gallivm, const struct pipe_blend_state *blend, struct lp_type type, unsigned rt, @@ -220,6 +221,7 @@ lp_build_blend_soa(LLVMBuilderRef builder, LLVMValueRef con[4], LLVMValueRef res[4]) { + LLVMBuilderRef builder = gallivm->builder; struct lp_build_blend_soa_context bld; unsigned i, j, k; @@ -227,7 +229,7 @@ lp_build_blend_soa(LLVMBuilderRef builder, /* Setup build context */ memset(&bld, 0, sizeof bld); - lp_build_context_init(&bld.base, builder, type); + lp_build_context_init(&bld.base, gallivm, type); for (i = 0; i < 4; ++i) { bld.src[i] = src[i]; bld.dst[i] = dst[i]; diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c index 7eb76d4fb31..1bf741194c5 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c @@ -97,6 +97,7 @@ lp_build_stencil_test_single(struct lp_build_context *bld, LLVMValueRef stencilRef, LLVMValueRef stencilVals) { + LLVMBuilderRef builder = bld->gallivm->builder; const unsigned stencilMax = 255; /* XXX fix */ struct lp_type type = bld->type; LLVMValueRef res; @@ -107,10 +108,10 @@ lp_build_stencil_test_single(struct lp_build_context *bld, if (stencil->valuemask != stencilMax) { /* compute stencilRef = stencilRef & valuemask */ - LLVMValueRef valuemask = lp_build_const_int_vec(type, stencil->valuemask); - stencilRef = LLVMBuildAnd(bld->builder, stencilRef, valuemask, ""); + LLVMValueRef valuemask = lp_build_const_int_vec(bld->gallivm, type, stencil->valuemask); + stencilRef = LLVMBuildAnd(builder, stencilRef, valuemask, ""); /* compute stencilVals = stencilVals & valuemask */ - stencilVals = LLVMBuildAnd(bld->builder, stencilVals, valuemask, ""); + stencilVals = LLVMBuildAnd(builder, stencilVals, valuemask, ""); } res = lp_build_cmp(bld, stencil->func, stencilRef, stencilVals); @@ -167,9 +168,10 @@ lp_build_stencil_op_single(struct lp_build_context *bld, LLVMValueRef stencilVals) { + LLVMBuilderRef builder = bld->gallivm->builder; struct lp_type type = bld->type; LLVMValueRef res; - LLVMValueRef max = lp_build_const_int_vec(type, 0xff); + LLVMValueRef max = lp_build_const_int_vec(bld->gallivm, type, 0xff); unsigned stencil_op; assert(type.sign); @@ -210,15 +212,15 @@ lp_build_stencil_op_single(struct lp_build_context *bld, break; case PIPE_STENCIL_OP_INCR_WRAP: res = lp_build_add(bld, stencilVals, bld->one); - res = LLVMBuildAnd(bld->builder, res, max, ""); + res = LLVMBuildAnd(builder, res, max, ""); break; case PIPE_STENCIL_OP_DECR_WRAP: res = lp_build_sub(bld, stencilVals, bld->one); - res = LLVMBuildAnd(bld->builder, res, max, ""); + res = LLVMBuildAnd(builder, res, max, ""); break; case PIPE_STENCIL_OP_INVERT: - res = LLVMBuildNot(bld->builder, stencilVals, ""); - res = LLVMBuildAnd(bld->builder, res, max, ""); + res = LLVMBuildNot(builder, stencilVals, ""); + res = LLVMBuildAnd(builder, res, max, ""); break; default: assert(0 && "bad stencil op mode"); @@ -242,6 +244,7 @@ lp_build_stencil_op(struct lp_build_context *bld, LLVMValueRef front_facing) { + LLVMBuilderRef builder = bld->gallivm->builder; LLVMValueRef res; assert(stencil[0].enabled); @@ -262,10 +265,11 @@ lp_build_stencil_op(struct lp_build_context *bld, if (stencil->writemask != 0xff) { /* mask &= stencil->writemask */ - LLVMValueRef writemask = lp_build_const_int_vec(bld->type, stencil->writemask); - mask = LLVMBuildAnd(bld->builder, mask, writemask, ""); + LLVMValueRef writemask = lp_build_const_int_vec(bld->gallivm, bld->type, + stencil->writemask); + mask = LLVMBuildAnd(builder, mask, writemask, ""); /* res = (res & mask) | (stencilVals & ~mask) */ - res = lp_build_select_bitwise(bld, writemask, res, stencilVals); + res = lp_build_select_bitwise(bld, mask, res, stencilVals); } else { /* res = mask ? res : stencilVals */ @@ -411,25 +415,27 @@ get_s_shift_and_mask(const struct util_format_description *format_desc, * \param counter is a pointer of the uint32 counter. */ void -lp_build_occlusion_count(LLVMBuilderRef builder, +lp_build_occlusion_count(struct gallivm_state *gallivm, struct lp_type type, LLVMValueRef maskvalue, LLVMValueRef counter) { - LLVMValueRef countmask = lp_build_const_int_vec(type, 1); + LLVMBuilderRef builder = gallivm->builder; + LLVMContextRef context = gallivm->context; + LLVMValueRef countmask = lp_build_const_int_vec(gallivm, type, 1); LLVMValueRef countv = LLVMBuildAnd(builder, maskvalue, countmask, "countv"); - LLVMTypeRef i8v16 = LLVMVectorType(LLVMInt8Type(), 16); + LLVMTypeRef i8v16 = LLVMVectorType(LLVMInt8TypeInContext(context), 16); LLVMValueRef counti = LLVMBuildBitCast(builder, countv, i8v16, "counti"); LLVMValueRef maskarray[4] = { - LLVMConstInt(LLVMInt32Type(), 0, 0), - LLVMConstInt(LLVMInt32Type(), 4, 0), - LLVMConstInt(LLVMInt32Type(), 8, 0), - LLVMConstInt(LLVMInt32Type(), 12, 0), + lp_build_const_int32(gallivm, 0), + lp_build_const_int32(gallivm, 4), + lp_build_const_int32(gallivm, 8), + lp_build_const_int32(gallivm, 12) }; LLVMValueRef shufflemask = LLVMConstVector(maskarray, 4); LLVMValueRef shufflev = LLVMBuildShuffleVector(builder, counti, LLVMGetUndef(i8v16), shufflemask, "shufflev"); - LLVMValueRef shuffle = LLVMBuildBitCast(builder, shufflev, LLVMInt32Type(), "shuffle"); - LLVMValueRef count = lp_build_intrinsic_unary(builder, "llvm.ctpop.i32", LLVMInt32Type(), shuffle); + LLVMValueRef shuffle = LLVMBuildBitCast(builder, shufflev, LLVMInt32TypeInContext(context), "shuffle"); + LLVMValueRef count = lp_build_intrinsic_unary(builder, "llvm.ctpop.i32", LLVMInt32TypeInContext(context), shuffle); LLVMValueRef orig = LLVMBuildLoad(builder, counter, "orig"); LLVMValueRef incr = LLVMBuildAdd(builder, orig, count, "incr"); LLVMBuildStore(builder, incr, counter); @@ -452,7 +458,7 @@ lp_build_occlusion_count(LLVMBuilderRef builder, * \param facing contains boolean value indicating front/back facing polygon */ void -lp_build_depth_stencil_test(LLVMBuilderRef builder, +lp_build_depth_stencil_test(struct gallivm_state *gallivm, const struct pipe_depth_state *depth, const struct pipe_stencil_state stencil[2], struct lp_type z_src_type, @@ -465,6 +471,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, LLVMValueRef *zs_value, boolean do_branch) { + LLVMBuilderRef builder = gallivm->builder; struct lp_type z_type; struct lp_build_context z_bld; struct lp_build_context s_bld; @@ -537,11 +544,11 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, /* Setup build context for Z vals */ - lp_build_context_init(&z_bld, builder, z_type); + lp_build_context_init(&z_bld, gallivm, z_type); /* Setup build context for stencil vals */ s_type = lp_type_int_vec(z_type.width); - lp_build_context_init(&s_bld, builder, s_type); + lp_build_context_init(&s_bld, gallivm, s_type); /* Load current z/stencil value from z/stencil buffer */ zs_dst_ptr = LLVMBuildBitCast(builder, @@ -559,14 +566,14 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, if (get_z_shift_and_mask(format_desc, &z_shift, &z_width, &z_mask)) { if (z_mask != 0xffffffff) { - z_bitmask = lp_build_const_int_vec(z_type, z_mask); + z_bitmask = lp_build_const_int_vec(gallivm, z_type, z_mask); } /* * Align the framebuffer Z 's LSB to the right. */ if (z_shift) { - LLVMValueRef shift = lp_build_const_int_vec(z_type, z_shift); + LLVMValueRef shift = lp_build_const_int_vec(gallivm, z_type, z_shift); z_dst = LLVMBuildLShr(builder, zs_dst, shift, "z_dst"); } else if (z_bitmask) { /* TODO: Instead of loading a mask from memory and ANDing, it's @@ -580,7 +587,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, if (get_s_shift_and_mask(format_desc, &s_shift, &s_mask)) { if (s_shift) { - LLVMValueRef shift = lp_build_const_int_vec(s_type, s_shift); + LLVMValueRef shift = lp_build_const_int_vec(gallivm, s_type, s_shift); stencil_vals = LLVMBuildLShr(builder, zs_dst, shift, ""); stencil_shift = shift; /* used below */ } @@ -589,7 +596,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, } if (s_mask != 0xffffffff) { - LLVMValueRef mask = lp_build_const_int_vec(s_type, s_mask); + LLVMValueRef mask = lp_build_const_int_vec(gallivm, s_type, s_mask); stencil_vals = LLVMBuildAnd(builder, stencil_vals, mask, ""); } @@ -600,12 +607,13 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, if (stencil[0].enabled) { if (face) { - LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, 0); + LLVMValueRef zero = lp_build_const_int32(gallivm, 0); /* front_facing = face != 0 ? ~0 : 0 */ front_facing = LLVMBuildICmp(builder, LLVMIntNE, face, zero, ""); front_facing = LLVMBuildSExt(builder, front_facing, - LLVMIntType(s_bld.type.length*s_bld.type.width), + LLVMIntTypeInContext(gallivm->context, + s_bld.type.length*s_bld.type.width), ""); front_facing = LLVMBuildBitCast(builder, front_facing, s_bld.int_vec_type, ""); @@ -642,7 +650,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, */ if (!z_type.floating) { - z_src = lp_build_clamped_float_to_unsigned_norm(builder, + z_src = lp_build_clamped_float_to_unsigned_norm(gallivm, z_src_type, z_width, z_src); @@ -657,7 +665,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, assert(z_src_type.norm); assert(!z_type.floating); if (z_src_type.width > z_width) { - LLVMValueRef shift = lp_build_const_int_vec(z_src_type, + LLVMValueRef shift = lp_build_const_int_vec(gallivm, z_src_type, z_src_type.width - z_width); z_src = LLVMBuildLShr(builder, z_src, shift, ""); } @@ -710,7 +718,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, z_fail_mask, front_facing); /* apply Z-pass operator */ - z_pass_mask = LLVMBuildAnd(z_bld.builder, orig_mask, z_pass, ""); + z_pass_mask = LLVMBuildAnd(builder, orig_mask, z_pass, ""); stencil_vals = lp_build_stencil_op(&s_bld, stencil, Z_PASS_OP, stencil_refs, stencil_vals, z_pass_mask, front_facing); @@ -720,7 +728,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, /* No depth test: apply Z-pass operator to stencil buffer values which * passed the stencil test. */ - s_pass_mask = LLVMBuildAnd(s_bld.builder, orig_mask, s_pass_mask, ""); + s_pass_mask = LLVMBuildAnd(builder, orig_mask, s_pass_mask, ""); stencil_vals = lp_build_stencil_op(&s_bld, stencil, Z_PASS_OP, stencil_refs, stencil_vals, s_pass_mask, front_facing); @@ -728,11 +736,11 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, /* Put Z and ztencil bits in the right place */ if (z_dst && z_shift) { - LLVMValueRef shift = lp_build_const_int_vec(z_type, z_shift); + LLVMValueRef shift = lp_build_const_int_vec(gallivm, z_type, z_shift); z_dst = LLVMBuildShl(builder, z_dst, shift, ""); } if (stencil_vals && stencil_shift) - stencil_vals = LLVMBuildShl(s_bld.builder, stencil_vals, + stencil_vals = LLVMBuildShl(builder, stencil_vals, stencil_shift, ""); /* Finally, merge/store the z/stencil values */ @@ -740,7 +748,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, (stencil[0].enabled && stencil[0].writemask)) { if (z_dst && stencil_vals) - zs_dst = LLVMBuildOr(z_bld.builder, z_dst, stencil_vals, ""); + zs_dst = LLVMBuildOr(builder, z_dst, stencil_vals, ""); else if (z_dst) zs_dst = z_dst; else @@ -775,7 +783,7 @@ lp_build_depth_write(LLVMBuilderRef builder, void -lp_build_deferred_depth_write(LLVMBuilderRef builder, +lp_build_deferred_depth_write(struct gallivm_state *gallivm, struct lp_type z_src_type, const struct util_format_description *format_desc, struct lp_build_mask_context *mask, @@ -785,11 +793,12 @@ lp_build_deferred_depth_write(LLVMBuilderRef builder, struct lp_type z_type; struct lp_build_context z_bld; LLVMValueRef z_dst; + LLVMBuilderRef builder = gallivm->builder; /* XXX: pointlessly redo type logic: */ z_type = lp_depth_type(format_desc, z_src_type.width*z_src_type.length); - lp_build_context_init(&z_bld, builder, z_type); + lp_build_context_init(&z_bld, gallivm, z_type); zs_dst_ptr = LLVMBuildBitCast(builder, zs_dst_ptr, LLVMPointerType(z_bld.vec_type, 0), ""); diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h index a54ef3a711e..038b136a281 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.h @@ -51,7 +51,7 @@ lp_depth_type(const struct util_format_description *format_desc, void -lp_build_depth_stencil_test(LLVMBuilderRef builder, +lp_build_depth_stencil_test(struct gallivm_state *gallivm, const struct pipe_depth_state *depth, const struct pipe_stencil_state stencil[2], struct lp_type type, @@ -71,7 +71,7 @@ lp_build_depth_write(LLVMBuilderRef builder, LLVMValueRef zs_value); void -lp_build_deferred_depth_write(LLVMBuilderRef builder, +lp_build_deferred_depth_write(struct gallivm_state *gallivm, struct lp_type z_src_type, const struct util_format_description *format_desc, struct lp_build_mask_context *mask, @@ -79,7 +79,7 @@ lp_build_deferred_depth_write(LLVMBuilderRef builder, LLVMValueRef zs_value); void -lp_build_occlusion_count(LLVMBuilderRef builder, +lp_build_occlusion_count(struct gallivm_state *gallivm, struct lp_type type, LLVMValueRef maskvalue, LLVMValueRef counter); diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c index c9da8900d0c..45ddf547bf0 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.c @@ -127,13 +127,14 @@ coeffs_init(struct lp_build_interp_soa_context *bld, LLVMValueRef dady_ptr) { struct lp_build_context *coeff_bld = &bld->coeff_bld; - LLVMBuilderRef builder = coeff_bld->builder; + struct gallivm_state *gallivm = coeff_bld->gallivm; + LLVMBuilderRef builder = gallivm->builder; LLVMValueRef zero = LLVMConstNull(coeff_bld->elem_type); LLVMValueRef one = LLVMConstReal(coeff_bld->elem_type, 1.0); - LLVMValueRef i0 = LLVMConstInt(LLVMInt32Type(), 0, 0); - LLVMValueRef i1 = LLVMConstInt(LLVMInt32Type(), 1, 0); - LLVMValueRef i2 = LLVMConstInt(LLVMInt32Type(), 2, 0); - LLVMValueRef i3 = LLVMConstInt(LLVMInt32Type(), 3, 0); + LLVMValueRef i0 = lp_build_const_int32(gallivm, 0); + LLVMValueRef i1 = lp_build_const_int32(gallivm, 1); + LLVMValueRef i2 = lp_build_const_int32(gallivm, 2); + LLVMValueRef i3 = lp_build_const_int32(gallivm, 3); unsigned attrib; unsigned chan; @@ -144,7 +145,8 @@ coeffs_init(struct lp_build_interp_soa_context *bld, const unsigned interp = bld->interp[attrib]; for (chan = 0; chan < NUM_CHANNELS; ++chan) { if (mask & (1 << chan)) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), attrib*NUM_CHANNELS + chan, 0); + LLVMValueRef index = lp_build_const_int32(gallivm, + attrib * NUM_CHANNELS + chan); LLVMValueRef a0 = zero; LLVMValueRef dadx = zero; LLVMValueRef dady = zero; @@ -231,7 +233,7 @@ coeffs_init(struct lp_build_interp_soa_context *bld, * a = {a, a, a, a} */ - a = lp_build_broadcast(builder, coeff_bld->vec_type, a); + a = lp_build_broadcast(gallivm, coeff_bld->vec_type, a); /* * Compute the attrib values on the upper-left corner of each quad. @@ -273,12 +275,14 @@ coeffs_init(struct lp_build_interp_soa_context *bld, */ static void attribs_update(struct lp_build_interp_soa_context *bld, + struct gallivm_state *gallivm, int quad_index, int start, int end) { + LLVMBuilderRef builder = gallivm->builder; struct lp_build_context *coeff_bld = &bld->coeff_bld; - LLVMValueRef shuffle = lp_build_const_int_vec(coeff_bld->type, quad_index); + LLVMValueRef shuffle = lp_build_const_int_vec(gallivm, coeff_bld->type, quad_index); LLVMValueRef oow = NULL; unsigned attrib; unsigned chan; @@ -308,7 +312,7 @@ attribs_update(struct lp_build_interp_soa_context *bld, * Broadcast the attribute value for this quad into all elements */ - a = LLVMBuildShuffleVector(coeff_bld->builder, + a = LLVMBuildShuffleVector(builder, a, coeff_bld->undef, shuffle, ""); /* @@ -380,10 +384,11 @@ pos_init(struct lp_build_interp_soa_context *bld, LLVMValueRef x0, LLVMValueRef y0) { + LLVMBuilderRef builder = bld->coeff_bld.gallivm->builder; struct lp_build_context *coeff_bld = &bld->coeff_bld; - bld->x = LLVMBuildSIToFP(coeff_bld->builder, x0, coeff_bld->elem_type, ""); - bld->y = LLVMBuildSIToFP(coeff_bld->builder, y0, coeff_bld->elem_type, ""); + bld->x = LLVMBuildSIToFP(builder, x0, coeff_bld->elem_type, ""); + bld->y = LLVMBuildSIToFP(builder, y0, coeff_bld->elem_type, ""); } @@ -392,6 +397,7 @@ pos_init(struct lp_build_interp_soa_context *bld, */ void lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, + struct gallivm_state *gallivm, unsigned num_inputs, const struct lp_shader_input *inputs, LLVMBuilderRef builder, @@ -417,7 +423,7 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, /* XXX: we don't support interpolating into any other types */ assert(memcmp(&coeff_type, &type, sizeof coeff_type) == 0); - lp_build_context_init(&bld->coeff_bld, builder, coeff_type); + lp_build_context_init(&bld->coeff_bld, gallivm, coeff_type); /* For convenience */ bld->pos = bld->attribs[0]; @@ -453,19 +459,21 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, */ void lp_build_interp_soa_update_inputs(struct lp_build_interp_soa_context *bld, + struct gallivm_state *gallivm, int quad_index) { assert(quad_index < 4); - attribs_update(bld, quad_index, 1, bld->num_attribs); + attribs_update(bld, gallivm, quad_index, 1, bld->num_attribs); } void lp_build_interp_soa_update_pos(struct lp_build_interp_soa_context *bld, + struct gallivm_state *gallivm, int quad_index) { assert(quad_index < 4); - attribs_update(bld, quad_index, 0, 1); + attribs_update(bld, gallivm, quad_index, 0, 1); } diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.h b/src/gallium/drivers/llvmpipe/lp_bld_interp.h index a7ebdd1bfa2..b58b2dc1155 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.h @@ -102,6 +102,7 @@ struct lp_build_interp_soa_context void lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, + struct gallivm_state *gallivm, unsigned num_inputs, const struct lp_shader_input *inputs, LLVMBuilderRef builder, @@ -114,11 +115,13 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, void lp_build_interp_soa_update_inputs(struct lp_build_interp_soa_context *bld, - int quad_index); + struct gallivm_state *gallivm, + int quad_index); void lp_build_interp_soa_update_pos(struct lp_build_interp_soa_context *bld, - int quad_index); + struct gallivm_state *gallivm, + int quad_index); #endif /* LP_BLD_INTERP_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index 763432ed712..2de20d6e9a3 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -50,6 +50,46 @@ DEBUG_GET_ONCE_BOOL_OPTION(lp_no_rast, "LP_NO_RAST", FALSE) +/** shared by all contexts */ +unsigned llvmpipe_variant_count; + + +/** + * This function is called by the gallivm "garbage collector" when + * the LLVM global data structures are freed. We must free all LLVM-related + * data. Specifically, all JIT'd shader variants. + */ +static void +garbage_collect_callback(void *cb_data) +{ + struct llvmpipe_context *lp = (struct llvmpipe_context *) cb_data; + struct lp_fs_variant_list_item *li; + + /* Free all the context's shader variants */ + li = first_elem(&lp->fs_variants_list); + while (!at_end(&lp->fs_variants_list, li)) { + struct lp_fs_variant_list_item *next = next_elem(li); + llvmpipe_remove_shader_variant(lp, li->base); + li = next; + } + + /* Free all the context's primitive setup variants */ + lp_delete_setup_variants(lp); + + /* release references to setup variants, shaders */ + lp_setup_set_setup_variant(lp->setup, NULL); + lp_setup_set_fs_variant(lp->setup, NULL); + lp_setup_reset(lp->setup); + + /* This type will be recreated upon demand */ + lp->jit_context_ptr_type = NULL; + + /* mark all state as dirty to ensure new shaders are jit'd, etc. */ + lp->dirty = ~0; +} + + + static void llvmpipe_destroy( struct pipe_context *pipe ) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); @@ -57,6 +97,9 @@ static void llvmpipe_destroy( struct pipe_context *pipe ) lp_print_counters(); + gallivm_remove_garbage_collector_callback(garbage_collect_callback, + llvmpipe); + /* This will also destroy llvmpipe->setup: */ if (llvmpipe->draw) @@ -82,7 +125,7 @@ static void llvmpipe_destroy( struct pipe_context *pipe ) } } - lp_delete_setup_variants(llvmpipe); + gallivm_destroy(llvmpipe->gallivm); align_free( llvmpipe ); } @@ -110,8 +153,10 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) memset(llvmpipe, 0, sizeof *llvmpipe); make_empty_list(&llvmpipe->fs_variants_list); + make_empty_list(&llvmpipe->setup_variants_list); + llvmpipe->pipe.winsys = screen->winsys; llvmpipe->pipe.screen = screen; llvmpipe->pipe.priv = priv; @@ -136,10 +181,12 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe_init_context_resource_funcs( &llvmpipe->pipe ); llvmpipe_init_surface_functions(llvmpipe); + llvmpipe->gallivm = gallivm_create(); + /* * Create drawing context and plug our rendering stage into it. */ - llvmpipe->draw = draw_create(&llvmpipe->pipe); + llvmpipe->draw = draw_create_gallivm(&llvmpipe->pipe, llvmpipe->gallivm); if (!llvmpipe->draw) goto fail; @@ -173,6 +220,9 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) lp_reset_counters(); + gallivm_register_garbage_collector_callback(garbage_collect_callback, + llvmpipe); + return &llvmpipe->pipe; fail: diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index db09c95b272..503f09d810c 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -104,9 +104,18 @@ struct llvmpipe_context { /** Vertex format */ struct vertex_info vertex_info; + /** Which vertex shader output slot contains color */ + int color_slot[2]; + + /** Which vertex shader output slot contains bcolor */ + int bcolor_slot[2]; + /** Which vertex shader output slot contains point size */ int psize_slot; + /**< minimum resolvable depth value, for polygon offset */ + double mrd; + /** The tiling engine */ struct lp_setup_context *setup; struct lp_setup_variant setup_variant; @@ -117,14 +126,27 @@ struct llvmpipe_context { unsigned tex_timestamp; boolean no_rast; + /** List of all fragment shader variants */ struct lp_fs_variant_list_item fs_variants_list; unsigned nr_fs_variants; + /** JIT code generation */ + struct gallivm_state *gallivm; + LLVMTypeRef jit_context_ptr_type; + struct lp_setup_variant_list_item setup_variants_list; unsigned nr_setup_variants; }; +/** + * Fragment and setup variant count, used to trigger garbage collection. + * This is global since all variants in all contexts will be free when + * we do garbage collection. + */ +extern unsigned llvmpipe_variant_count; + + struct pipe_context * llvmpipe_create_context( struct pipe_screen *screen, void *priv ); diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index e2c723b7a87..85e3cdec82c 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -56,6 +56,13 @@ llvmpipe_flush( struct pipe_context *pipe, /* ask the setup module to flush */ lp_setup_flush(llvmpipe->setup, flags, fence, reason); + + if (llvmpipe_variant_count > 1000) { + /* time to do a garbage collection */ + gallivm_garbage_collect(llvmpipe->gallivm); + llvmpipe_variant_count = 0; + } + /* Enable to dump BMPs of the color/depth buffers each frame */ if (0) { if (flags & PIPE_FLUSH_FRAME) { @@ -101,8 +108,8 @@ llvmpipe_finish( struct pipe_context *pipe, boolean llvmpipe_flush_resource(struct pipe_context *pipe, struct pipe_resource *resource, - unsigned face, unsigned level, + int layer, unsigned flush_flags, boolean read_only, boolean cpu_access, @@ -111,7 +118,7 @@ llvmpipe_flush_resource(struct pipe_context *pipe, { unsigned referenced; - referenced = pipe->is_resource_referenced(pipe, resource, face, level); + referenced = pipe->is_resource_referenced(pipe, resource, level, layer); if ((referenced & PIPE_REFERENCED_FOR_WRITE) || ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) { diff --git a/src/gallium/drivers/llvmpipe/lp_flush.h b/src/gallium/drivers/llvmpipe/lp_flush.h index 3626ce4a86c..579d24c68ad 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.h +++ b/src/gallium/drivers/llvmpipe/lp_flush.h @@ -47,8 +47,8 @@ llvmpipe_finish( struct pipe_context *pipe, boolean llvmpipe_flush_resource(struct pipe_context *pipe, struct pipe_resource *resource, - unsigned face, unsigned level, + int layer, unsigned flush_flags, boolean read_only, boolean cpu_access, diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index c540f9b3628..a775990f92a 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -33,82 +33,85 @@ */ -#include <llvm-c/Transforms/Scalar.h> - #include "util/u_memory.h" #include "gallivm/lp_bld_init.h" #include "gallivm/lp_bld_debug.h" -#include "lp_screen.h" #include "gallivm/lp_bld_intr.h" +#include "lp_context.h" +#include "lp_screen.h" #include "lp_jit.h" static void -lp_jit_init_globals(struct llvmpipe_screen *screen) +lp_jit_create_types(struct llvmpipe_context *lp) { + struct gallivm_state *gallivm = lp->gallivm; + LLVMContextRef lc = gallivm->context; LLVMTypeRef texture_type; /* struct lp_jit_texture */ { LLVMTypeRef elem_types[LP_JIT_TEXTURE_NUM_FIELDS]; - elem_types[LP_JIT_TEXTURE_WIDTH] = LLVMInt32Type(); - elem_types[LP_JIT_TEXTURE_HEIGHT] = LLVMInt32Type(); - elem_types[LP_JIT_TEXTURE_DEPTH] = LLVMInt32Type(); - elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type(); + elem_types[LP_JIT_TEXTURE_WIDTH] = + elem_types[LP_JIT_TEXTURE_HEIGHT] = + elem_types[LP_JIT_TEXTURE_DEPTH] = + elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32TypeInContext(lc); elem_types[LP_JIT_TEXTURE_ROW_STRIDE] = - LLVMArrayType(LLVMInt32Type(), LP_MAX_TEXTURE_LEVELS); elem_types[LP_JIT_TEXTURE_IMG_STRIDE] = - LLVMArrayType(LLVMInt32Type(), LP_MAX_TEXTURE_LEVELS); + LLVMArrayType(LLVMInt32TypeInContext(lc), LP_MAX_TEXTURE_LEVELS); elem_types[LP_JIT_TEXTURE_DATA] = - LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0), + LLVMArrayType(LLVMPointerType(LLVMInt8TypeInContext(lc), 0), LP_MAX_TEXTURE_LEVELS); - elem_types[LP_JIT_TEXTURE_MIN_LOD] = LLVMFloatType(); - elem_types[LP_JIT_TEXTURE_MAX_LOD] = LLVMFloatType(); - elem_types[LP_JIT_TEXTURE_LOD_BIAS] = LLVMFloatType(); + elem_types[LP_JIT_TEXTURE_MIN_LOD] = + elem_types[LP_JIT_TEXTURE_MAX_LOD] = + elem_types[LP_JIT_TEXTURE_LOD_BIAS] = LLVMFloatTypeInContext(lc); elem_types[LP_JIT_TEXTURE_BORDER_COLOR] = - LLVMArrayType(LLVMFloatType(), 4); + LLVMArrayType(LLVMFloatTypeInContext(lc), 4); - texture_type = LLVMStructType(elem_types, Elements(elem_types), 0); + texture_type = LLVMStructTypeInContext(lc, elem_types, + Elements(elem_types), 0); + + LLVMInvalidateStructLayout(gallivm->target, texture_type); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, width, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_WIDTH); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, height, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_HEIGHT); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, depth, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_DEPTH); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, last_level, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_LAST_LEVEL); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, row_stride, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_ROW_STRIDE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, img_stride, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_IMG_STRIDE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, data, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_DATA); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, min_lod, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_MIN_LOD); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, max_lod, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_MAX_LOD); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, lod_bias, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_LOD_BIAS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, border_color, - screen->target, texture_type, + gallivm->target, texture_type, LP_JIT_TEXTURE_BORDER_COLOR); LP_CHECK_STRUCT_SIZE(struct lp_jit_texture, - screen->target, texture_type); + gallivm->target, texture_type); - LLVMAddTypeName(screen->module, "texture", texture_type); + LLVMAddTypeName(gallivm->module, "texture", texture_type); } /* struct lp_jit_context */ @@ -116,44 +119,47 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) LLVMTypeRef elem_types[LP_JIT_CTX_COUNT]; LLVMTypeRef context_type; - elem_types[LP_JIT_CTX_CONSTANTS] = LLVMPointerType(LLVMFloatType(), 0); - elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatType(); - elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = LLVMInt32Type(); - elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32Type(); - elem_types[LP_JIT_CTX_BLEND_COLOR] = LLVMPointerType(LLVMInt8Type(), 0); + elem_types[LP_JIT_CTX_CONSTANTS] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0); + elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatTypeInContext(lc); + elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = + elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc); + elem_types[LP_JIT_CTX_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0); elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); - context_type = LLVMStructType(elem_types, Elements(elem_types), 0); + context_type = LLVMStructTypeInContext(lc, elem_types, + Elements(elem_types), 0); + + LLVMInvalidateStructLayout(gallivm->target, context_type); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants, - screen->target, context_type, + gallivm->target, context_type, LP_JIT_CTX_CONSTANTS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value, - screen->target, context_type, + gallivm->target, context_type, LP_JIT_CTX_ALPHA_REF); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_front, - screen->target, context_type, + gallivm->target, context_type, LP_JIT_CTX_STENCIL_REF_FRONT); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_back, - screen->target, context_type, + gallivm->target, context_type, LP_JIT_CTX_STENCIL_REF_BACK); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color, - screen->target, context_type, + gallivm->target, context_type, LP_JIT_CTX_BLEND_COLOR); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures, - screen->target, context_type, + gallivm->target, context_type, LP_JIT_CTX_TEXTURES); LP_CHECK_STRUCT_SIZE(struct lp_jit_context, - screen->target, context_type); + gallivm->target, context_type); - LLVMAddTypeName(screen->module, "context", context_type); + LLVMAddTypeName(gallivm->module, "context", context_type); - screen->context_ptr_type = LLVMPointerType(context_type, 0); + lp->jit_context_ptr_type = LLVMPointerType(context_type, 0); } if (gallivm_debug & GALLIVM_DEBUG_IR) { - LLVMDumpModule(screen->module); + LLVMDumpModule(gallivm->module); } } @@ -161,8 +167,7 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) void lp_jit_screen_cleanup(struct llvmpipe_screen *screen) { - if(screen->pass) - LLVMDisposePassManager(screen->pass); + /* nothing */ } @@ -170,30 +175,14 @@ void lp_jit_screen_init(struct llvmpipe_screen *screen) { lp_build_init(); +} - screen->module = lp_build_module; - screen->provider = lp_build_provider; - screen->engine = lp_build_engine; - screen->target = lp_build_target; - - screen->pass = LLVMCreateFunctionPassManager(screen->provider); - LLVMAddTargetData(screen->target, screen->pass); - - if ((gallivm_debug & GALLIVM_DEBUG_NO_OPT) == 0) { - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - /* TODO: Add more passes */ - LLVMAddCFGSimplificationPass(screen->pass); - LLVMAddPromoteMemoryToRegisterPass(screen->pass); - LLVMAddConstantPropagationPass(screen->pass); - LLVMAddInstructionCombiningPass(screen->pass); - LLVMAddGVNPass(screen->pass); - } else { - /* We need at least this pass to prevent the backends to fail in - * unexpected ways. - */ - LLVMAddPromoteMemoryToRegisterPass(screen->pass); - } - lp_jit_init_globals(screen); +LLVMTypeRef +lp_jit_get_context_type(struct llvmpipe_context *lp) +{ + if (!lp->jit_context_ptr_type) + lp_jit_create_types(lp); + + return lp->jit_context_ptr_type; } diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 114f21f2d16..a6763dce17a 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -120,23 +120,23 @@ enum { }; -#define lp_jit_context_constants(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_CONSTANTS, "constants") +#define lp_jit_context_constants(_gallivm, _ptr) \ + lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_CONSTANTS, "constants") -#define lp_jit_context_alpha_ref_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_ALPHA_REF, "alpha_ref_value") +#define lp_jit_context_alpha_ref_value(_gallivm, _ptr) \ + lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_ALPHA_REF, "alpha_ref_value") -#define lp_jit_context_stencil_ref_front_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_FRONT, "stencil_ref_front") +#define lp_jit_context_stencil_ref_front_value(_gallivm, _ptr) \ + lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_STENCIL_REF_FRONT, "stencil_ref_front") -#define lp_jit_context_stencil_ref_back_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_BACK, "stencil_ref_back") +#define lp_jit_context_stencil_ref_back_value(_gallivm, _ptr) \ + lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_STENCIL_REF_BACK, "stencil_ref_back") -#define lp_jit_context_blend_color(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_BLEND_COLOR, "blend_color") +#define lp_jit_context_blend_color(_gallivm, _ptr) \ + lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_BLEND_COLOR, "blend_color") -#define lp_jit_context_textures(_builder, _ptr) \ - lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CTX_TEXTURES, "textures") +#define lp_jit_context_textures(_gallivm, _ptr) \ + lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_TEXTURES, "textures") @@ -162,4 +162,8 @@ void lp_jit_screen_init(struct llvmpipe_screen *screen); +LLVMTypeRef +lp_jit_get_context_type(struct llvmpipe_context *lp); + + #endif /* LP_JIT_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index decf3bd4499..dafadc1ea9b 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -47,6 +47,7 @@ #ifdef DEBUG int jit_line = 0; const struct lp_rast_state *jit_state = NULL; +const struct lp_rasterizer_task *jit_task = NULL; #endif @@ -119,8 +120,8 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, * and update the tile's layout info. */ (void) llvmpipe_get_texture_tile(lpt, - zsbuf->face + zsbuf->zslice, - zsbuf->level, + zsbuf->u.tex.first_layer, + zsbuf->u.tex.level, usage, task->x, task->y); @@ -288,7 +289,6 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, - /** * Convert the color tile from tiled to linear layout. * This is generally only done when we're flushing the scene just prior to @@ -306,15 +306,15 @@ lp_rast_store_linear_color( struct lp_rasterizer_task *task ) for (buf = 0; buf < scene->fb.nr_cbufs; buf++) { struct pipe_surface *cbuf = scene->fb.cbufs[buf]; - const unsigned face_slice = cbuf->face + cbuf->zslice; - const unsigned level = cbuf->level; + const unsigned layer = cbuf->u.tex.first_layer; + const unsigned level = cbuf->u.tex.level; struct llvmpipe_resource *lpt = llvmpipe_resource(cbuf->texture); if (!task->color_tiles[buf]) continue; llvmpipe_unswizzle_cbuf_tile(lpt, - face_slice, + layer, level, task->x, task->y, task->color_tiles[buf]); @@ -362,7 +362,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task, depth = lp_rast_get_depth_block_pointer(task, tile_x + x, tile_y + y); /* run shader on 4x4 block */ - BEGIN_JIT_CALL(state); + BEGIN_JIT_CALL(state, task); variant->jit_function[RAST_WHOLE]( &state->jit_context, tile_x + x, tile_y + y, inputs->frontfacing, @@ -443,7 +443,7 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task, assert(lp_check_alignment(state->jit_context.blend_color, 16)); /* run shader on 4x4 block */ - BEGIN_JIT_CALL(state); + BEGIN_JIT_CALL(state, task); variant->jit_function[RAST_EDGE_TEST](&state->jit_context, x, y, inputs->frontfacing, diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index b30408f097b..cd686bc82c1 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -45,13 +45,16 @@ */ #ifdef DEBUG +struct lp_rasterizer_task; extern int jit_line; extern const struct lp_rast_state *jit_state; +extern const struct lp_rasterizer_task *jit_task; -#define BEGIN_JIT_CALL(state) \ +#define BEGIN_JIT_CALL(state, task) \ do { \ jit_line = __LINE__; \ jit_state = state; \ + jit_task = task; \ } while (0) #define END_JIT_CALL() \ @@ -62,7 +65,7 @@ extern const struct lp_rast_state *jit_state; #else -#define BEGIN_JIT_CALL(X) +#define BEGIN_JIT_CALL(X, Y) #define END_JIT_CALL() #endif @@ -191,8 +194,8 @@ lp_rast_get_color_tile_pointer(struct lp_rasterizer_task *task, if (usage != LP_TEX_USAGE_WRITE_ALL) { llvmpipe_swizzle_cbuf_tile(lpt, - cbuf->face + cbuf->zslice, - cbuf->level, + cbuf->u.tex.first_layer, + cbuf->u.tex.level, task->x, task->y, task->color_tiles[buf]); } @@ -258,7 +261,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task, depth = lp_rast_get_depth_block_pointer(task, x, y); /* run shader on 4x4 block */ - BEGIN_JIT_CALL(state); + BEGIN_JIT_CALL(state, task); variant->jit_function[RAST_WHOLE]( &state->jit_context, x, y, inputs->frontfacing, diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index a4fdf7cff36..5d0f5f8b7b5 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -74,6 +74,7 @@ lp_scene_create( struct pipe_context *pipe ) void lp_scene_destroy(struct lp_scene *scene) { + lp_fence_reference(&scene->fence, NULL); pipe_mutex_destroy(scene->mutex); assert(scene->data.head->next == NULL); FREE(scene->data.head); @@ -136,30 +137,30 @@ lp_scene_begin_rasterization(struct lp_scene *scene) int i; //LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); - + for (i = 0; i < scene->fb.nr_cbufs; i++) { struct pipe_surface *cbuf = scene->fb.cbufs[i]; + assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer); scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture, - cbuf->level); + cbuf->u.tex.level); scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture, - cbuf->face, - cbuf->level, - cbuf->zslice, + cbuf->u.tex.level, + cbuf->u.tex.first_layer, LP_TEX_USAGE_READ_WRITE, LP_TEX_LAYOUT_LINEAR); } if (fb->zsbuf) { struct pipe_surface *zsbuf = scene->fb.zsbuf; - scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->level); + assert(zsbuf->u.tex.first_layer == zsbuf->u.tex.last_layer); + scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->u.tex.level); scene->zsbuf.blocksize = util_format_get_blocksize(zsbuf->texture->format); scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture, - zsbuf->face, - zsbuf->level, - zsbuf->zslice, + zsbuf->u.tex.level, + zsbuf->u.tex.first_layer, LP_TEX_USAGE_READ_WRITE, LP_TEX_LAYOUT_NONE); } @@ -181,9 +182,8 @@ lp_scene_end_rasterization(struct lp_scene *scene ) if (scene->cbufs[i].map) { struct pipe_surface *cbuf = scene->fb.cbufs[i]; llvmpipe_resource_unmap(cbuf->texture, - cbuf->face, - cbuf->level, - cbuf->zslice); + cbuf->u.tex.level, + cbuf->u.tex.first_layer); scene->cbufs[i].map = NULL; } } @@ -192,9 +192,8 @@ lp_scene_end_rasterization(struct lp_scene *scene ) if (scene->zsbuf.map) { struct pipe_surface *zsbuf = scene->fb.zsbuf; llvmpipe_resource_unmap(zsbuf->texture, - zsbuf->face, - zsbuf->level, - zsbuf->zslice); + zsbuf->u.tex.level, + zsbuf->u.tex.first_layer); scene->zsbuf.map = NULL; } diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index ad0ea75b3a3..9459a3cd113 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -287,12 +287,13 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, static void llvmpipe_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_surface *surface, + struct pipe_resource *resource, + unsigned level, unsigned layer, void *context_private) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); struct sw_winsys *winsys = screen->winsys; - struct llvmpipe_resource *texture = llvmpipe_resource(surface->texture); + struct llvmpipe_resource *texture = llvmpipe_resource(resource); assert(texture->dt); if (texture->dt) diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h index 731526dfabe..7f69a11a6e3 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.h +++ b/src/gallium/drivers/llvmpipe/lp_screen.h @@ -34,12 +34,10 @@ #ifndef LP_SCREEN_H #define LP_SCREEN_H -#include "gallivm/lp_bld.h" -#include <llvm-c/ExecutionEngine.h> - -#include "os/os_thread.h" #include "pipe/p_screen.h" #include "pipe/p_defines.h" +#include "os/os_thread.h" +#include "gallivm/lp_bld.h" struct sw_winsys; @@ -51,14 +49,6 @@ struct llvmpipe_screen struct sw_winsys *winsys; - LLVMModuleRef module; - LLVMExecutionEngineRef engine; - LLVMModuleProviderRef provider; - LLVMTargetDataRef target; - LLVMPassManagerRef pass; - - LLVMTypeRef context_ptr_type; - unsigned num_threads; /* Increments whenever textures are modified. Contexts can track this. diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 6118434d3d3..5d83a1e3579 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -114,7 +114,7 @@ first_point( struct lp_setup_context *setup, setup->point( setup, v0 ); } -static void lp_setup_reset( struct lp_setup_context *setup ) +void lp_setup_reset( struct lp_setup_context *setup ) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -263,7 +263,6 @@ execute_clears( struct lp_setup_context *setup ) const char *states[] = { "FLUSHED", - "EMPTY ", "CLEARED", "ACTIVE " }; @@ -913,6 +912,12 @@ lp_setup_update_state( struct lp_setup_context *setup, llvmpipe_update_derived(lp); } + if (lp->setup->dirty) { + llvmpipe_update_setup(lp); + } + + assert(setup->setup.variant); + /* Will probably need to move this somewhere else, just need * to know about vertex shader point size attribute. */ @@ -928,7 +933,7 @@ lp_setup_update_state( struct lp_setup_context *setup, setup->setup.variant->key.size) == 0); } - if (update_scene) { + if (update_scene && setup->state != SETUP_ACTIVE) { if (!set_scene_state( setup, SETUP_ACTIVE, __FUNCTION__ )) return FALSE; } @@ -991,6 +996,8 @@ lp_setup_destroy( struct lp_setup_context *setup ) lp_scene_destroy(scene); } + lp_fence_reference(&setup->last_fence, NULL); + FREE( setup ); } diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index ebb18f81344..0d6e161a218 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -45,6 +45,9 @@ struct lp_jit_context; struct llvmpipe_query; struct pipe_fence_handle; struct lp_setup_variant; +struct lp_setup_context; + +void lp_setup_reset( struct lp_setup_context *setup ); struct lp_setup_context * lp_setup_create( struct pipe_context *pipe, diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c index 9c1f0fe7939..384242f81d7 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c @@ -141,6 +141,8 @@ lp_setup_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr) const boolean flatshade_first = setup->flatshade_first; unsigned i; + assert(setup->setup.variant); + if (!lp_setup_update_state(setup, TRUE)) return; diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 0f5f7369e04..8725ea39fe9 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -53,6 +53,11 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe) unsigned vs_index; uint i; + llvmpipe->color_slot[0] = ~0; + llvmpipe->color_slot[1] = ~0; + llvmpipe->bcolor_slot[0] = ~0; + llvmpipe->bcolor_slot[1] = ~0; + /* * Match FS inputs against VS outputs, emitting the necessary * attributes. Could cache these structs and look them up with a @@ -76,12 +81,31 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe) lpfs->info.base.input_semantic_name[i], lpfs->info.base.input_semantic_index[i]); + if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_COLOR && + lpfs->info.base.input_semantic_index[i] < 2) { + int idx = lpfs->info.base.input_semantic_index[i]; + llvmpipe->color_slot[idx] = vinfo->num_attribs; + } + /* * Emit the requested fs attribute for all but position. */ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); } + /* Figure out if we need bcolor as well. + */ + for (i = 0; i < 2; i++) { + vs_index = draw_find_shader_output(llvmpipe->draw, + TGSI_SEMANTIC_BCOLOR, i); + + if (vs_index > 0) { + llvmpipe->bcolor_slot[i] = vinfo->num_attribs; + draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); + } + } + + /* Figure out if we need pointsize as well. */ vs_index = draw_find_shader_output(llvmpipe->draw, diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 48971510f21..2c4943a69f6 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -102,10 +102,10 @@ #include <llvm-c/BitWriter.h> +/** Fragment shader number (for debugging) */ static unsigned fs_no = 0; - /** * Expand the relevent bits of mask_input to a 4-dword mask for the * four pixels in a 2x2 quad. This will set the four elements of the @@ -115,13 +115,14 @@ static unsigned fs_no = 0; * \param mask_input bitwise mask for the whole 4x4 stamp */ static LLVMValueRef -generate_quad_mask(LLVMBuilderRef builder, +generate_quad_mask(struct gallivm_state *gallivm, struct lp_type fs_type, unsigned quad, LLVMValueRef mask_input) /* int32 */ { + LLVMBuilderRef builder = gallivm->builder; struct lp_type mask_type; - LLVMTypeRef i32t = LLVMInt32Type(); + LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context); LLVMValueRef bits[4]; LLVMValueRef mask; int shift; @@ -136,7 +137,6 @@ generate_quad_mask(LLVMBuilderRef builder, /* * mask_input >>= (quad * 4) */ - switch (quad) { case 0: shift = 0; @@ -163,8 +163,9 @@ generate_quad_mask(LLVMBuilderRef builder, /* * mask = { mask_input & (1 << i), for i in [0,3] } */ - - mask = lp_build_broadcast(builder, lp_build_vec_type(mask_type), mask_input); + mask = lp_build_broadcast(gallivm, + lp_build_vec_type(gallivm, mask_type), + mask_input); bits[0] = LLVMConstInt(i32t, 1 << 0, 0); bits[1] = LLVMConstInt(i32t, 1 << 1, 0); @@ -176,11 +177,10 @@ generate_quad_mask(LLVMBuilderRef builder, /* * mask = mask != 0 ? ~0 : 0 */ - - mask = lp_build_compare(builder, + mask = lp_build_compare(gallivm, mask_type, PIPE_FUNC_NOTEQUAL, mask, - lp_build_const_int_vec(mask_type, 0)); + lp_build_const_int_vec(gallivm, mask_type, 0)); return mask; } @@ -213,7 +213,8 @@ find_output_by_semantic( const struct tgsi_shader_info *info, * \param partial_mask if 1, do mask_input testing */ static void -generate_fs(struct lp_fragment_shader *shader, +generate_fs(struct gallivm_state *gallivm, + struct lp_fragment_shader *shader, const struct lp_fragment_shader_variant_key *key, LLVMBuilderRef builder, struct lp_type type, @@ -278,42 +279,42 @@ generate_fs(struct lp_fragment_shader *shader, assert(i < 4); - stencil_refs[0] = lp_jit_context_stencil_ref_front_value(builder, context_ptr); - stencil_refs[1] = lp_jit_context_stencil_ref_back_value(builder, context_ptr); + stencil_refs[0] = lp_jit_context_stencil_ref_front_value(gallivm, context_ptr); + stencil_refs[1] = lp_jit_context_stencil_ref_back_value(gallivm, context_ptr); - vec_type = lp_build_vec_type(type); + vec_type = lp_build_vec_type(gallivm, type); - consts_ptr = lp_jit_context_constants(builder, context_ptr); + consts_ptr = lp_jit_context_constants(gallivm, context_ptr); memset(outputs, 0, sizeof outputs); /* Declare the color and z variables */ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { for(chan = 0; chan < NUM_CHANNELS; ++chan) { - color[cbuf][chan] = lp_build_alloca(builder, vec_type, "color"); + color[cbuf][chan] = lp_build_alloca(gallivm, vec_type, "color"); } } /* do triangle edge testing */ if (partial_mask) { - *pmask = generate_quad_mask(builder, type, + *pmask = generate_quad_mask(gallivm, type, i, mask_input); } else { - *pmask = lp_build_const_int_vec(type, ~0); + *pmask = lp_build_const_int_vec(gallivm, type, ~0); } /* 'mask' will control execution based on quad's pixel alive/killed state */ - lp_build_mask_begin(&mask, builder, type, *pmask); + lp_build_mask_begin(&mask, gallivm, type, *pmask); if (!(depth_mode & EARLY_DEPTH_TEST) && !simple_shader) lp_build_mask_check(&mask); - lp_build_interp_soa_update_pos(interp, i); + lp_build_interp_soa_update_pos(interp, gallivm, i); z = interp->pos[2]; if (depth_mode & EARLY_DEPTH_TEST) { - lp_build_depth_stencil_test(builder, + lp_build_depth_stencil_test(gallivm, &key->depth, key->stencil, type, @@ -330,14 +331,13 @@ generate_fs(struct lp_fragment_shader *shader, } } - lp_build_interp_soa_update_inputs(interp, i); + lp_build_interp_soa_update_inputs(interp, gallivm, i); /* Build the actual shader */ - lp_build_tgsi_soa(builder, tokens, type, &mask, + lp_build_tgsi_soa(gallivm, tokens, type, &mask, consts_ptr, interp->pos, interp->inputs, outputs, sampler, &shader->info.base); - /* Alpha test */ if (key->alpha.enabled) { int color0 = find_output_by_semantic(&shader->info.base, @@ -348,10 +348,10 @@ generate_fs(struct lp_fragment_shader *shader, LLVMValueRef alpha = LLVMBuildLoad(builder, outputs[color0][3], "alpha"); LLVMValueRef alpha_ref_value; - alpha_ref_value = lp_jit_context_alpha_ref_value(builder, context_ptr); - alpha_ref_value = lp_build_broadcast(builder, vec_type, alpha_ref_value); + alpha_ref_value = lp_jit_context_alpha_ref_value(gallivm, context_ptr); + alpha_ref_value = lp_build_broadcast(gallivm, vec_type, alpha_ref_value); - lp_build_alpha_test(builder, key->alpha.func, type, + lp_build_alpha_test(gallivm, key->alpha.func, type, &mask, alpha, alpha_ref_value, (depth_mode & LATE_DEPTH_TEST) != 0); } @@ -367,7 +367,7 @@ generate_fs(struct lp_fragment_shader *shader, z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z"); } - lp_build_depth_stencil_test(builder, + lp_build_depth_stencil_test(gallivm, &key->depth, key->stencil, type, @@ -390,7 +390,7 @@ generate_fs(struct lp_fragment_shader *shader, * depth value, update from zs_value with the new mask value and * write that out. */ - lp_build_deferred_depth_write(builder, + lp_build_deferred_depth_write(gallivm, type, zs_format_desc, &mask, @@ -420,7 +420,7 @@ generate_fs(struct lp_fragment_shader *shader, } if (counter) - lp_build_occlusion_count(builder, type, + lp_build_occlusion_count(gallivm, type, lp_build_mask_value(&mask), counter); *pmask = lp_build_mask_end(&mask); @@ -437,7 +437,8 @@ generate_fs(struct lp_fragment_shader *shader, * \param dst_ptr the destination color buffer pointer */ static void -generate_blend(const struct pipe_blend_state *blend, +generate_blend(struct gallivm_state *gallivm, + const struct pipe_blend_state *blend, unsigned rt, LLVMBuilderRef builder, struct lp_type type, @@ -456,21 +457,21 @@ generate_blend(const struct pipe_blend_state *blend, LLVMValueRef res[4]; unsigned chan; - lp_build_context_init(&bld, builder, type); + lp_build_context_init(&bld, gallivm, type); - lp_build_mask_begin(&mask_ctx, builder, type, mask); + lp_build_mask_begin(&mask_ctx, gallivm, type, mask); if (do_branch) lp_build_mask_check(&mask_ctx); - vec_type = lp_build_vec_type(type); + vec_type = lp_build_vec_type(gallivm, type); - const_ptr = lp_jit_context_blend_color(builder, context_ptr); + const_ptr = lp_jit_context_blend_color(gallivm, context_ptr); const_ptr = LLVMBuildBitCast(builder, const_ptr, LLVMPointerType(vec_type, 0), ""); /* load constant blend color and colors from the dest color buffer */ for(chan = 0; chan < 4; ++chan) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); + LLVMValueRef index = lp_build_const_int32(gallivm, chan); con[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), ""); dst[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), ""); @@ -480,12 +481,12 @@ generate_blend(const struct pipe_blend_state *blend, } /* do blend */ - lp_build_blend_soa(builder, blend, type, rt, src, dst, con, res); + lp_build_blend_soa(gallivm, blend, type, rt, src, dst, con, res); /* store results to color buffer */ for(chan = 0; chan < 4; ++chan) { if(blend->rt[rt].colormask & (1 << chan)) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); + LLVMValueRef index = lp_build_const_int32(gallivm, chan); lp_build_name(res[chan], "res.%c", "rgba"[chan]); res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]); LLVMBuildStore(builder, res[chan], LLVMBuildGEP(builder, dst_ptr, &index, 1, "")); @@ -503,11 +504,12 @@ generate_blend(const struct pipe_blend_state *blend, * 2x2 pixels. */ static void -generate_fragment(struct llvmpipe_screen *screen, +generate_fragment(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, struct lp_fragment_shader_variant *variant, unsigned partial_mask) { + struct gallivm_state *gallivm = lp->gallivm; const struct lp_fragment_shader_variant_key *key = &variant->key; struct lp_shader_input inputs[PIPE_MAX_SHADER_INPUTS]; char func_name[256]; @@ -518,6 +520,8 @@ generate_fragment(struct llvmpipe_screen *screen, LLVMTypeRef blend_vec_type; LLVMTypeRef arg_types[11]; LLVMTypeRef func_type; + LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context); + LLVMTypeRef int8_type = LLVMInt8TypeInContext(gallivm->context); LLVMValueRef context_ptr; LLVMValueRef x; LLVMValueRef y; @@ -579,29 +583,30 @@ generate_fragment(struct llvmpipe_screen *screen, * lp_jit.h's lp_jit_frag_func function pointer type, and vice-versa. */ - fs_elem_type = lp_build_elem_type(fs_type); - fs_int_vec_type = lp_build_int_vec_type(fs_type); + fs_elem_type = lp_build_elem_type(gallivm, fs_type); + fs_int_vec_type = lp_build_int_vec_type(gallivm, fs_type); - blend_vec_type = lp_build_vec_type(blend_type); + blend_vec_type = lp_build_vec_type(gallivm, blend_type); util_snprintf(func_name, sizeof(func_name), "fs%u_variant%u_%s", shader->no, variant->no, partial_mask ? "partial" : "whole"); - arg_types[0] = screen->context_ptr_type; /* context */ - arg_types[1] = LLVMInt32Type(); /* x */ - arg_types[2] = LLVMInt32Type(); /* y */ - arg_types[3] = LLVMInt32Type(); /* facing */ + arg_types[0] = lp_jit_get_context_type(lp); /* context */ + arg_types[1] = int32_type; /* x */ + arg_types[2] = int32_type; /* y */ + arg_types[3] = int32_type; /* facing */ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* a0 */ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dadx */ arg_types[6] = LLVMPointerType(fs_elem_type, 0); /* dady */ arg_types[7] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ - arg_types[8] = LLVMPointerType(LLVMInt8Type(), 0); /* depth */ - arg_types[9] = LLVMInt32Type(); /* mask_input */ - arg_types[10] = LLVMPointerType(LLVMInt32Type(), 0);/* counter */ + arg_types[8] = LLVMPointerType(int8_type, 0); /* depth */ + arg_types[9] = int32_type; /* mask_input */ + arg_types[10] = LLVMPointerType(int32_type, 0); /* counter */ - func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); + func_type = LLVMFunctionType(LLVMVoidTypeInContext(gallivm->context), + arg_types, Elements(arg_types), 0); - function = LLVMAddFunction(screen->module, func_name, func_type); + function = LLVMAddFunction(gallivm->module, func_name, func_type); LLVMSetFunctionCallConv(function, LLVMCCallConv); variant->function[partial_mask] = function; @@ -643,8 +648,9 @@ generate_fragment(struct llvmpipe_screen *screen, * Function body */ - block = LLVMAppendBasicBlock(function, "entry"); - builder = LLVMCreateBuilder(); + block = LLVMAppendBasicBlockInContext(gallivm->context, function, "entry"); + builder = gallivm->builder; + assert(builder); LLVMPositionBuilderAtEnd(builder, block); /* @@ -653,6 +659,7 @@ generate_fragment(struct llvmpipe_screen *screen, * already included in the shader key. */ lp_build_interp_soa_init(&interp, + gallivm, shader->info.base.num_inputs, inputs, builder, fs_type, @@ -666,7 +673,7 @@ generate_fragment(struct llvmpipe_screen *screen, zs_format_desc = util_format_description(key->zsbuf_format); for(i = 0; i < num_fs; ++i) { - LLVMValueRef depth_offset = LLVMConstInt(LLVMInt32Type(), + LLVMValueRef depth_offset = LLVMConstInt(int32_type, i*fs_type.length*zs_format_desc->block.bits/8, 0); LLVMValueRef out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS]; @@ -674,7 +681,8 @@ generate_fragment(struct llvmpipe_screen *screen, depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &depth_offset, 1, ""); - generate_fs(shader, key, + generate_fs(gallivm, + shader, key, builder, fs_type, context_ptr, @@ -700,7 +708,7 @@ generate_fragment(struct llvmpipe_screen *screen, */ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { LLVMValueRef color_ptr; - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), cbuf, 0); + LLVMValueRef index = lp_build_const_int32(gallivm, cbuf); LLVMValueRef blend_in_color[NUM_CHANNELS]; unsigned rt; @@ -715,7 +723,7 @@ generate_fragment(struct llvmpipe_screen *screen, LLVMBuildLoad(builder, fs_out_color[cbuf][chan][i], "fs_color_vals"); } - lp_build_conv(builder, fs_type, blend_type, + lp_build_conv(gallivm, fs_type, blend_type, fs_color_vals, num_fs, &blend_in_color[chan], 1); @@ -724,11 +732,11 @@ generate_fragment(struct llvmpipe_screen *screen, } if (partial_mask || !variant->opaque) { - lp_build_conv_mask(builder, fs_type, blend_type, + lp_build_conv_mask(lp->gallivm, fs_type, blend_type, fs_mask, num_fs, &blend_mask, 1); } else { - blend_mask = lp_build_const_int_vec(blend_type, ~0); + blend_mask = lp_build_const_int_vec(lp->gallivm, blend_type, ~0); } color_ptr = LLVMBuildLoad(builder, @@ -749,7 +757,8 @@ generate_fragment(struct llvmpipe_screen *screen, !key->alpha.enabled && !shader->info.base.uses_kill); - generate_blend(&key->blend, + generate_blend(lp->gallivm, + &key->blend, rt, builder, blend_type, @@ -763,9 +772,6 @@ generate_fragment(struct llvmpipe_screen *screen, LLVMBuildRetVoid(builder); - LLVMDisposeBuilder(builder); - - /* Verify the LLVM IR. If invalid, dump and abort */ #ifdef DEBUG if(LLVMVerifyFunction(function, LLVMPrintMessageAction)) { @@ -776,7 +782,7 @@ generate_fragment(struct llvmpipe_screen *screen, #endif /* Apply optimizations to LLVM IR */ - LLVMRunFunctionPassManager(screen->pass, function); + LLVMRunFunctionPassManager(gallivm->passmgr, function); if ((gallivm_debug & GALLIVM_DEBUG_IR) || (LP_DEBUG & DEBUG_FS)) { /* Print the LLVM IR to stderr */ @@ -786,14 +792,14 @@ generate_fragment(struct llvmpipe_screen *screen, /* Dump byte code to a file */ if (0) { - LLVMWriteBitcodeToFile(lp_build_module, "llvmpipe.bc"); + LLVMWriteBitcodeToFile(gallivm->module, "llvmpipe.bc"); } /* * Translate the LLVM IR into machine code. */ { - void *f = LLVMGetPointerToGlobal(screen->engine, function); + void *f = LLVMGetPointerToGlobal(gallivm->engine, function); variant->jit_function[partial_mask] = (lp_jit_frag_func)pointer_to_func(f); @@ -897,8 +903,13 @@ lp_debug_fs_variant(const struct lp_fragment_shader_variant *variant) debug_printf("\n"); } + +/** + * Generate a new fragment shader variant from the shader code and + * other state indicated by the key. + */ static struct lp_fragment_shader_variant * -generate_variant(struct llvmpipe_screen *screen, +generate_variant(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, const struct lp_fragment_shader_variant_key *key) { @@ -944,11 +955,11 @@ generate_variant(struct llvmpipe_screen *screen, lp_debug_fs_variant(variant); } - generate_fragment(screen, shader, variant, RAST_EDGE_TEST); + generate_fragment(lp, shader, variant, RAST_EDGE_TEST); if (variant->opaque) { /* Specialized shader, which doesn't need to read the color buffer. */ - generate_fragment(screen, shader, variant, RAST_WHOLE); + generate_fragment(lp, shader, variant, RAST_WHOLE); } else { variant->jit_function[RAST_WHOLE] = variant->jit_function[RAST_EDGE_TEST]; } @@ -1033,7 +1044,8 @@ llvmpipe_create_fs_state(struct pipe_context *pipe, if (LP_DEBUG & DEBUG_TGSI) { unsigned attrib; - debug_printf("llvmpipe: Create fragment shader #%u %p:\n", shader->no, (void *) shader); + debug_printf("llvmpipe: Create fragment shader #%u %p:\n", + shader->no, (void *) shader); tgsi_dump(templ->tokens, 0); debug_printf("usage masks:\n"); for (attrib = 0; attrib < shader->info.base.num_inputs; ++attrib) { @@ -1070,33 +1082,49 @@ llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs) llvmpipe->dirty |= LP_NEW_FS; } -static void -remove_shader_variant(struct llvmpipe_context *lp, - struct lp_fragment_shader_variant *variant) + +/** + * Remove shader variant from two lists: the shader's variant list + * and the context's variant list. + */ +void +llvmpipe_remove_shader_variant(struct llvmpipe_context *lp, + struct lp_fragment_shader_variant *variant) { - struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); unsigned i; if (gallivm_debug & GALLIVM_DEBUG_IR) { - debug_printf("llvmpipe: del fs #%u var #%u v created #%u v cached #%u v total cached #%u\n", - variant->shader->no, variant->no, variant->shader->variants_created, - variant->shader->variants_cached, lp->nr_fs_variants); + debug_printf("llvmpipe: del fs #%u var #%u v created #%u v cached" + " #%u v total cached #%u\n", + variant->shader->no, + variant->no, + variant->shader->variants_created, + variant->shader->variants_cached, + lp->nr_fs_variants); } + + /* free all the variant's JIT'd functions */ for (i = 0; i < Elements(variant->function); i++) { if (variant->function[i]) { if (variant->jit_function[i]) - LLVMFreeMachineCodeForFunction(screen->engine, + LLVMFreeMachineCodeForFunction(lp->gallivm->engine, variant->function[i]); LLVMDeleteFunction(variant->function[i]); } } + + /* remove from shader's list */ remove_from_list(&variant->list_item_local); variant->shader->variants_cached--; + + /* remove from context's list */ remove_from_list(&variant->list_item_global); lp->nr_fs_variants--; + FREE(variant); } + static void llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { @@ -1105,23 +1133,23 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) struct lp_fs_variant_list_item *li; assert(fs != llvmpipe->fs); - (void) llvmpipe; /* * XXX: we need to flush the context until we have some sort of reference * counting in fragment shaders as they may still be binned * Flushing alone might not sufficient we need to wait on it too. */ - llvmpipe_finish(pipe, __FUNCTION__); + /* Delete all the variants */ li = first_elem(&shader->variants); while(!at_end(&shader->variants, li)) { struct lp_fs_variant_list_item *next = next_elem(li); - remove_shader_variant(llvmpipe, li->base); + llvmpipe_remove_shader_variant(llvmpipe, li->base); li = next; } + /* Delete draw module's data */ draw_delete_fragment_shader(llvmpipe->draw, shader->draw_data); assert(shader->variants_cached == 0); @@ -1277,14 +1305,15 @@ make_variant_key(struct llvmpipe_context *lp, } } + + /** - * Update fragment state. This is called just prior to drawing + * Update fragment shader state. This is called just prior to drawing * something when some fragment-related state has changed. */ void llvmpipe_update_fs(struct llvmpipe_context *lp) { - struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); struct lp_fragment_shader *shader = lp->fs; struct lp_fragment_shader_variant_key key; struct lp_fragment_shader_variant *variant = NULL; @@ -1292,6 +1321,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) make_variant_key(lp, shader, &key); + /* Search the variants for one which matches the key */ li = first_elem(&shader->variants); while(!at_end(&shader->variants, li)) { if(memcmp(&li->base->key, &key, shader->variant_key_size) == 0) { @@ -1302,36 +1332,49 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) } if (variant) { + /* Move this variant to the head of the list to implement LRU + * deletion of shader's when we have too many. + */ move_to_head(&lp->fs_variants_list, &variant->list_item_global); } else { - int64_t t0, t1; - int64_t dt; + /* variant not found, create it now */ + int64_t t0, t1, dt; unsigned i; + + /* First, check if we've exceeded the max number of shader variants. + * If so, free 25% of them (the least recently used ones). + */ if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) { struct pipe_context *pipe = &lp->pipe; /* - * XXX: we need to flush the context until we have some sort of reference - * counting in fragment shaders as they may still be binned + * XXX: we need to flush the context until we have some sort of + * reference counting in fragment shaders as they may still be binned * Flushing alone might not be sufficient we need to wait on it too. */ llvmpipe_finish(pipe, __FUNCTION__); for (i = 0; i < LP_MAX_SHADER_VARIANTS / 4; i++) { - struct lp_fs_variant_list_item *item = last_elem(&lp->fs_variants_list); - remove_shader_variant(lp, item->base); + struct lp_fs_variant_list_item *item; + item = last_elem(&lp->fs_variants_list); + llvmpipe_remove_shader_variant(lp, item->base); } } - t0 = os_time_get(); - - variant = generate_variant(screen, shader, &key); + /* + * Generate the new variant. + */ + t0 = os_time_get(); + variant = generate_variant(lp, shader, &key); t1 = os_time_get(); dt = t1 - t0; LP_COUNT_ADD(llvm_compile_time, dt); LP_COUNT_ADD(nr_llvm_compiles, 2); /* emit vs. omit in/out test */ + llvmpipe_variant_count++; + + /* Put the new variant into the list */ if (variant) { insert_at_head(&shader->variants, &variant->list_item_local); insert_at_head(&lp->fs_variants_list, &variant->list_item_global); @@ -1340,6 +1383,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) } } + /* Bind this variant */ lp_setup_set_fs_variant(lp->setup, variant); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h index 7d58c4936c7..98410c69359 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h @@ -69,12 +69,15 @@ struct lp_fragment_shader_variant_key struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS]; }; + +/** doubly-linked list item */ struct lp_fs_variant_list_item { struct lp_fragment_shader_variant *base; struct lp_fs_variant_list_item *next, *prev; }; + struct lp_fragment_shader_variant { struct lp_fragment_shader_variant_key key; @@ -118,5 +121,9 @@ struct lp_fragment_shader void lp_debug_fs_variant(const struct lp_fragment_shader_variant *variant); +void +llvmpipe_remove_shader_variant(struct llvmpipe_context *lp, + struct lp_fragment_shader_variant *variant); + #endif /* LP_STATE_FS_H_ */ diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c index dbd73812e45..574f9e940ef 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c +++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c @@ -32,16 +32,64 @@ #include "lp_setup.h" #include "draw/draw_context.h" +struct lp_rast_state { + struct pipe_rasterizer_state lp_state; + struct pipe_rasterizer_state draw_state; +}; + +/* State which might be handled in either the draw module or locally. + * This function is used to turn that state off in one of the two + * places. + */ +static void +clear_flags(struct pipe_rasterizer_state *rast) +{ + rast->light_twoside = 0; + rast->offset_tri = 0; +} + static void * llvmpipe_create_rasterizer_state(struct pipe_context *pipe, const struct pipe_rasterizer_state *rast) { - /* We do nothing special with rasterizer state. - * The CSO handle is just a pointer to a pipe_rasterizer_state object. + boolean need_pipeline; + + /* Partition rasterizer state into what we want the draw module to + * handle, and what we'll look after ourselves. + */ + struct lp_rast_state *state = MALLOC_STRUCT(lp_rast_state); + if (state == NULL) + return NULL; + + memcpy(&state->draw_state, rast, sizeof *rast); + memcpy(&state->lp_state, rast, sizeof *rast); + + /* We rely on draw module to do unfilled polyons, AA lines and + * points and stipple. + * + * Over time, reduce this list of conditions, and expand the list + * of flags which get cleared in clear_flags(). */ - return mem_dup(rast, sizeof(*rast)); + need_pipeline = (rast->fill_front != PIPE_POLYGON_MODE_FILL || + rast->fill_back != PIPE_POLYGON_MODE_FILL || + rast->point_smooth || + rast->line_smooth || + rast->line_stipple_enable || + rast->poly_stipple_enable); + + /* If not using the pipeline, clear out the flags which we can + * handle ourselves. If we *are* using the pipeline, do everything + * on the pipeline and clear those flags on our internal copy of + * the state. + */ + if (need_pipeline) + clear_flags(&state->lp_state); + else + clear_flags(&state->draw_state); + + return state; } @@ -50,36 +98,33 @@ static void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); - const struct pipe_rasterizer_state *rasterizer = - (const struct pipe_rasterizer_state *) handle; - - if (llvmpipe->rasterizer == rasterizer) - return; + const struct lp_rast_state *state = + (const struct lp_rast_state *) handle; - /* pass-through to draw module */ - draw_set_rasterizer_state(llvmpipe->draw, rasterizer, handle); + if (state) { + llvmpipe->rasterizer = &state->lp_state; + draw_set_rasterizer_state(llvmpipe->draw, &state->draw_state, handle); - llvmpipe->rasterizer = rasterizer; - - /* Note: we can immediately set the triangle state here and - * not worry about binning because we handle culling during - * triangle setup, not when rasterizing the bins. - */ - if (llvmpipe->rasterizer) { + /* XXX: just pass lp_state directly to setup. + */ lp_setup_set_triangle_state( llvmpipe->setup, - llvmpipe->rasterizer->cull_face, - llvmpipe->rasterizer->front_ccw, - llvmpipe->rasterizer->scissor, - llvmpipe->rasterizer->gl_rasterization_rules); + state->lp_state.cull_face, + state->lp_state.front_ccw, + state->lp_state.scissor, + state->lp_state.gl_rasterization_rules); lp_setup_set_flatshade_first( llvmpipe->setup, - llvmpipe->rasterizer->flatshade_first); + state->lp_state.flatshade_first); lp_setup_set_line_state( llvmpipe->setup, - llvmpipe->rasterizer->line_width); + state->lp_state.line_width); lp_setup_set_point_state( llvmpipe->setup, - llvmpipe->rasterizer->point_size, - llvmpipe->rasterizer->point_size_per_vertex, - llvmpipe->rasterizer->sprite_coord_enable, - llvmpipe->rasterizer->sprite_coord_mode); + state->lp_state.point_size, + state->lp_state.point_size_per_vertex, + state->lp_state.sprite_coord_enable, + state->lp_state.sprite_coord_mode); + } + else { + llvmpipe->rasterizer = NULL; + draw_set_rasterizer_state(llvmpipe->draw, NULL, handle); } llvmpipe->dirty |= LP_NEW_RASTERIZER; diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c index 2c8b8b9a928..ad751b9ef42 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c @@ -30,9 +30,13 @@ #include "util/u_memory.h" #include "util/u_simple_list.h" #include "os/os_time.h" +#include "gallivm/lp_bld_arit.h" +#include "gallivm/lp_bld_const.h" #include "gallivm/lp_bld_debug.h" #include "gallivm/lp_bld_init.h" #include "gallivm/lp_bld_intr.h" +#include "gallivm/lp_bld_flow.h" +#include "gallivm/lp_bld_type.h" #include <llvm-c/Analysis.h> /* for LLVMVerifyFunction */ #include "lp_perf.h" @@ -40,8 +44,6 @@ #include "lp_flush.h" #include "lp_screen.h" #include "lp_context.h" -#include "lp_setup_context.h" -#include "lp_rast.h" #include "lp_state.h" #include "lp_state_fs.h" #include "lp_state_setup.h" @@ -74,26 +76,37 @@ struct lp_setup_args LLVMValueRef dy01_ooa; LLVMValueRef dx20_ooa; LLVMValueRef dx01_ooa; + + /* Temporary, per-attribute: + */ + LLVMValueRef v0a; + LLVMValueRef v1a; + LLVMValueRef v2a; }; -static LLVMTypeRef type4f(void) + + +static LLVMTypeRef +type4f(struct gallivm_state *gallivm) { - return LLVMVectorType(LLVMFloatType(), 4); + return LLVMVectorType(LLVMFloatTypeInContext(gallivm->context), 4); } /* Equivalent of _mm_setr_ps(a,b,c,d) */ -static LLVMValueRef vec4f(LLVMBuilderRef bld, - LLVMValueRef a, LLVMValueRef b, LLVMValueRef c, LLVMValueRef d, - const char *name) +static LLVMValueRef +vec4f(struct gallivm_state *gallivm, + LLVMValueRef a, LLVMValueRef b, LLVMValueRef c, LLVMValueRef d, + const char *name) { - LLVMValueRef i0 = LLVMConstInt(LLVMInt32Type(), 0, 0); - LLVMValueRef i1 = LLVMConstInt(LLVMInt32Type(), 1, 0); - LLVMValueRef i2 = LLVMConstInt(LLVMInt32Type(), 2, 0); - LLVMValueRef i3 = LLVMConstInt(LLVMInt32Type(), 3, 0); + LLVMBuilderRef bld = gallivm->builder; + LLVMValueRef i0 = lp_build_const_int32(gallivm, 0); + LLVMValueRef i1 = lp_build_const_int32(gallivm, 1); + LLVMValueRef i2 = lp_build_const_int32(gallivm, 2); + LLVMValueRef i3 = lp_build_const_int32(gallivm, 3); - LLVMValueRef res = LLVMGetUndef(type4f()); + LLVMValueRef res = LLVMGetUndef(type4f(gallivm)); res = LLVMBuildInsertElement(bld, res, a, i0, ""); res = LLVMBuildInsertElement(bld, res, b, i1, ""); @@ -105,15 +118,17 @@ static LLVMValueRef vec4f(LLVMBuilderRef bld, /* Equivalent of _mm_set1_ps(a) */ -static LLVMValueRef vec4f_from_scalar(LLVMBuilderRef bld, - LLVMValueRef a, - const char *name) +static LLVMValueRef +vec4f_from_scalar(struct gallivm_state *gallivm, + LLVMValueRef a, + const char *name) { - LLVMValueRef res = LLVMGetUndef(type4f()); + LLVMBuilderRef bld = gallivm->builder; + LLVMValueRef res = LLVMGetUndef(type4f(gallivm)); int i; for(i = 0; i < 4; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + LLVMValueRef index = lp_build_const_int32(gallivm, i); res = LLVMBuildInsertElement(bld, res, a, index, i == 3 ? name : ""); } @@ -121,14 +136,15 @@ static LLVMValueRef vec4f_from_scalar(LLVMBuilderRef bld, } static void -store_coef(LLVMBuilderRef builder, +store_coef(struct gallivm_state *gallivm, struct lp_setup_args *args, unsigned slot, LLVMValueRef a0, LLVMValueRef dadx, LLVMValueRef dady) { - LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), slot, 0); + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef idx = lp_build_const_int32(gallivm, slot); LLVMBuildStore(builder, a0, @@ -146,19 +162,14 @@ store_coef(LLVMBuilderRef builder, static void -emit_constant_coef4( LLVMBuilderRef builder, +emit_constant_coef4(struct gallivm_state *gallivm, struct lp_setup_args *args, unsigned slot, - LLVMValueRef vert, - unsigned attr) + LLVMValueRef vert) { - LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); - LLVMValueRef zerovec = vec4f_from_scalar(builder, zero, "zero"); - LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), attr, 0); - LLVMValueRef attr_ptr = LLVMBuildGEP(builder, vert, &idx, 1, "attr_ptr"); - LLVMValueRef vert_attr = LLVMBuildLoad(builder, attr_ptr, "vert_attr"); - - store_coef(builder, args, slot, vert_attr, zerovec, zerovec); + LLVMValueRef zero = lp_build_const_float(gallivm, 0.0); + LLVMValueRef zerovec = vec4f_from_scalar(gallivm, zero, "zero"); + store_coef(gallivm, args, slot, vert, zerovec, zerovec); } @@ -168,43 +179,194 @@ emit_constant_coef4( LLVMBuilderRef builder, * \param frontface is the triangle front facing? */ static void -emit_facing_coef( LLVMBuilderRef builder, +emit_facing_coef(struct gallivm_state *gallivm, struct lp_setup_args *args, unsigned slot ) { + LLVMBuilderRef builder = gallivm->builder; + LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context); LLVMValueRef a0_0 = args->facing; - LLVMValueRef a0_0f = LLVMBuildSIToFP(builder, a0_0, LLVMFloatType(), ""); - LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); - LLVMValueRef a0 = vec4f(builder, a0_0f, zero, zero, zero, "facing"); - LLVMValueRef zerovec = vec4f_from_scalar(builder, zero, "zero"); + LLVMValueRef a0_0f = LLVMBuildSIToFP(builder, a0_0, float_type, ""); + LLVMValueRef zero = lp_build_const_float(gallivm, 0.0); + LLVMValueRef a0 = vec4f(gallivm, a0_0f, zero, zero, zero, "facing"); + LLVMValueRef zerovec = vec4f_from_scalar(gallivm, zero, "zero"); - store_coef(builder, args, slot, a0, zerovec, zerovec); + store_coef(gallivm, args, slot, a0, zerovec, zerovec); } static LLVMValueRef -vert_attrib(LLVMBuilderRef b, +vert_attrib(struct gallivm_state *gallivm, LLVMValueRef vert, int attr, int elem, const char *name) { + LLVMBuilderRef b = gallivm->builder; LLVMValueRef idx[2]; - idx[0] = LLVMConstInt(LLVMInt32Type(), attr, 0); - idx[1] = LLVMConstInt(LLVMInt32Type(), elem, 0); + idx[0] = lp_build_const_int32(gallivm, attr); + idx[1] = lp_build_const_int32(gallivm, elem); return LLVMBuildLoad(b, LLVMBuildGEP(b, vert, idx, 2, ""), name); } +static LLVMValueRef +vert_clamp(LLVMBuilderRef b, + LLVMValueRef x, + LLVMValueRef min, + LLVMValueRef max) +{ + LLVMValueRef min_result = LLVMBuildFCmp(b, LLVMRealUGT, min, x, ""); + LLVMValueRef max_result = LLVMBuildFCmp(b, LLVMRealUGT, x, max, ""); + LLVMValueRef clamp_value; + + clamp_value = LLVMBuildSelect(b, min_result, min, x, ""); + clamp_value = LLVMBuildSelect(b, max_result, max, x, ""); + return clamp_value; +} + +static void +lp_twoside(struct gallivm_state *gallivm, + struct lp_setup_args *args, + const struct lp_setup_variant_key *key, + int bcolor_slot) +{ + LLVMBuilderRef b = gallivm->builder; + LLVMValueRef a0_back, a1_back, a2_back; + LLVMValueRef idx2 = lp_build_const_int32(gallivm, bcolor_slot); + + LLVMValueRef facing = args->facing; + LLVMValueRef front_facing = LLVMBuildICmp(b, LLVMIntEQ, facing, lp_build_const_int32(gallivm, 0), ""); /** need i1 for if condition */ + + a0_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx2, 1, ""), "v0a_back"); + a1_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx2, 1, ""), "v1a_back"); + a2_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx2, 1, ""), "v2a_back"); + + /* Possibly swap the front and back attrib values, + * + * Prefer select to if so we don't have to worry about phis or + * allocas. + */ + args->v0a = LLVMBuildSelect(b, front_facing, a0_back, args->v0a, ""); + args->v1a = LLVMBuildSelect(b, front_facing, a1_back, args->v1a, ""); + args->v2a = LLVMBuildSelect(b, front_facing, a2_back, args->v2a, ""); + +} + +static void +lp_do_offset_tri(struct gallivm_state *gallivm, + struct lp_setup_args *args, + const struct lp_setup_variant_key *key) +{ + LLVMBuilderRef b = gallivm->builder; + struct lp_build_context bld; + LLVMValueRef zoffset, mult; + LLVMValueRef z0_new, z1_new, z2_new; + LLVMValueRef dzdx0, dzdx, dzdy0, dzdy; + LLVMValueRef max, max_value; + + LLVMValueRef one = lp_build_const_float(gallivm, 1.0); + LLVMValueRef zero = lp_build_const_float(gallivm, 0.0); + LLVMValueRef two = lp_build_const_int32(gallivm, 2); + + /* edge vectors: e = v0 - v2, f = v1 - v2 */ + LLVMValueRef v0_x = vert_attrib(gallivm, args->v0, 0, 0, "v0_x"); + LLVMValueRef v1_x = vert_attrib(gallivm, args->v1, 0, 0, "v1_x"); + LLVMValueRef v2_x = vert_attrib(gallivm, args->v2, 0, 0, "v2_x"); + LLVMValueRef v0_y = vert_attrib(gallivm, args->v0, 0, 1, "v0_y"); + LLVMValueRef v1_y = vert_attrib(gallivm, args->v1, 0, 1, "v1_y"); + LLVMValueRef v2_y = vert_attrib(gallivm, args->v2, 0, 1, "v2_y"); + LLVMValueRef v0_z = vert_attrib(gallivm, args->v0, 0, 2, "v0_z"); + LLVMValueRef v1_z = vert_attrib(gallivm, args->v1, 0, 2, "v1_z"); + LLVMValueRef v2_z = vert_attrib(gallivm, args->v2, 0, 2, "v2_z"); + + /* edge vectors: e = v0 - v2, f = v1 - v2 */ + LLVMValueRef dx02 = LLVMBuildFSub(b, v0_x, v2_x, "dx02"); + LLVMValueRef dy02 = LLVMBuildFSub(b, v0_y, v2_y, "dy02"); + LLVMValueRef dz02 = LLVMBuildFSub(b, v0_z, v2_z, "dz02"); + LLVMValueRef dx12 = LLVMBuildFSub(b, v1_x, v2_x, "dx12"); + LLVMValueRef dy12 = LLVMBuildFSub(b, v1_y, v2_y, "dy12"); + LLVMValueRef dz12 = LLVMBuildFSub(b, v1_z, v2_z, "dz12"); + + /* det = cross(e,f).z */ + LLVMValueRef dx02_dy12 = LLVMBuildFMul(b, dx02, dy12, "dx02_dy12"); + LLVMValueRef dy02_dx12 = LLVMBuildFMul(b, dy02, dx12, "dy02_dx12"); + LLVMValueRef det = LLVMBuildFSub(b, dx02_dy12, dy02_dx12, "det"); + LLVMValueRef inv_det = LLVMBuildFDiv(b, one, det, "inv_det"); + + /* (res1,res2) = cross(e,f).xy */ + LLVMValueRef dy02_dz12 = LLVMBuildFMul(b, dy02, dz12, "dy02_dz12"); + LLVMValueRef dz02_dy12 = LLVMBuildFMul(b, dz02, dy12, "dz02_dy12"); + LLVMValueRef dz02_dx12 = LLVMBuildFMul(b, dz02, dx12, "dz02_dx12"); + LLVMValueRef dx02_dz12 = LLVMBuildFMul(b, dx02, dz12, "dx02_dz12"); + LLVMValueRef res1 = LLVMBuildFSub(b, dy02_dz12, dz02_dy12, "res1"); + LLVMValueRef res2 = LLVMBuildFSub(b, dz02_dx12, dx02_dz12, "res2"); + + /* dzdx = fabsf(res1 * inv_det), dydx = fabsf(res2 * inv_det)*/ + lp_build_context_init(&bld, gallivm, lp_type_float(32)); + dzdx0 = LLVMBuildFMul(b, res1, inv_det, "dzdx"); + dzdx = lp_build_abs(&bld, dzdx0); + dzdy0 = LLVMBuildFMul(b, res2, inv_det, "dzdy"); + dzdy = lp_build_abs(&bld, dzdy0); + + /* zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale */ + max = LLVMBuildFCmp(b, LLVMRealUGT, dzdx, dzdy, ""); + max_value = LLVMBuildSelect(b, max, dzdx, dzdy, "max"); + + mult = LLVMBuildFMul(b, max_value, lp_build_const_float(gallivm, key->scale), ""); + zoffset = LLVMBuildFAdd(b, lp_build_const_float(gallivm, key->units), mult, "zoffset"); + + /* clamp and do offset */ + z0_new = vert_clamp(b, LLVMBuildFAdd(b, v0_z, zoffset, ""), zero, one); + z1_new = vert_clamp(b, LLVMBuildFAdd(b, v1_z, zoffset, ""), zero, one); + z2_new = vert_clamp(b, LLVMBuildFAdd(b, v2_z, zoffset, ""), zero, one); + + /* insert into args->a0.z, a1.z, a2.z: + */ + args->v0a = LLVMBuildInsertElement(b, args->v0a, z0_new, two, ""); + args->v1a = LLVMBuildInsertElement(b, args->v1a, z1_new, two, ""); + args->v2a = LLVMBuildInsertElement(b, args->v2a, z2_new, two, ""); +} + +static void +load_attribute(struct gallivm_state *gallivm, + struct lp_setup_args *args, + const struct lp_setup_variant_key *key, + unsigned vert_attr) +{ + LLVMBuilderRef b = gallivm->builder; + LLVMValueRef idx = lp_build_const_int32(gallivm, vert_attr); + + /* Load the vertex data + */ + args->v0a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx, 1, ""), "v0a"); + args->v1a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx, 1, ""), "v1a"); + args->v2a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx, 1, ""), "v2a"); + + + /* Potentially modify it according to twoside, offset, etc: + */ + if (vert_attr == 0 && (key->scale != 0.0f || key->units != 0.0f)) { + lp_do_offset_tri(gallivm, args, key); + } + + if (key->twoside) { + if (vert_attr == key->color_slot && key->bcolor_slot != ~0) + lp_twoside(gallivm, args, key, key->bcolor_slot); + else if (vert_attr == key->spec_slot && key->bspec_slot != ~0) + lp_twoside(gallivm, args, key, key->bspec_slot); + } +} static void -emit_coef4( LLVMBuilderRef b, +emit_coef4( struct gallivm_state *gallivm, struct lp_setup_args *args, unsigned slot, LLVMValueRef a0, LLVMValueRef a1, LLVMValueRef a2) { + LLVMBuilderRef b = gallivm->builder; LLVMValueRef dy20_ooa = args->dy20_ooa; LLVMValueRef dy01_ooa = args->dy01_ooa; LLVMValueRef dx20_ooa = args->dx20_ooa; @@ -236,27 +398,24 @@ emit_coef4( LLVMBuilderRef b, LLVMValueRef attr_v0 = LLVMBuildFAdd(b, dadx_x0, dady_y0, "attr_v0"); LLVMValueRef attr_0 = LLVMBuildFSub(b, a0, attr_v0, "attr_0"); - store_coef(b, args, slot, attr_0, dadx, dady); + store_coef(gallivm, args, slot, attr_0, dadx, dady); } static void -emit_linear_coef( LLVMBuilderRef b, +emit_linear_coef( struct gallivm_state *gallivm, struct lp_setup_args *args, - unsigned slot, - unsigned vert_attr) + unsigned slot) { - LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), vert_attr, 0); - - LLVMValueRef a0 = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx, 1, ""), "v0a"); - LLVMValueRef a1 = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx, 1, ""), "v1a"); - LLVMValueRef a2 = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx, 1, ""), "v2a"); - - emit_coef4(b, args, slot, a0, a1, a2); + /* nothing to do anymore */ + emit_coef4(gallivm, + args, slot, + args->v0a, + args->v1a, + args->v2a); } - /** * Compute a0, dadx and dady for a perspective-corrected interpolant, * for a triangle. @@ -266,37 +425,32 @@ emit_linear_coef( LLVMBuilderRef b, * divide the interpolated value by the interpolated W at that fragment. */ static void -emit_perspective_coef( LLVMBuilderRef b, +emit_perspective_coef( struct gallivm_state *gallivm, struct lp_setup_args *args, - unsigned slot, - unsigned vert_attr) + unsigned slot) { + LLVMBuilderRef b = gallivm->builder; + /* premultiply by 1/w (v[0][3] is always 1/w): */ - LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), vert_attr, 0); - - LLVMValueRef v0a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx, 1, ""), "v0a"); - LLVMValueRef v1a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx, 1, ""), "v1a"); - LLVMValueRef v2a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx, 1, ""), "v2a"); - - LLVMValueRef v0_oow = vec4f_from_scalar(b, vert_attrib(b, args->v0, 0, 3, ""), "v0_oow"); - LLVMValueRef v1_oow = vec4f_from_scalar(b, vert_attrib(b, args->v1, 0, 3, ""), "v1_oow"); - LLVMValueRef v2_oow = vec4f_from_scalar(b, vert_attrib(b, args->v2, 0, 3, ""), "v2_oow"); + LLVMValueRef v0_oow = vec4f_from_scalar(gallivm, vert_attrib(gallivm, args->v0, 0, 3, ""), "v0_oow"); + LLVMValueRef v1_oow = vec4f_from_scalar(gallivm, vert_attrib(gallivm, args->v1, 0, 3, ""), "v1_oow"); + LLVMValueRef v2_oow = vec4f_from_scalar(gallivm, vert_attrib(gallivm, args->v2, 0, 3, ""), "v2_oow"); - LLVMValueRef v0_oow_v0a = LLVMBuildFMul(b, v0a, v0_oow, "v0_oow_v0a"); - LLVMValueRef v1_oow_v1a = LLVMBuildFMul(b, v1a, v1_oow, "v1_oow_v1a"); - LLVMValueRef v2_oow_v2a = LLVMBuildFMul(b, v2a, v2_oow, "v2_oow_v2a"); + LLVMValueRef v0_oow_v0a = LLVMBuildFMul(b, args->v0a, v0_oow, "v0_oow_v0a"); + LLVMValueRef v1_oow_v1a = LLVMBuildFMul(b, args->v1a, v1_oow, "v1_oow_v1a"); + LLVMValueRef v2_oow_v2a = LLVMBuildFMul(b, args->v2a, v2_oow, "v2_oow_v2a"); - emit_coef4(b, args, slot, v0_oow_v0a, v1_oow_v1a, v2_oow_v2a); + emit_coef4(gallivm, args, slot, v0_oow_v0a, v1_oow_v1a, v2_oow_v2a); } static void -emit_position_coef( LLVMBuilderRef builder, +emit_position_coef( struct gallivm_state *gallivm, struct lp_setup_args *args, - int slot, int attrib ) + int slot ) { - emit_linear_coef(builder, args, slot, attrib); + emit_linear_coef(gallivm, args, slot); } @@ -306,7 +460,7 @@ emit_position_coef( LLVMBuilderRef builder, * Compute the inputs-> dadx, dady, a0 values. */ static void -emit_tri_coef( LLVMBuilderRef builder, +emit_tri_coef( struct gallivm_state *gallivm, const struct lp_setup_variant_key *key, struct lp_setup_args *args ) { @@ -314,29 +468,34 @@ emit_tri_coef( LLVMBuilderRef builder, /* The internal position input is in slot zero: */ - emit_position_coef(builder, args, 0, 0); + load_attribute(gallivm, args, key, 0); + emit_position_coef(gallivm, args, 0); /* setup interpolation for all the remaining attributes: */ for (slot = 0; slot < key->num_inputs; slot++) { - unsigned vert_attr = key->inputs[slot].src_index; + + if (key->inputs[slot].interp == LP_INTERP_CONSTANT || + key->inputs[slot].interp == LP_INTERP_LINEAR || + key->inputs[slot].interp == LP_INTERP_PERSPECTIVE) + load_attribute(gallivm, args, key, key->inputs[slot].src_index); switch (key->inputs[slot].interp) { case LP_INTERP_CONSTANT: if (key->flatshade_first) { - emit_constant_coef4(builder, args, slot+1, args->v0, vert_attr); + emit_constant_coef4(gallivm, args, slot+1, args->v0a); } else { - emit_constant_coef4(builder, args, slot+1, args->v2, vert_attr); + emit_constant_coef4(gallivm, args, slot+1, args->v2a); } break; case LP_INTERP_LINEAR: - emit_linear_coef(builder, args, slot+1, vert_attr); + emit_linear_coef(gallivm, args, slot+1); break; case LP_INTERP_PERSPECTIVE: - emit_perspective_coef(builder, args, slot+1, vert_attr); + emit_perspective_coef(gallivm, args, slot+1); break; case LP_INTERP_POSITION: @@ -347,7 +506,7 @@ emit_tri_coef( LLVMBuilderRef builder, break; case LP_INTERP_FACING: - emit_facing_coef(builder, args, slot+1); + emit_facing_coef(gallivm, args, slot+1); break; default: @@ -360,7 +519,7 @@ emit_tri_coef( LLVMBuilderRef builder, /* XXX: This is generic code, share with fs/vs codegen: */ static lp_jit_setup_triangle -finalize_function(struct llvmpipe_screen *screen, +finalize_function(struct gallivm_state *gallivm, LLVMBuilderRef builder, LLVMValueRef function) { @@ -376,7 +535,7 @@ finalize_function(struct llvmpipe_screen *screen, #endif /* Apply optimizations to LLVM IR */ - LLVMRunFunctionPassManager(screen->pass, function); + LLVMRunFunctionPassManager(gallivm->passmgr, function); if (gallivm_debug & GALLIVM_DEBUG_IR) { @@ -388,7 +547,7 @@ finalize_function(struct llvmpipe_screen *screen, /* * Translate the LLVM IR into machine code. */ - f = LLVMGetPointerToGlobal(screen->engine, function); + f = LLVMGetPointerToGlobal(gallivm->engine, function); if (gallivm_debug & GALLIVM_DEBUG_ASM) { @@ -403,11 +562,12 @@ finalize_function(struct llvmpipe_screen *screen, /* XXX: Generic code: */ static void -lp_emit_emms(LLVMBuilderRef builder) +lp_emit_emms(struct gallivm_state *gallivm) { #ifdef PIPE_ARCH_X86 /* Avoid corrupting the FPU stack on 32bit OSes. */ - lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0); + lp_build_intrinsic(gallivm->builder, "llvm.x86.mmx.emms", + LLVMVoidTypeInContext(gallivm->context), NULL, 0); #endif } @@ -428,21 +588,23 @@ set_noalias(LLVMBuilderRef builder, } static void -init_args(LLVMBuilderRef b, +init_args(struct gallivm_state *gallivm, struct lp_setup_args *args, const struct lp_setup_variant *variant) { - LLVMValueRef v0_x = vert_attrib(b, args->v0, 0, 0, "v0_x"); - LLVMValueRef v0_y = vert_attrib(b, args->v0, 0, 1, "v0_y"); + LLVMBuilderRef b = gallivm->builder; + + LLVMValueRef v0_x = vert_attrib(gallivm, args->v0, 0, 0, "v0_x"); + LLVMValueRef v0_y = vert_attrib(gallivm, args->v0, 0, 1, "v0_y"); - LLVMValueRef v1_x = vert_attrib(b, args->v1, 0, 0, "v1_x"); - LLVMValueRef v1_y = vert_attrib(b, args->v1, 0, 1, "v1_y"); + LLVMValueRef v1_x = vert_attrib(gallivm, args->v1, 0, 0, "v1_x"); + LLVMValueRef v1_y = vert_attrib(gallivm, args->v1, 0, 1, "v1_y"); - LLVMValueRef v2_x = vert_attrib(b, args->v2, 0, 0, "v2_x"); - LLVMValueRef v2_y = vert_attrib(b, args->v2, 0, 1, "v2_y"); + LLVMValueRef v2_x = vert_attrib(gallivm, args->v2, 0, 0, "v2_x"); + LLVMValueRef v2_y = vert_attrib(gallivm, args->v2, 0, 1, "v2_y"); - LLVMValueRef pixel_center = LLVMConstReal(LLVMFloatType(), - variant->key.pixel_center_half ? 0.5 : 0); + LLVMValueRef pixel_center = lp_build_const_float(gallivm, + variant->key.pixel_center_half ? 0.5 : 0); LLVMValueRef x0_center = LLVMBuildFSub(b, v0_x, pixel_center, "x0_center" ); LLVMValueRef y0_center = LLVMBuildFSub(b, v0_y, pixel_center, "y0_center" ); @@ -452,7 +614,7 @@ init_args(LLVMBuilderRef b, LLVMValueRef dx20 = LLVMBuildFSub(b, v2_x, v0_x, "dx20"); LLVMValueRef dy20 = LLVMBuildFSub(b, v2_y, v0_y, "dy20"); - LLVMValueRef one = LLVMConstReal(LLVMFloatType(), 1.0); + LLVMValueRef one = lp_build_const_float(gallivm, 1.0); LLVMValueRef e = LLVMBuildFMul(b, dx01, dy20, "e"); LLVMValueRef f = LLVMBuildFMul(b, dx20, dy01, "f"); LLVMValueRef ooa = LLVMBuildFDiv(b, one, LLVMBuildFSub(b, e, f, ""), "ooa"); @@ -462,14 +624,14 @@ init_args(LLVMBuilderRef b, LLVMValueRef dx20_ooa = LLVMBuildFMul(b, dx20, ooa, "dx20_ooa"); LLVMValueRef dx01_ooa = LLVMBuildFMul(b, dx01, ooa, "dx01_ooa"); - args->dy20_ooa = vec4f_from_scalar(b, dy20_ooa, "dy20_ooa_4f"); - args->dy01_ooa = vec4f_from_scalar(b, dy01_ooa, "dy01_ooa_4f"); + args->dy20_ooa = vec4f_from_scalar(gallivm, dy20_ooa, "dy20_ooa_4f"); + args->dy01_ooa = vec4f_from_scalar(gallivm, dy01_ooa, "dy01_ooa_4f"); - args->dx20_ooa = vec4f_from_scalar(b, dx20_ooa, "dx20_ooa_4f"); - args->dx01_ooa = vec4f_from_scalar(b, dx01_ooa, "dx01_ooa_4f"); + args->dx20_ooa = vec4f_from_scalar(gallivm, dx20_ooa, "dx20_ooa_4f"); + args->dx01_ooa = vec4f_from_scalar(gallivm, dx01_ooa, "dx01_ooa_4f"); - args->x0_center = vec4f_from_scalar(b, x0_center, "x0_center_4f"); - args->y0_center = vec4f_from_scalar(b, y0_center, "y0_center_4f"); + args->x0_center = vec4f_from_scalar(gallivm, x0_center, "x0_center_4f"); + args->y0_center = vec4f_from_scalar(gallivm, y0_center, "y0_center_4f"); } /** @@ -477,8 +639,9 @@ init_args(LLVMBuilderRef b, * */ static struct lp_setup_variant * -generate_setup_variant(struct llvmpipe_screen *screen, - struct lp_setup_variant_key *key) +generate_setup_variant(struct gallivm_state *gallivm, + struct lp_setup_variant_key *key, + struct llvmpipe_context *lp) { struct lp_setup_variant *variant = NULL; struct lp_setup_args args; @@ -487,7 +650,7 @@ generate_setup_variant(struct llvmpipe_screen *screen, LLVMTypeRef func_type; LLVMTypeRef arg_types[7]; LLVMBasicBlockRef block; - LLVMBuilderRef builder; + LLVMBuilderRef builder = gallivm->builder; int64_t t0, t1; if (0) @@ -512,19 +675,20 @@ generate_setup_variant(struct llvmpipe_screen *screen, * the vertices. */ - vec4f_type = LLVMVectorType(LLVMFloatType(), 4); + vec4f_type = LLVMVectorType(LLVMFloatTypeInContext(gallivm->context), 4); arg_types[0] = LLVMPointerType(vec4f_type, 0); /* v0 */ arg_types[1] = LLVMPointerType(vec4f_type, 0); /* v1 */ arg_types[2] = LLVMPointerType(vec4f_type, 0); /* v2 */ - arg_types[3] = LLVMInt32Type(); /* facing */ + arg_types[3] = LLVMInt32TypeInContext(gallivm->context); /* facing */ arg_types[4] = LLVMPointerType(vec4f_type, 0); /* a0, aligned */ arg_types[5] = LLVMPointerType(vec4f_type, 0); /* dadx, aligned */ arg_types[6] = LLVMPointerType(vec4f_type, 0); /* dady, aligned */ - func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); + func_type = LLVMFunctionType(LLVMVoidTypeInContext(gallivm->context), + arg_types, Elements(arg_types), 0); - variant->function = LLVMAddFunction(screen->module, func_name, func_type); + variant->function = LLVMAddFunction(gallivm->module, func_name, func_type); if (!variant->function) goto fail; @@ -549,19 +713,18 @@ generate_setup_variant(struct llvmpipe_screen *screen, /* * Function body */ - block = LLVMAppendBasicBlock(variant->function, "entry"); - builder = LLVMCreateBuilder(); + block = LLVMAppendBasicBlockInContext(gallivm->context, + variant->function, "entry"); LLVMPositionBuilderAtEnd(builder, block); set_noalias(builder, variant->function, arg_types, Elements(arg_types)); - init_args(builder, &args, variant); - emit_tri_coef(builder, &variant->key, &args); + init_args(gallivm, &args, variant); + emit_tri_coef(gallivm, &variant->key, &args); - lp_emit_emms(builder); + lp_emit_emms(gallivm); LLVMBuildRetVoid(builder); - LLVMDisposeBuilder(builder); - variant->jit_function = finalize_function(screen, builder, + variant->jit_function = finalize_function(gallivm, builder, variant->function); if (!variant->jit_function) goto fail; @@ -581,7 +744,7 @@ fail: if (variant) { if (variant->function) { if (variant->jit_function) - LLVMFreeMachineCodeForFunction(screen->engine, + LLVMFreeMachineCodeForFunction(gallivm->engine, variant->function); LLVMDeleteFunction(variant->function); } @@ -605,14 +768,20 @@ lp_make_setup_variant_key(struct llvmpipe_context *lp, key->num_inputs = fs->info.base.num_inputs; key->flatshade_first = lp->rasterizer->flatshade_first; key->pixel_center_half = lp->rasterizer->gl_rasterization_rules; + key->twoside = lp->rasterizer->light_twoside; key->size = Offset(struct lp_setup_variant_key, inputs[key->num_inputs]); + key->color_slot = lp->color_slot[0]; + key->bcolor_slot = lp->bcolor_slot[0]; + key->spec_slot = lp->color_slot[1]; + key->bspec_slot = lp->bcolor_slot[1]; + key->units = (float) (lp->rasterizer->offset_units * lp->mrd); + key->scale = lp->rasterizer->offset_scale; key->pad = 0; - memcpy(key->inputs, fs->inputs, key->num_inputs * sizeof key->inputs[0]); for (i = 0; i < key->num_inputs; i++) { if (key->inputs[i].interp == LP_INTERP_COLOR) { - if (lp->rasterizer->flatshade) + if (lp->rasterizer->flatshade) key->inputs[i].interp = LP_INTERP_CONSTANT; else key->inputs[i].interp = LP_INTERP_LINEAR; @@ -626,8 +795,6 @@ static void remove_setup_variant(struct llvmpipe_context *lp, struct lp_setup_variant *variant) { - struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); - if (gallivm_debug & GALLIVM_DEBUG_IR) { debug_printf("llvmpipe: del setup_variant #%u total %u\n", variant->no, lp->nr_setup_variants); @@ -635,7 +802,7 @@ remove_setup_variant(struct llvmpipe_context *lp, if (variant->function) { if (variant->jit_function) - LLVMFreeMachineCodeForFunction(screen->engine, + LLVMFreeMachineCodeForFunction(lp->gallivm->engine, variant->function); LLVMDeleteFunction(variant->function); } @@ -678,8 +845,6 @@ cull_setup_variants(struct llvmpipe_context *lp) void llvmpipe_update_setup(struct llvmpipe_context *lp) { - struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); - struct lp_setup_variant_key *key = &lp->setup_variant.key; struct lp_setup_variant *variant = NULL; struct lp_setup_variant_list_item *li; @@ -702,9 +867,11 @@ llvmpipe_update_setup(struct llvmpipe_context *lp) cull_setup_variants(lp); } - variant = generate_setup_variant(screen, key); + variant = generate_setup_variant(lp->gallivm, key, lp); insert_at_head(&lp->setup_variants_list, &variant->list_item_global); lp->nr_setup_variants++; + + llvmpipe_variant_count++; } lp_setup_set_setup_variant(lp->setup, diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.h b/src/gallium/drivers/llvmpipe/lp_state_setup.h index b0c81baa75f..90c55ca4ce6 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.h @@ -15,11 +15,20 @@ struct lp_setup_variant_list_item struct lp_setup_variant_key { + unsigned size:16; unsigned num_inputs:8; + unsigned color_slot:8; + + unsigned bcolor_slot:8; + unsigned spec_slot:8; + unsigned bspec_slot:8; unsigned flatshade_first:1; unsigned pixel_center_half:1; - unsigned pad:7; - unsigned size:16; + unsigned twoside:1; + unsigned pad:5; + + float units; + float scale; struct lp_shader_input inputs[PIPE_MAX_SHADER_INPUTS]; }; diff --git a/src/gallium/drivers/llvmpipe/lp_state_surface.c b/src/gallium/drivers/llvmpipe/lp_state_surface.c index cd1a5b19803..375ceb2b942 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_state_surface.c @@ -77,6 +77,7 @@ llvmpipe_set_framebuffer_state(struct pipe_context *pipe, else { mrd = 0.00002; } + lp->mrd = mrd; draw_set_mrd(lp->draw, mrd); } diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index 164242eda67..e7e46a628a1 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -52,19 +52,23 @@ adjust_to_tile_bounds(unsigned x, unsigned y, unsigned width, unsigned height, static void lp_resource_copy(struct pipe_context *pipe, - struct pipe_resource *dst, struct pipe_subresource subdst, + struct pipe_resource *dst, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource *src, struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + struct pipe_resource *src, unsigned src_level, + const struct pipe_box *src_box) { - /* XXX what about the dstz/srcz parameters - zslice wasn't used... */ + /* XXX this used to ignore srcz/dstz + * assume it works the same for cube and 3d + */ struct llvmpipe_resource *src_tex = llvmpipe_resource(src); struct llvmpipe_resource *dst_tex = llvmpipe_resource(dst); const enum pipe_format format = src_tex->base.format; + unsigned width = src_box->width; + unsigned height = src_box->height; + assert(src_box->depth == 1); llvmpipe_flush_resource(pipe, - dst, subdst.face, subdst.level, + dst, dst_level, dstz, 0, /* flush_flags */ FALSE, /* read_only */ TRUE, /* cpu_access */ @@ -72,7 +76,7 @@ lp_resource_copy(struct pipe_context *pipe, "blit dest"); llvmpipe_flush_resource(pipe, - src, subsrc.face, subsrc.level, + src, src_level, src_box->z, 0, /* flush_flags */ TRUE, /* read_only */ TRUE, /* cpu_access */ @@ -80,9 +84,10 @@ lp_resource_copy(struct pipe_context *pipe, "blit src"); /* - printf("surface copy from %u to %u: %u,%u to %u,%u %u x %u\n", - src_tex->id, dst_tex->id, - srcx, srcy, dstx, dsty, width, height); + printf("surface copy from %u lvl %u to %u lvl %u: %u,%u,%u to %u,%u,%u %u x %u x %u\n", + src_tex->id, src_level, dst_tex->id, dst_level, + src_box->x, src_box->y, src_box->z, dstx, dsty, dstz, + src_box->width, src_box->height, src_box->depth); */ /* set src tiles to linear layout */ @@ -90,12 +95,13 @@ lp_resource_copy(struct pipe_context *pipe, unsigned tx, ty, tw, th; unsigned x, y; - adjust_to_tile_bounds(srcx, srcy, width, height, &tx, &ty, &tw, &th); + adjust_to_tile_bounds(src_box->x, src_box->y, width, height, + &tx, &ty, &tw, &th); for (y = 0; y < th; y += TILE_SIZE) { for (x = 0; x < tw; x += TILE_SIZE) { (void) llvmpipe_get_texture_tile_linear(src_tex, - subsrc.face, subsrc.level, + src_box->z, src_level, LP_TEX_USAGE_READ, tx + x, ty + y); } @@ -130,7 +136,7 @@ lp_resource_copy(struct pipe_context *pipe, usage = LP_TEX_USAGE_READ_WRITE; (void) llvmpipe_get_texture_tile_linear(dst_tex, - subdst.face, subdst.level, + dstz, dst_level, usage, tx + x, ty + y); } @@ -140,22 +146,22 @@ lp_resource_copy(struct pipe_context *pipe, /* copy */ { const ubyte *src_linear_ptr - = llvmpipe_get_texture_image_address(src_tex, subsrc.face, - subsrc.level, + = llvmpipe_get_texture_image_address(src_tex, src_box->z, + src_level, LP_TEX_LAYOUT_LINEAR); ubyte *dst_linear_ptr - = llvmpipe_get_texture_image_address(dst_tex, subdst.face, - subdst.level, + = llvmpipe_get_texture_image_address(dst_tex, dstz, + dst_level, LP_TEX_LAYOUT_LINEAR); if (dst_linear_ptr && src_linear_ptr) { util_copy_rect(dst_linear_ptr, format, - llvmpipe_resource_stride(&dst_tex->base, subdst.level), + llvmpipe_resource_stride(&dst_tex->base, dst_level), dstx, dsty, width, height, src_linear_ptr, - llvmpipe_resource_stride(&src_tex->base, subsrc.level), - srcx, srcy); + llvmpipe_resource_stride(&src_tex->base, src_level), + src_box->x, src_box->y); } } } diff --git a/src/gallium/drivers/llvmpipe/lp_test.h b/src/gallium/drivers/llvmpipe/lp_test.h index 90422e42588..c64f3e149fd 100644 --- a/src/gallium/drivers/llvmpipe/lp_test.h +++ b/src/gallium/drivers/llvmpipe/lp_test.h @@ -64,13 +64,14 @@ write_tsv_header(FILE *fp); boolean -test_some(unsigned verbose, FILE *fp, unsigned long n); +test_some(struct gallivm_state *gallivm,unsigned verbose, FILE *fp, + unsigned long n); boolean -test_single(unsigned verbose, FILE *fp); +test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp); boolean -test_all(unsigned verbose, FILE *fp); +test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp); #if defined(PIPE_CC_MSVC) diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c index 8b6b5e1298f..b3ca134131d 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_blend.c +++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c @@ -163,11 +163,13 @@ dump_blend_type(FILE *fp, static LLVMValueRef -add_blend_test(LLVMModuleRef module, +add_blend_test(struct gallivm_state *gallivm, const struct pipe_blend_state *blend, enum vector_mode mode, struct lp_type type) { + LLVMModuleRef module = gallivm->module; + LLVMContextRef context = gallivm->context; LLVMTypeRef vec_type; LLVMTypeRef args[4]; LLVMValueRef func; @@ -179,18 +181,18 @@ add_blend_test(LLVMModuleRef module, LLVMBuilderRef builder; const unsigned rt = 0; - vec_type = lp_build_vec_type(type); + vec_type = lp_build_vec_type(gallivm, type); args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0); - func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 4, 0)); + func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidTypeInContext(context), args, 4, 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); src_ptr = LLVMGetParam(func, 0); dst_ptr = LLVMGetParam(func, 1); const_ptr = LLVMGetParam(func, 2); res_ptr = LLVMGetParam(func, 3); - block = LLVMAppendBasicBlock(func, "entry"); - builder = LLVMCreateBuilder(); + block = LLVMAppendBasicBlockInContext(context, func, "entry"); + builder = gallivm->builder; LLVMPositionBuilderAtEnd(builder, block); if (mode == AoS) { @@ -203,7 +205,7 @@ add_blend_test(LLVMModuleRef module, dst = LLVMBuildLoad(builder, dst_ptr, "dst"); con = LLVMBuildLoad(builder, const_ptr, "const"); - res = lp_build_blend_aos(builder, blend, type, rt, src, dst, con, 3); + res = lp_build_blend_aos(gallivm, blend, type, rt, src, dst, con, 3); lp_build_name(res, "res"); @@ -218,7 +220,7 @@ add_blend_test(LLVMModuleRef module, unsigned i; for(i = 0; i < 4; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + LLVMValueRef index = LLVMConstInt(LLVMInt32TypeInContext(context), i, 0); src[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, src_ptr, &index, 1, ""), ""); dst[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), ""); con[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), ""); @@ -227,10 +229,10 @@ add_blend_test(LLVMModuleRef module, lp_build_name(dst[i], "dst.%c", "rgba"[i]); } - lp_build_blend_soa(builder, blend, type, rt, src, dst, con, res); + lp_build_blend_soa(gallivm, blend, type, rt, src, dst, con, res); for(i = 0; i < 4; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + LLVMValueRef index = LLVMConstInt(LLVMInt32TypeInContext(context), i, 0); lp_build_name(res[i], "res.%c", "rgba"[i]); LLVMBuildStore(builder, res[i], LLVMBuildGEP(builder, res_ptr, &index, 1, "")); } @@ -238,7 +240,6 @@ add_blend_test(LLVMModuleRef module, LLVMBuildRetVoid(builder);; - LLVMDisposeBuilder(builder); return func; } @@ -465,16 +466,16 @@ compute_blend_ref(const struct pipe_blend_state *blend, PIPE_ALIGN_STACK static boolean -test_one(unsigned verbose, +test_one(struct gallivm_state *gallivm, + unsigned verbose, FILE *fp, const struct pipe_blend_state *blend, enum vector_mode mode, struct lp_type type) { - LLVMModuleRef module = NULL; + LLVMModuleRef module = gallivm->module; LLVMValueRef func = NULL; - LLVMExecutionEngineRef engine = lp_build_engine; - LLVMPassManagerRef pass = NULL; + LLVMExecutionEngineRef engine = gallivm->engine; char *error = NULL; blend_test_ptr_t blend_test_ptr; boolean success; @@ -487,9 +488,7 @@ test_one(unsigned verbose, if(verbose >= 1) dump_blend_type(stdout, blend, mode, type); - module = LLVMModuleCreateWithName("test"); - - func = add_blend_test(module, blend, mode, type); + func = add_blend_test(gallivm, blend, mode, type); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { LLVMDumpModule(module); @@ -497,24 +496,6 @@ test_one(unsigned verbose, } LLVMDisposeMessage(error); -#if 0 - pass = LLVMCreatePassManager(); - LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - LLVMAddPromoteMemoryToRegisterPass(pass); - LLVMAddGVNPass(pass); - LLVMAddCFGSimplificationPass(pass); - LLVMRunPassManager(pass, module); -#else - (void)pass; -#endif - - if(verbose >= 2) - LLVMDumpModule(module); - code = LLVMGetPointerToGlobal(engine, func); blend_test_ptr = voidptr_to_blend_test_ptr_t(code); @@ -715,9 +696,6 @@ test_one(unsigned verbose, LLVMFreeMachineCodeForFunction(engine, func); - if(pass) - LLVMDisposePassManager(pass); - return success; } @@ -773,7 +751,7 @@ const unsigned num_types = sizeof(blend_types)/sizeof(blend_types[0]); boolean -test_all(unsigned verbose, FILE *fp) +test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { const unsigned *rgb_func; const unsigned *rgb_src_factor; @@ -809,7 +787,7 @@ test_all(unsigned verbose, FILE *fp) blend.rt[0].alpha_dst_factor = *alpha_dst_factor; blend.rt[0].colormask = PIPE_MASK_RGBA; - if(!test_one(verbose, fp, &blend, mode, *type)) + if(!test_one(gallivm, verbose, fp, &blend, mode, *type)) success = FALSE; } @@ -826,7 +804,8 @@ test_all(unsigned verbose, FILE *fp) boolean -test_some(unsigned verbose, FILE *fp, unsigned long n) +test_some(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, + unsigned long n) { const unsigned *rgb_func; const unsigned *rgb_src_factor; @@ -868,7 +847,7 @@ test_some(unsigned verbose, FILE *fp, unsigned long n) blend.rt[0].alpha_dst_factor = *alpha_dst_factor; blend.rt[0].colormask = PIPE_MASK_RGBA; - if(!test_one(verbose, fp, &blend, mode, *type)) + if(!test_one(gallivm, verbose, fp, &blend, mode, *type)) success = FALSE; } @@ -877,7 +856,7 @@ test_some(unsigned verbose, FILE *fp, unsigned long n) boolean -test_single(unsigned verbose, FILE *fp) +test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { printf("no test_single()"); return TRUE; diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c index 3ba42bf11a6..f4a2f360c75 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_conv.c +++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c @@ -97,64 +97,65 @@ dump_conv_types(FILE *fp, static LLVMValueRef -add_conv_test(LLVMModuleRef module, +add_conv_test(struct gallivm_state *gallivm, struct lp_type src_type, unsigned num_srcs, struct lp_type dst_type, unsigned num_dsts) { + LLVMModuleRef module = gallivm->module; + LLVMContextRef context = gallivm->context; + LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef args[2]; LLVMValueRef func; LLVMValueRef src_ptr; LLVMValueRef dst_ptr; LLVMBasicBlockRef block; - LLVMBuilderRef builder; LLVMValueRef src[LP_MAX_VECTOR_LENGTH]; LLVMValueRef dst[LP_MAX_VECTOR_LENGTH]; unsigned i; - args[0] = LLVMPointerType(lp_build_vec_type(src_type), 0); - args[1] = LLVMPointerType(lp_build_vec_type(dst_type), 0); + args[0] = LLVMPointerType(lp_build_vec_type(gallivm, src_type), 0); + args[1] = LLVMPointerType(lp_build_vec_type(gallivm, dst_type), 0); - func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 2, 0)); + func = LLVMAddFunction(module, "test", + LLVMFunctionType(LLVMVoidTypeInContext(context), + args, 2, 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); src_ptr = LLVMGetParam(func, 0); dst_ptr = LLVMGetParam(func, 1); - block = LLVMAppendBasicBlock(func, "entry"); - builder = LLVMCreateBuilder(); + block = LLVMAppendBasicBlockInContext(context, func, "entry"); LLVMPositionBuilderAtEnd(builder, block); for(i = 0; i < num_srcs; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + LLVMValueRef index = LLVMConstInt(LLVMInt32TypeInContext(context), i, 0); LLVMValueRef ptr = LLVMBuildGEP(builder, src_ptr, &index, 1, ""); src[i] = LLVMBuildLoad(builder, ptr, ""); } - lp_build_conv(builder, src_type, dst_type, src, num_srcs, dst, num_dsts); + lp_build_conv(gallivm, src_type, dst_type, src, num_srcs, dst, num_dsts); for(i = 0; i < num_dsts; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); + LLVMValueRef index = LLVMConstInt(LLVMInt32TypeInContext(context), i, 0); LLVMValueRef ptr = LLVMBuildGEP(builder, dst_ptr, &index, 1, ""); LLVMBuildStore(builder, dst[i], ptr); } LLVMBuildRetVoid(builder);; - LLVMDisposeBuilder(builder); return func; } PIPE_ALIGN_STACK static boolean -test_one(unsigned verbose, +test_one(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, struct lp_type src_type, struct lp_type dst_type) { - LLVMModuleRef module = NULL; + LLVMModuleRef module = gallivm->module; + LLVMExecutionEngineRef engine = gallivm->engine; LLVMValueRef func = NULL; - LLVMExecutionEngineRef engine = lp_build_engine; - LLVMPassManagerRef pass = NULL; char *error = NULL; conv_test_ptr_t conv_test_ptr; boolean success; @@ -193,9 +194,7 @@ test_one(unsigned verbose, eps = MAX2(lp_const_eps(src_type), lp_const_eps(dst_type)); - module = LLVMModuleCreateWithName("test"); - - func = add_conv_test(module, src_type, num_srcs, dst_type, num_dsts); + func = add_conv_test(gallivm, src_type, num_srcs, dst_type, num_dsts); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { LLVMDumpModule(module); @@ -203,21 +202,6 @@ test_one(unsigned verbose, } LLVMDisposeMessage(error); -#if 0 - pass = LLVMCreatePassManager(); - LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - LLVMAddPromoteMemoryToRegisterPass(pass); - LLVMAddGVNPass(pass); - LLVMAddCFGSimplificationPass(pass); - LLVMRunPassManager(pass, module); -#else - (void)pass; -#endif - if(verbose >= 2) LLVMDumpModule(module); @@ -342,9 +326,6 @@ test_one(unsigned verbose, LLVMFreeMachineCodeForFunction(engine, func); - if(pass) - LLVMDisposePassManager(pass); - return success; } @@ -390,7 +371,7 @@ const unsigned num_types = sizeof(conv_types)/sizeof(conv_types[0]); boolean -test_all(unsigned verbose, FILE *fp) +test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { const struct lp_type *src_type; const struct lp_type *dst_type; @@ -405,7 +386,7 @@ test_all(unsigned verbose, FILE *fp) if(src_type->norm != dst_type->norm) continue; - if(!test_one(verbose, fp, *src_type, *dst_type)) + if(!test_one(gallivm, verbose, fp, *src_type, *dst_type)) success = FALSE; } @@ -416,7 +397,8 @@ test_all(unsigned verbose, FILE *fp) boolean -test_some(unsigned verbose, FILE *fp, unsigned long n) +test_some(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, + unsigned long n) { const struct lp_type *src_type; const struct lp_type *dst_type; @@ -430,7 +412,7 @@ test_some(unsigned verbose, FILE *fp, unsigned long n) dst_type = &conv_types[rand() % num_types]; } while (src_type == dst_type || src_type->norm != dst_type->norm); - if(!test_one(verbose, fp, *src_type, *dst_type)) + if(!test_one(gallivm, verbose, fp, *src_type, *dst_type)) success = FALSE; } @@ -439,7 +421,7 @@ test_some(unsigned verbose, FILE *fp, unsigned long n) boolean -test_single(unsigned verbose, FILE *fp) +test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { /* float, fixed, sign, norm, width, len */ struct lp_type f32x4_type = @@ -449,7 +431,7 @@ test_single(unsigned verbose, FILE *fp) boolean success; - success = test_one(verbose, fp, f32x4_type, ub8x4_type); + success = test_one(gallivm, verbose, fp, f32x4_type, ub8x4_type); return success; } diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c index 2855d7cea4f..4152ca6cf63 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_format.c +++ b/src/gallium/drivers/llvmpipe/lp_test_format.c @@ -30,13 +30,6 @@ #include <stdio.h> #include <float.h> -#include "gallivm/lp_bld.h" -#include "gallivm/lp_bld_debug.h" -#include "gallivm/lp_bld_init.h" -#include <llvm-c/Analysis.h> -#include <llvm-c/Target.h> -#include <llvm-c/Transforms/Scalar.h> - #include "util/u_memory.h" #include "util/u_pointer.h" #include "util/u_string.h" @@ -44,7 +37,11 @@ #include "util/u_format_tests.h" #include "util/u_format_s3tc.h" +#include "gallivm/lp_bld.h" +#include "gallivm/lp_bld_debug.h" #include "gallivm/lp_bld_format.h" +#include "gallivm/lp_bld_init.h" + #include "lp_test.h" @@ -78,56 +75,57 @@ typedef void static LLVMValueRef -add_fetch_rgba_test(unsigned verbose, +add_fetch_rgba_test(struct gallivm_state *gallivm, unsigned verbose, const struct util_format_description *desc, struct lp_type type) { char name[256]; + LLVMContextRef context = gallivm->context; + LLVMModuleRef module = gallivm->module; + LLVMBuilderRef builder = gallivm->builder; + LLVMPassManagerRef passmgr = gallivm->passmgr; LLVMTypeRef args[4]; LLVMValueRef func; LLVMValueRef packed_ptr; - LLVMValueRef offset = LLVMConstNull(LLVMInt32Type()); + LLVMValueRef offset = LLVMConstNull(LLVMInt32TypeInContext(context)); LLVMValueRef rgba_ptr; LLVMValueRef i; LLVMValueRef j; LLVMBasicBlockRef block; - LLVMBuilderRef builder; LLVMValueRef rgba; util_snprintf(name, sizeof name, "fetch_%s_%s", desc->short_name, type.floating ? "float" : "unorm8"); - args[0] = LLVMPointerType(lp_build_vec_type(type), 0); - args[1] = LLVMPointerType(LLVMInt8Type(), 0); - args[3] = args[2] = LLVMInt32Type(); + args[0] = LLVMPointerType(lp_build_vec_type(gallivm, type), 0); + args[1] = LLVMPointerType(LLVMInt8TypeInContext(context), 0); + args[3] = args[2] = LLVMInt32TypeInContext(context); - func = LLVMAddFunction(lp_build_module, name, - LLVMFunctionType(LLVMVoidType(), args, Elements(args), 0)); + func = LLVMAddFunction(module, name, + LLVMFunctionType(LLVMVoidTypeInContext(context), + args, Elements(args), 0)); LLVMSetFunctionCallConv(func, LLVMCCallConv); rgba_ptr = LLVMGetParam(func, 0); packed_ptr = LLVMGetParam(func, 1); i = LLVMGetParam(func, 2); j = LLVMGetParam(func, 3); - block = LLVMAppendBasicBlock(func, "entry"); - builder = LLVMCreateBuilder(); + block = LLVMAppendBasicBlockInContext(context, func, "entry"); LLVMPositionBuilderAtEnd(builder, block); - rgba = lp_build_fetch_rgba_aos(builder, desc, type, + rgba = lp_build_fetch_rgba_aos(gallivm, desc, type, packed_ptr, offset, i, j); LLVMBuildStore(builder, rgba, rgba_ptr); LLVMBuildRetVoid(builder); - LLVMDisposeBuilder(builder); - if (LLVMVerifyFunction(func, LLVMPrintMessageAction)) { LLVMDumpValue(func); abort(); } - LLVMRunFunctionPassManager(lp_build_pass, func); + LLVMRunFunctionPassManager(passmgr, func); if (verbose >= 1) { LLVMDumpValue(func); @@ -139,10 +137,11 @@ add_fetch_rgba_test(unsigned verbose, PIPE_ALIGN_STACK static boolean -test_format_float(unsigned verbose, FILE *fp, +test_format_float(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, const struct util_format_description *desc) { LLVMValueRef fetch = NULL; + LLVMExecutionEngineRef engine = gallivm->engine; fetch_ptr_t fetch_ptr; PIPE_ALIGN_VAR(16) float unpacked[4]; boolean first = TRUE; @@ -150,9 +149,9 @@ test_format_float(unsigned verbose, FILE *fp, unsigned i, j, k, l; void *f; - fetch = add_fetch_rgba_test(verbose, desc, lp_float32_vec4_type()); + fetch = add_fetch_rgba_test(gallivm, verbose, desc, lp_float32_vec4_type()); - f = LLVMGetPointerToGlobal(lp_build_engine, fetch); + f = LLVMGetPointerToGlobal(engine, fetch); fetch_ptr = (fetch_ptr_t) pointer_to_func(f); if (verbose >= 2) { @@ -208,7 +207,7 @@ test_format_float(unsigned verbose, FILE *fp, } } - LLVMFreeMachineCodeForFunction(lp_build_engine, fetch); + LLVMFreeMachineCodeForFunction(engine, fetch); LLVMDeleteFunction(fetch); if(fp) @@ -220,7 +219,8 @@ test_format_float(unsigned verbose, FILE *fp, PIPE_ALIGN_STACK static boolean -test_format_unorm8(unsigned verbose, FILE *fp, +test_format_unorm8(struct gallivm_state *gallivm, + unsigned verbose, FILE *fp, const struct util_format_description *desc) { LLVMValueRef fetch = NULL; @@ -231,9 +231,9 @@ test_format_unorm8(unsigned verbose, FILE *fp, unsigned i, j, k, l; void *f; - fetch = add_fetch_rgba_test(verbose, desc, lp_unorm8_vec4_type()); + fetch = add_fetch_rgba_test(gallivm, verbose, desc, lp_unorm8_vec4_type()); - f = LLVMGetPointerToGlobal(lp_build_engine, fetch); + f = LLVMGetPointerToGlobal(gallivm->engine, fetch); fetch_ptr = (fetch_ptr_t) pointer_to_func(f); if (verbose >= 2) { @@ -290,7 +290,7 @@ test_format_unorm8(unsigned verbose, FILE *fp, if (!success) LLVMDumpValue(fetch); - LLVMFreeMachineCodeForFunction(lp_build_engine, fetch); + LLVMFreeMachineCodeForFunction(gallivm->engine, fetch); LLVMDeleteFunction(fetch); if(fp) @@ -303,16 +303,17 @@ test_format_unorm8(unsigned verbose, FILE *fp, static boolean -test_one(unsigned verbose, FILE *fp, +test_one(struct gallivm_state *gallivm, + unsigned verbose, FILE *fp, const struct util_format_description *format_desc) { boolean success = TRUE; - if (!test_format_float(verbose, fp, format_desc)) { + if (!test_format_float(gallivm, verbose, fp, format_desc)) { success = FALSE; } - if (!test_format_unorm8(verbose, fp, format_desc)) { + if (!test_format_unorm8(gallivm, verbose, fp, format_desc)) { success = FALSE; } @@ -321,7 +322,7 @@ test_one(unsigned verbose, FILE *fp, boolean -test_all(unsigned verbose, FILE *fp) +test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { enum pipe_format format; boolean success = TRUE; @@ -349,7 +350,7 @@ test_all(unsigned verbose, FILE *fp) continue; } - if (!test_one(verbose, fp, format_desc)) { + if (!test_one(gallivm, verbose, fp, format_desc)) { success = FALSE; } } @@ -359,14 +360,15 @@ test_all(unsigned verbose, FILE *fp) boolean -test_some(unsigned verbose, FILE *fp, unsigned long n) +test_some(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, + unsigned long n) { - return test_all(verbose, fp); + return test_all(gallivm, verbose, fp); } boolean -test_single(unsigned verbose, FILE *fp) +test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { printf("no test_single()"); return TRUE; diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c index 7a0d06ae2c8..149ee6f1256 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_main.c +++ b/src/gallium/drivers/llvmpipe/lp_test_main.c @@ -380,6 +380,7 @@ int main(int argc, char **argv) unsigned i; boolean success; boolean single = FALSE; + struct gallivm_state *gallivm; for(i = 1; i < argc; ++i) { if(strcmp(argv[i], "-v") == 0) @@ -394,21 +395,23 @@ int main(int argc, char **argv) lp_build_init(); + gallivm = gallivm_create(); + util_cpu_detect(); if(fp) { /* Warm up the caches */ - test_some(0, NULL, 100); + test_some(gallivm, 0, NULL, 100); write_tsv_header(fp); } if (single) - success = test_single(verbose, fp); + success = test_single(gallivm, verbose, fp); else if (n) - success = test_some(verbose, fp, n); + success = test_some(gallivm, verbose, fp, n); else - success = test_all(verbose, fp); + success = test_all(gallivm, verbose, fp); if(fp) fclose(fp); diff --git a/src/gallium/drivers/llvmpipe/lp_test_printf.c b/src/gallium/drivers/llvmpipe/lp_test_printf.c index 4653f30e39d..620cdb57c13 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_printf.c +++ b/src/gallium/drivers/llvmpipe/lp_test_printf.c @@ -35,11 +35,6 @@ #include "gallivm/lp_bld_assert.h" #include "gallivm/lp_bld_printf.h" -#include <llvm-c/Analysis.h> -#include <llvm-c/ExecutionEngine.h> -#include <llvm-c/Target.h> -#include <llvm-c/Transforms/Scalar.h> - #include "lp_test.h" @@ -63,48 +58,45 @@ typedef void (*test_printf_t)(int i); static LLVMValueRef -add_printf_test(LLVMModuleRef module) +add_printf_test(struct gallivm_state *gallivm) { - LLVMTypeRef args[1] = { LLVMIntType(32) }; - LLVMValueRef func = LLVMAddFunction(module, "test_printf", LLVMFunctionType(LLVMVoidType(), args, 1, 0)); - LLVMBuilderRef builder = LLVMCreateBuilder(); - LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); + LLVMModuleRef module = gallivm->module; + LLVMTypeRef args[1] = { LLVMIntTypeInContext(gallivm->context, 32) }; + LLVMValueRef func = LLVMAddFunction(module, "test_printf", LLVMFunctionType(LLVMVoidTypeInContext(gallivm->context), args, 1, 0)); + LLVMBuilderRef builder = gallivm->builder; + LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(gallivm->context, func, "entry"); LLVMSetFunctionCallConv(func, LLVMCCallConv); LLVMPositionBuilderAtEnd(builder, block); - lp_build_printf(builder, "hello, world\n"); - lp_build_printf(builder, "print 5 6: %d %d\n", LLVMConstInt(LLVMInt32Type(), 5, 0), - LLVMConstInt(LLVMInt32Type(), 6, 0)); + lp_build_printf(gallivm, "hello, world\n"); + lp_build_printf(gallivm, "print 5 6: %d %d\n", LLVMConstInt(LLVMInt32TypeInContext(gallivm->context), 5, 0), + LLVMConstInt(LLVMInt32TypeInContext(gallivm->context), 6, 0)); /* Also test lp_build_assert(). This should not fail. */ - lp_build_assert(builder, LLVMConstInt(LLVMInt32Type(), 1, 0), "assert(1)"); + lp_build_assert(gallivm, LLVMConstInt(LLVMInt32TypeInContext(gallivm->context), 1, 0), "assert(1)"); LLVMBuildRetVoid(builder); - LLVMDisposeBuilder(builder); + return func; } PIPE_ALIGN_STACK static boolean -test_printf(unsigned verbose, FILE *fp, const struct printf_test_case *testcase) +test_printf(struct gallivm_state *gallivm, + unsigned verbose, FILE *fp, + const struct printf_test_case *testcase) { - LLVMModuleRef module = NULL; - LLVMValueRef test = NULL; - LLVMExecutionEngineRef engine = NULL; - LLVMModuleProviderRef provider = NULL; - LLVMPassManagerRef pass = NULL; + LLVMExecutionEngineRef engine = gallivm->engine; + LLVMModuleRef module = gallivm->module; + LLVMValueRef test; char *error = NULL; - test_printf_t test_printf; - float unpacked[4]; - unsigned packed; + test_printf_t test_printf_func; boolean success = TRUE; void *code; - module = LLVMModuleCreateWithName("test"); - - test = add_printf_test(module); + test = add_printf_test(gallivm); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { LLVMDumpModule(module); @@ -112,74 +104,40 @@ test_printf(unsigned verbose, FILE *fp, const struct printf_test_case *testcase) } LLVMDisposeMessage(error); - provider = LLVMCreateModuleProviderForExistingModule(module); -#if 0 - if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) { - fprintf(stderr, "%s\n", error); - LLVMDisposeMessage(error); - abort(); - } -#else - (void) provider; - engine = lp_build_engine; -#endif - -#if 0 - pass = LLVMCreatePassManager(); - LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - LLVMAddPromoteMemoryToRegisterPass(pass); - LLVMAddGVNPass(pass); - LLVMAddCFGSimplificationPass(pass); - LLVMRunPassManager(pass, module); -#else - (void)pass; -#endif - code = LLVMGetPointerToGlobal(engine, test); - test_printf = (test_printf_t)pointer_to_func(code); - - memset(unpacked, 0, sizeof unpacked); - packed = 0; - + test_printf_func = (test_printf_t) pointer_to_func(code); // LLVMDumpModule(module); - test_printf(0); + test_printf_func(0); LLVMFreeMachineCodeForFunction(engine, test); - LLVMDisposeExecutionEngine(engine); - if(pass) - LLVMDisposePassManager(pass); - return success; } boolean -test_all(unsigned verbose, FILE *fp) +test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { boolean success = TRUE; - test_printf(verbose, fp, NULL); + test_printf(gallivm, verbose, fp, NULL); return success; } boolean -test_some(unsigned verbose, FILE *fp, unsigned long n) +test_some(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, + unsigned long n) { - return test_all(verbose, fp); + return test_all(gallivm, verbose, fp); } boolean -test_single(unsigned verbose, FILE *fp) +test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { printf("no test_single()"); return TRUE; diff --git a/src/gallium/drivers/llvmpipe/lp_test_round.c b/src/gallium/drivers/llvmpipe/lp_test_round.c index 816518e5081..4edee4af123 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_round.c +++ b/src/gallium/drivers/llvmpipe/lp_test_round.c @@ -34,11 +34,6 @@ #include "gallivm/lp_bld_init.h" #include "gallivm/lp_bld_arit.h" -#include <llvm-c/Analysis.h> -#include <llvm-c/ExecutionEngine.h> -#include <llvm-c/Target.h> -#include <llvm-c/Transforms/Scalar.h> - #include "lp_test.h" @@ -64,18 +59,21 @@ typedef LLVMValueRef (*lp_func_t)(struct lp_build_context *, LLVMValueRef); static LLVMValueRef -add_test(LLVMModuleRef module, const char *name, lp_func_t lp_func) +add_test(struct gallivm_state *gallivm, const char *name, lp_func_t lp_func) { - LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatType(), 4); + LLVMModuleRef module = gallivm->module; + LLVMContextRef context = gallivm->context; + LLVMBuilderRef builder = gallivm->builder; + + LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatTypeInContext(context), 4); LLVMTypeRef args[1] = { v4sf }; LLVMValueRef func = LLVMAddFunction(module, name, LLVMFunctionType(v4sf, args, 1, 0)); LLVMValueRef arg1 = LLVMGetParam(func, 0); - LLVMBuilderRef builder = LLVMCreateBuilder(); - LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); + LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(context, func, "entry"); LLVMValueRef ret; struct lp_build_context bld; - lp_build_context_init(&bld, builder, lp_float32_vec4_type()); + lp_build_context_init(&bld, gallivm, lp_float32_vec4_type()); LLVMSetFunctionCallConv(func, LLVMCCallConv); @@ -84,7 +82,7 @@ add_test(LLVMModuleRef module, const char *name, lp_func_t lp_func) ret = lp_func(&bld, arg1); LLVMBuildRet(builder, ret); - LLVMDisposeBuilder(builder); + return func; } @@ -117,12 +115,11 @@ compare(v4sf x, v4sf y) PIPE_ALIGN_STACK static boolean -test_round(unsigned verbose, FILE *fp) +test_round(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { - LLVMModuleRef module = NULL; + LLVMModuleRef module = gallivm->module; LLVMValueRef test_round = NULL, test_trunc, test_floor, test_ceil; - LLVMExecutionEngineRef engine = lp_build_engine; - LLVMPassManagerRef pass = NULL; + LLVMExecutionEngineRef engine = gallivm->engine; char *error = NULL; test_round_t round_func, trunc_func, floor_func, ceil_func; float unpacked[4]; @@ -130,12 +127,10 @@ test_round(unsigned verbose, FILE *fp) boolean success = TRUE; int i; - module = LLVMModuleCreateWithName("test"); - - test_round = add_test(module, "round", lp_build_round); - test_trunc = add_test(module, "trunc", lp_build_trunc); - test_floor = add_test(module, "floor", lp_build_floor); - test_ceil = add_test(module, "ceil", lp_build_ceil); + test_round = add_test(gallivm, "round", lp_build_round); + test_trunc = add_test(gallivm, "trunc", lp_build_trunc); + test_floor = add_test(gallivm, "floor", lp_build_floor); + test_ceil = add_test(gallivm, "ceil", lp_build_ceil); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { printf("LLVMVerifyModule: %s\n", error); @@ -144,21 +139,6 @@ test_round(unsigned verbose, FILE *fp) } LLVMDisposeMessage(error); -#if 0 - pass = LLVMCreatePassManager(); - LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - LLVMAddPromoteMemoryToRegisterPass(pass); - LLVMAddGVNPass(pass); - LLVMAddCFGSimplificationPass(pass); - LLVMRunPassManager(pass, module); -#else - (void)pass; -#endif - round_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_round)); trunc_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_trunc)); floor_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_floor)); @@ -229,17 +209,13 @@ test_round(unsigned verbose, FILE *fp) LLVMFreeMachineCodeForFunction(engine, test_floor); LLVMFreeMachineCodeForFunction(engine, test_ceil); - LLVMDisposeExecutionEngine(engine); - if(pass) - LLVMDisposePassManager(pass); - return success; } #else /* !PIPE_ARCH_SSE */ static boolean -test_round(unsigned verbose, FILE *fp) +test_round(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { return TRUE; } @@ -248,20 +224,21 @@ test_round(unsigned verbose, FILE *fp) boolean -test_all(unsigned verbose, FILE *fp) +test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { - return test_round(verbose, fp); + return test_round(gallivm, verbose, fp); } boolean -test_some(unsigned verbose, FILE *fp, unsigned long n) +test_some(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, + unsigned long n) { - return test_all(verbose, fp); + return test_all(gallivm, verbose, fp); } boolean -test_single(unsigned verbose, FILE *fp) +test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { printf("no test_single()"); return TRUE; diff --git a/src/gallium/drivers/llvmpipe/lp_test_sincos.c b/src/gallium/drivers/llvmpipe/lp_test_sincos.c index 79939b1a393..066d633d443 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_sincos.c +++ b/src/gallium/drivers/llvmpipe/lp_test_sincos.c @@ -29,15 +29,11 @@ #include <stdlib.h> #include <stdio.h> +#include "util/u_pointer.h" + #include "gallivm/lp_bld.h" #include "gallivm/lp_bld_init.h" #include "gallivm/lp_bld_arit.h" -#include "util/u_pointer.h" - -#include <llvm-c/Analysis.h> -#include <llvm-c/ExecutionEngine.h> -#include <llvm-c/Target.h> -#include <llvm-c/Transforms/Scalar.h> #include "lp_test.h" @@ -61,25 +57,25 @@ write_tsv_header(FILE *fp) typedef __m128 (*test_sincos_t)(__m128); static LLVMValueRef -add_sincos_test(LLVMModuleRef module, boolean sin) +add_sincos_test(struct gallivm_state *gallivm, LLVMModuleRef module, + LLVMContextRef context, boolean sin) { - LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatType(), 4); + LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatTypeInContext(context), 4); LLVMTypeRef args[1] = { v4sf }; LLVMValueRef func = LLVMAddFunction(module, "sincos", LLVMFunctionType(v4sf, args, 1, 0)); LLVMValueRef arg1 = LLVMGetParam(func, 0); - LLVMBuilderRef builder = LLVMCreateBuilder(); - LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry"); + LLVMBuilderRef builder = gallivm->builder; + LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(context, func, "entry"); LLVMValueRef ret; struct lp_build_context bld; - lp_build_context_init(&bld, builder, lp_float32_vec4_type()); + lp_build_context_init(&bld, gallivm, lp_float32_vec4_type()); LLVMSetFunctionCallConv(func, LLVMCCallConv); LLVMPositionBuilderAtEnd(builder, block); ret = sin ? lp_build_sin(&bld, arg1) : lp_build_cos(&bld, arg1); LLVMBuildRet(builder, ret); - LLVMDisposeBuilder(builder); return func; } @@ -95,22 +91,20 @@ printv(char* string, v4sf value) PIPE_ALIGN_STACK static boolean -test_sincos(unsigned verbose, FILE *fp) +test_sincos(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { - LLVMModuleRef module = NULL; + LLVMModuleRef module = gallivm->module; LLVMValueRef test_sin = NULL, test_cos = NULL; - LLVMExecutionEngineRef engine = lp_build_engine; - LLVMPassManagerRef pass = NULL; + LLVMExecutionEngineRef engine = gallivm->engine; + LLVMContextRef context = gallivm->context; char *error = NULL; test_sincos_t sin_func; test_sincos_t cos_func; float unpacked[4]; boolean success = TRUE; - module = LLVMModuleCreateWithName("test"); - - test_sin = add_sincos_test(module, TRUE); - test_cos = add_sincos_test(module, FALSE); + test_sin = add_sincos_test(gallivm, module, context, TRUE); + test_cos = add_sincos_test(gallivm, module, context,FALSE); if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) { printf("LLVMVerifyModule: %s\n", error); @@ -119,21 +113,6 @@ test_sincos(unsigned verbose, FILE *fp) } LLVMDisposeMessage(error); -#if 0 - pass = LLVMCreatePassManager(); - LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass); - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - LLVMAddConstantPropagationPass(pass); - LLVMAddInstructionCombiningPass(pass); - LLVMAddPromoteMemoryToRegisterPass(pass); - LLVMAddGVNPass(pass); - LLVMAddCFGSimplificationPass(pass); - LLVMRunPassManager(pass, module); -#else - (void)pass; -#endif - sin_func = (test_sincos_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_sin)); cos_func = (test_sincos_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_cos)); @@ -152,16 +131,13 @@ test_sincos(unsigned verbose, FILE *fp) LLVMFreeMachineCodeForFunction(engine, test_sin); LLVMFreeMachineCodeForFunction(engine, test_cos); - if(pass) - LLVMDisposePassManager(pass); - return success; } #else /* !PIPE_ARCH_SSE */ static boolean -test_sincos(unsigned verbose, FILE *fp) +test_sincos(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { return TRUE; } @@ -170,24 +146,25 @@ test_sincos(unsigned verbose, FILE *fp) boolean -test_all(unsigned verbose, FILE *fp) +test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { boolean success = TRUE; - test_sincos(verbose, fp); + test_sincos(gallivm, verbose, fp); return success; } boolean -test_some(unsigned verbose, FILE *fp, unsigned long n) +test_some(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, + unsigned long n) { - return test_all(verbose, fp); + return test_all(gallivm, verbose, fp); } boolean -test_single(unsigned verbose, FILE *fp) +test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp) { printf("no test_single()"); return TRUE; diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c index f417fc8a9ea..ed4282937f8 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c @@ -43,6 +43,7 @@ #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" #include "gallivm/lp_bld_debug.h" +#include "gallivm/lp_bld_const.h" #include "gallivm/lp_bld_type.h" #include "gallivm/lp_bld_sample.h" #include "gallivm/lp_bld_tgsi.h" @@ -89,7 +90,7 @@ struct lp_llvm_sampler_soa */ static LLVMValueRef lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, - LLVMBuilderRef builder, + struct gallivm_state *gallivm, unsigned unit, unsigned member_index, const char *member_name, @@ -97,6 +98,7 @@ lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, { struct llvmpipe_sampler_dynamic_state *state = (struct llvmpipe_sampler_dynamic_state *)base; + LLVMBuilderRef builder = gallivm->builder; LLVMValueRef indices[4]; LLVMValueRef ptr; LLVMValueRef res; @@ -104,13 +106,13 @@ lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, assert(unit < PIPE_MAX_SAMPLERS); /* context[0] */ - indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); + indices[0] = lp_build_const_int32(gallivm, 0); /* context[0].textures */ - indices[1] = LLVMConstInt(LLVMInt32Type(), LP_JIT_CTX_TEXTURES, 0); + indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_TEXTURES); /* context[0].textures[unit] */ - indices[2] = LLVMConstInt(LLVMInt32Type(), unit, 0); + indices[2] = lp_build_const_int32(gallivm, unit); /* context[0].textures[unit].member */ - indices[3] = LLVMConstInt(LLVMInt32Type(), member_index, 0); + indices[3] = lp_build_const_int32(gallivm, member_index); ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), ""); @@ -137,10 +139,10 @@ lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, #define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \ static LLVMValueRef \ lp_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \ - LLVMBuilderRef builder, \ + struct gallivm_state *gallivm, \ unsigned unit) \ { \ - return lp_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \ + return lp_llvm_texture_member(base, gallivm, unit, _index, #_name, _emit_load ); \ } @@ -170,7 +172,7 @@ lp_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler) */ static void lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, - LLVMBuilderRef builder, + struct gallivm_state *gallivm, struct lp_type type, unsigned unit, unsigned num_coords, @@ -186,11 +188,11 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, assert(unit < PIPE_MAX_SAMPLERS); if (LP_PERF & PERF_NO_TEX) { - lp_build_sample_nop(type, texel); + lp_build_sample_nop(gallivm, type, texel); return; } - lp_build_sample_soa(builder, + lp_build_sample_soa(gallivm, &sampler->dynamic_state.static_state[unit], &sampler->dynamic_state.base, type, diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index a4b9f2590af..9753da5e57e 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -49,6 +49,7 @@ #include "lp_tile_image.h" #include "lp_texture.h" #include "lp_setup.h" +#include "lp_state.h" #include "state_tracker/sw_winsys.h" @@ -242,6 +243,7 @@ llvmpipe_resource_create(struct pipe_screen *_screen, /* other data (vertex buffer, const buffer, etc) */ const enum pipe_format format = templat->format; const uint w = templat->width0 / util_format_get_blockheight(format); + /* XXX buffers should only have one dimension, those values should be 1 */ const uint h = templat->height0 / util_format_get_blockwidth(format); const uint d = templat->depth0; const uint bpp = util_format_get_blocksize(format); @@ -329,17 +331,16 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen, */ void * llvmpipe_resource_map(struct pipe_resource *resource, - unsigned face, - unsigned level, - unsigned zslice, + unsigned level, + unsigned layer, enum lp_texture_usage tex_usage, enum lp_texture_layout layout) { struct llvmpipe_resource *lpr = llvmpipe_resource(resource); uint8_t *map; - assert(face < 6); assert(level < LP_MAX_TEXTURE_LEVELS); + assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1)); assert(tex_usage == LP_TEX_USAGE_READ || tex_usage == LP_TEX_USAGE_READ_WRITE || @@ -363,9 +364,8 @@ llvmpipe_resource_map(struct pipe_resource *resource, dt_usage = PIPE_TRANSFER_READ_WRITE; } - assert(face == 0); assert(level == 0); - assert(zslice == 0); + assert(layer == 0); /* FIXME: keep map count? */ map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage); @@ -381,15 +381,8 @@ llvmpipe_resource_map(struct pipe_resource *resource, return map2; } else if (resource_is_texture(resource)) { - /* regular texture */ - if (resource->target != PIPE_TEXTURE_CUBE) { - assert(face == 0); - } - if (resource->target != PIPE_TEXTURE_3D) { - assert(zslice == 0); - } - map = llvmpipe_get_texture_image(lpr, face + zslice, level, + map = llvmpipe_get_texture_image(lpr, layer, level, tex_usage, layout); return map; } @@ -404,9 +397,8 @@ llvmpipe_resource_map(struct pipe_resource *resource, */ void llvmpipe_resource_unmap(struct pipe_resource *resource, - unsigned face, unsigned level, - unsigned zslice) + unsigned layer) { struct llvmpipe_resource *lpr = llvmpipe_resource(resource); @@ -415,12 +407,11 @@ llvmpipe_resource_unmap(struct pipe_resource *resource, struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen); struct sw_winsys *winsys = lp_screen->winsys; - assert(face == 0); assert(level == 0); - assert(zslice == 0); + assert(layer == 0); /* make sure linear image is up to date */ - (void) llvmpipe_get_texture_image(lpr, face + zslice, level, + (void) llvmpipe_get_texture_image(lpr, layer, level, LP_TEX_USAGE_READ, LP_TEX_LAYOUT_LINEAR); @@ -520,34 +511,35 @@ llvmpipe_resource_get_handle(struct pipe_screen *screen, static struct pipe_surface * -llvmpipe_get_tex_surface(struct pipe_screen *screen, - struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned usage) +llvmpipe_create_surface(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { struct pipe_surface *ps; - assert(level <= pt->last_level); + assert(surf_tmpl->u.tex.level <= pt->last_level); ps = CALLOC_STRUCT(pipe_surface); if (ps) { pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = u_minify(pt->width0, level); - ps->height = u_minify(pt->height0, level); - ps->usage = usage; - - ps->face = face; - ps->level = level; - ps->zslice = zslice; + ps->context = pipe; + ps->format = surf_tmpl->format; + ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); + ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); + ps->usage = surf_tmpl->usage; + + ps->u.tex.level = surf_tmpl->u.tex.level; + ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; + ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; } return ps; } static void -llvmpipe_tex_surface_destroy(struct pipe_surface *surf) +llvmpipe_surface_destroy(struct pipe_context *pipe, + struct pipe_surface *surf) { /* Effectively do the texture_update work here - if texture images * needed post-processing to put them into hardware layout, this is @@ -561,16 +553,17 @@ llvmpipe_tex_surface_destroy(struct pipe_surface *surf) static struct pipe_transfer * llvmpipe_get_transfer(struct pipe_context *pipe, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { + struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct llvmpipe_resource *lprex = llvmpipe_resource(resource); struct llvmpipe_transfer *lpr; assert(resource); - assert(sr.level <= resource->last_level); + assert(level <= resource->last_level); /* * Transfers, like other pipe operations, must happen in order, so flush the @@ -580,7 +573,8 @@ llvmpipe_get_transfer(struct pipe_context *pipe, boolean read_only = !(usage & PIPE_TRANSFER_WRITE); boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); if (!llvmpipe_flush_resource(pipe, resource, - sr.face, sr.level, + level, + box->depth > 1 ? -1 : box->z, 0, /* flush_flags */ read_only, TRUE, /* cpu_access */ @@ -594,14 +588,17 @@ llvmpipe_get_transfer(struct pipe_context *pipe, } } + if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][0]) + llvmpipe->dirty |= LP_NEW_CONSTANTS; + lpr = CALLOC_STRUCT(llvmpipe_transfer); if (lpr) { struct pipe_transfer *pt = &lpr->base; pipe_resource_reference(&pt->resource, resource); pt->box = *box; - pt->sr = sr; - pt->stride = lprex->row_stride[sr.level]; - pt->slice_stride = lprex->img_stride[sr.level]; + pt->level = level; + pt->stride = lprex->row_stride[level]; + pt->layer_stride = lprex->img_stride[level]; pt->usage = usage; return pt; @@ -635,8 +632,7 @@ llvmpipe_transfer_map( struct pipe_context *pipe, enum lp_texture_usage tex_usage; const char *mode; - assert(transfer->sr.face < 6); - assert(transfer->sr.level < LP_MAX_TEXTURE_LEVELS); + assert(transfer->level < LP_MAX_TEXTURE_LEVELS); /* printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n", @@ -666,9 +662,8 @@ llvmpipe_transfer_map( struct pipe_context *pipe, format = lpr->base.format; map = llvmpipe_resource_map(transfer->resource, - transfer->sr.face, - transfer->sr.level, - transfer->box.z, + transfer->level, + transfer->box.z, tex_usage, LP_TEX_LAYOUT_LINEAR); @@ -680,7 +675,7 @@ llvmpipe_transfer_map( struct pipe_context *pipe, */ screen->timestamp++; } - + map += transfer->box.y / util_format_get_blockheight(format) * transfer->stride + transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); @@ -696,21 +691,20 @@ llvmpipe_transfer_unmap(struct pipe_context *pipe, assert(transfer->resource); llvmpipe_resource_unmap(transfer->resource, - transfer->sr.face, - transfer->sr.level, - transfer->box.z); + transfer->level, + transfer->box.z); } static unsigned int llvmpipe_is_resource_referenced( struct pipe_context *pipe, - struct pipe_resource *presource, - unsigned face, unsigned level) + struct pipe_resource *presource, + unsigned level, int layer) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); if (presource->target == PIPE_BUFFER) return PIPE_UNREFERENCED; - + return lp_setup_is_resource_referenced(llvmpipe->setup, presource); } @@ -740,6 +734,7 @@ llvmpipe_user_buffer_create(struct pipe_screen *screen, buffer->base.width0 = bytes; buffer->base.height0 = 1; buffer->base.depth0 = 1; + buffer->base.array_size = 1; buffer->userBuffer = TRUE; buffer->data = ptr; @@ -1396,8 +1391,6 @@ llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) screen->resource_get_handle = llvmpipe_resource_get_handle; screen->user_buffer_create = llvmpipe_user_buffer_create; - screen->get_tex_surface = llvmpipe_get_tex_surface; - screen->tex_surface_destroy = llvmpipe_tex_surface_destroy; } @@ -1412,4 +1405,7 @@ llvmpipe_init_context_resource_funcs(struct pipe_context *pipe) pipe->transfer_flush_region = u_default_transfer_flush_region; pipe->transfer_inline_write = u_default_transfer_inline_write; + + pipe->create_surface = llvmpipe_create_surface; + pipe->surface_destroy = llvmpipe_surface_destroy; } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index 4e4a65dcb40..b789c0f4090 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -172,17 +172,15 @@ llvmpipe_resource_stride(struct pipe_resource *resource, void * llvmpipe_resource_map(struct pipe_resource *resource, - unsigned face_slice, - unsigned level, - unsigned zslice, + unsigned level, + unsigned layer, enum lp_texture_usage tex_usage, enum lp_texture_layout layout); void llvmpipe_resource_unmap(struct pipe_resource *resource, - unsigned face_slice, unsigned level, - unsigned zslice); + unsigned layer); void * diff --git a/src/gallium/drivers/sw/Makefile b/src/gallium/drivers/noop/Makefile index 2713a62ee9f..29b8d73de22 100644 --- a/src/gallium/drivers/sw/Makefile +++ b/src/gallium/drivers/noop/Makefile @@ -4,7 +4,10 @@ TOP = ../../../.. include $(TOP)/configs/current +LIBNAME = noop + C_SOURCES = \ - sw.c + noop_pipe.c \ + noop_state.c include ../../Makefile.template diff --git a/src/gallium/drivers/noop/SConscript b/src/gallium/drivers/noop/SConscript new file mode 100644 index 00000000000..a4d0dcaf270 --- /dev/null +++ b/src/gallium/drivers/noop/SConscript @@ -0,0 +1,15 @@ +####################################################################### +# SConscript for noop convenience library + +Import('*') + +env = env.Clone() + +noop = env.ConvenienceLibrary( + target = 'noop', + source = [ + 'noop_pipe.c', + 'noop_state.c' + ] + ) + extra +Export('noop') diff --git a/src/gallium/drivers/noop/noop_pipe.c b/src/gallium/drivers/noop/noop_pipe.c new file mode 100644 index 00000000000..c9c463f470f --- /dev/null +++ b/src/gallium/drivers/noop/noop_pipe.c @@ -0,0 +1,515 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include <stdio.h> +#include <errno.h> +#include <pipe/p_defines.h> +#include <pipe/p_state.h> +#include <pipe/p_context.h> +#include <pipe/p_screen.h> +#include <util/u_memory.h> +#include <util/u_inlines.h> +#include <util/u_format.h> +#include "noop_public.h" +#include "state_tracker/sw_winsys.h" + +void noop_init_state_functions(struct pipe_context *ctx); + +/* + * query + */ +struct noop_query { + unsigned query; +}; +static struct pipe_query *noop_create_query(struct pipe_context *ctx, unsigned query_type) +{ + struct noop_query *query = CALLOC_STRUCT(noop_query); + + return (struct pipe_query *)query; +} + +static void noop_destroy_query(struct pipe_context *ctx, struct pipe_query *query) +{ + FREE(query); +} + +static void noop_begin_query(struct pipe_context *ctx, struct pipe_query *query) +{ +} + +static void noop_end_query(struct pipe_context *ctx, struct pipe_query *query) +{ +} + +static boolean noop_get_query_result(struct pipe_context *ctx, + struct pipe_query *query, + boolean wait, void *vresult) +{ + uint64_t *result = (uint64_t*)vresult; + + *result = 0; + return TRUE; +} + + +/* + * resource + */ +struct noop_resource { + struct pipe_resource base; + unsigned size; + char *data; + struct sw_displaytarget *dt; +}; + +static unsigned noop_is_resource_referenced(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, int layer) +{ + return PIPE_UNREFERENCED; +} + +static struct pipe_resource *noop_resource_create(struct pipe_screen *screen, + const struct pipe_resource *templ) +{ + struct noop_resource *nresource; + unsigned stride; + + nresource = CALLOC_STRUCT(noop_resource); + if (nresource == NULL) + return NULL; + + stride = util_format_get_stride(templ->format, templ->width0); + nresource->base = *templ; + nresource->base.screen = screen; + nresource->size = stride * templ->height0 * templ->depth0; + nresource->data = malloc(nresource->size); + pipe_reference_init(&nresource->base.reference, 1); + if (nresource->data == NULL) { + FREE(nresource); + return NULL; + } +#if 0 + if (nresource->base.bind & (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT | + PIPE_BIND_SHARED)) { + struct sw_winsys *winsys = (struct sw_winsys *)screen->winsys; + unsigned stride; + + nresource->dt = winsys->displaytarget_create(winsys, nresource->base.bind, + nresource->base.format, + nresource->base.width0, + nresource->base.height0, + 16, &stride); + } +#endif + return &nresource->base; +} + +static struct pipe_resource *noop_resource_from_handle(struct pipe_screen * screen, + const struct pipe_resource *templ, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = (struct sw_winsys *)screen->winsys; + struct noop_resource *nresource; + struct sw_displaytarget *dt; + unsigned stride; + + dt = winsys->displaytarget_from_handle(winsys, templ, whandle, &stride); + if (dt == NULL) { + return NULL; + } + nresource = (struct noop_resource *)noop_resource_create(screen, templ); + nresource->dt = dt; + return &nresource->base; +} + +static boolean noop_resource_get_handle(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle) +{ + struct sw_winsys *winsys = (struct sw_winsys *)screen->winsys; + struct noop_resource *nresource = (struct noop_resource *)resource; + + if (nresource->dt == NULL) + return FALSE; + + return winsys->displaytarget_get_handle(winsys, nresource->dt, handle); +} + +static void noop_resource_destroy(struct pipe_screen *screen, + struct pipe_resource *resource) +{ + struct noop_resource *nresource = (struct noop_resource *)resource; + + if (nresource->dt) { + /* display target */ + struct sw_winsys *winsys = (struct sw_winsys *)screen->winsys; + winsys->displaytarget_destroy(winsys, nresource->dt); + } + free(nresource->data); + FREE(resource); +} + +static struct pipe_resource *noop_user_buffer_create(struct pipe_screen *screen, + void *ptr, unsigned bytes, + unsigned bind) +{ + struct pipe_resource templ; + + templ.target = PIPE_BUFFER; + templ.format = PIPE_FORMAT_R8_UNORM; + templ.usage = PIPE_USAGE_IMMUTABLE; + templ.bind = bind; + templ.width0 = bytes; + templ.height0 = 1; + templ.depth0 = 1; + templ.flags = 0; + return noop_resource_create(screen, &templ); +} + + +/* + * transfer + */ +static struct pipe_transfer *noop_get_transfer(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + enum pipe_transfer_usage usage, + const struct pipe_box *box) +{ + struct pipe_transfer *transfer; + + transfer = CALLOC_STRUCT(pipe_transfer); + if (transfer == NULL) + return NULL; + pipe_resource_reference(&transfer->resource, resource); + transfer->level = level; + transfer->usage = usage; + transfer->box = *box; + transfer->stride = 1; + transfer->layer_stride = 1; + return transfer; +} + +static void *noop_transfer_map(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + struct noop_resource *nresource = (struct noop_resource *)transfer->resource; + + return nresource->data; +} + +static void noop_transfer_flush_region(struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ +} + +static void noop_transfer_unmap(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ +} + +static void noop_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + pipe_resource_reference(&transfer->resource, NULL); + FREE(transfer); +} + +static void noop_transfer_inline_write(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ +} + + +/* + * clear/copy + */ +static void noop_clear(struct pipe_context *ctx, unsigned buffers, + const float *rgba, double depth, unsigned stencil) +{ +} + +static void noop_clear_render_target(struct pipe_context *ctx, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ +} + +static void noop_clear_depth_stencil(struct pipe_context *ctx, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ +} + +static void noop_resource_copy_region(struct pipe_context *ctx, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box) +{ +} + + +/* + * context + */ +static void noop_flush(struct pipe_context *ctx, unsigned flags, + struct pipe_fence_handle **fence) +{ +} + +static void noop_destroy_context(struct pipe_context *ctx) +{ + FREE(ctx); +} + +static struct pipe_context *noop_create_context(struct pipe_screen *screen, void *priv) +{ + struct pipe_context *ctx = CALLOC_STRUCT(pipe_context); + + if (ctx == NULL) + return NULL; + ctx->winsys = screen->winsys; + ctx->screen = screen; + ctx->priv = priv; + ctx->destroy = noop_destroy_context; + ctx->flush = noop_flush; + ctx->clear = noop_clear; + ctx->clear_render_target = noop_clear_render_target; + ctx->clear_depth_stencil = noop_clear_depth_stencil; + ctx->resource_copy_region = noop_resource_copy_region; + ctx->create_query = noop_create_query; + ctx->destroy_query = noop_destroy_query; + ctx->begin_query = noop_begin_query; + ctx->end_query = noop_end_query; + ctx->get_query_result = noop_get_query_result; + ctx->get_transfer = noop_get_transfer; + ctx->transfer_map = noop_transfer_map; + ctx->transfer_flush_region = noop_transfer_flush_region; + ctx->transfer_unmap = noop_transfer_unmap; + ctx->transfer_destroy = noop_transfer_destroy; + ctx->transfer_inline_write = noop_transfer_inline_write; + ctx->is_resource_referenced = noop_is_resource_referenced; + noop_init_state_functions(ctx); + + return ctx; +} + + +/* + * pipe_screen + */ +static void noop_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_resource *resource, + unsigned level, unsigned layer, + void *context_private) +{ +} + +static const char *noop_get_vendor(struct pipe_screen* pscreen) +{ + return "X.Org"; +} + +static const char *noop_get_name(struct pipe_screen* pscreen) +{ + return "NOOP"; +} + +static int noop_get_param(struct pipe_screen* pscreen, enum pipe_cap param) +{ + switch (param) { + /* Supported features (boolean caps). */ + case PIPE_CAP_NPOT_TEXTURES: + case PIPE_CAP_TWO_SIDED_STENCIL: + case PIPE_CAP_GLSL: + case PIPE_CAP_OCCLUSION_QUERY: + case PIPE_CAP_POINT_SPRITE: + case PIPE_CAP_ANISOTROPIC_FILTER: + case PIPE_CAP_TEXTURE_MIRROR_CLAMP: + case PIPE_CAP_TEXTURE_MIRROR_REPEAT: + case PIPE_CAP_TEXTURE_SHADOW_MAP: + case PIPE_CAP_TEXTURE_SWIZZLE: + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + + return 1; + case PIPE_CAP_DUAL_SOURCE_BLEND: + + case PIPE_CAP_SM3: + case PIPE_CAP_INDEP_BLEND_ENABLE: + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + case PIPE_CAP_DEPTH_CLAMP: + case PIPE_CAP_SHADER_STENCIL_EXPORT: + case PIPE_CAP_TIMER_QUERY: + case PIPE_CAP_STREAM_OUTPUT: + case PIPE_CAP_PRIMITIVE_RESTART: + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + + /* Texturing. */ + case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: + case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: + case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: + return 14; + case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: + return 16; + case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: + case PIPE_CAP_MAX_COMBINED_SAMPLERS: + return 16; + + /* Render targets. */ + case PIPE_CAP_MAX_RENDER_TARGETS: + return 8; + + /* Fragment coordinate conventions. */ + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; + + default: + return 0; + } +} + +static float noop_get_paramf(struct pipe_screen* pscreen, enum pipe_cap param) +{ + switch (param) { + case PIPE_CAP_MAX_LINE_WIDTH: + case PIPE_CAP_MAX_LINE_WIDTH_AA: + case PIPE_CAP_MAX_POINT_WIDTH: + case PIPE_CAP_MAX_POINT_WIDTH_AA: + return 8192.0f; + case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: + return 16.0f; + case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: + return 16.0f; + default: + return 0.0f; + } +} + +static int noop_get_shader_param(struct pipe_screen* pscreen, unsigned shader, enum pipe_shader_cap param) +{ + switch(shader) + { + case PIPE_SHADER_FRAGMENT: + case PIPE_SHADER_VERTEX: + case PIPE_SHADER_GEOMETRY: + break; + default: + return 0; + } + + switch (param) { + case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: + case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: + case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: + case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: + return 16384; + case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: + return 8; + case PIPE_SHADER_CAP_MAX_INPUTS: + return 16; + case PIPE_SHADER_CAP_MAX_TEMPS: + return 256; + case PIPE_SHADER_CAP_MAX_ADDRS: + return 1; + case PIPE_SHADER_CAP_MAX_CONSTS: + return 256; + case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: + return 1; + case PIPE_SHADER_CAP_MAX_PREDS: + return 0; + case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: + return 1; + case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: + case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: + case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: + case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: + return 1; + default: + return 0; + } +} + +static boolean noop_is_format_supported(struct pipe_screen* screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned sample_count, + unsigned usage, + unsigned geom_flags) +{ + return true; +} + +static void noop_destroy_screen(struct pipe_screen *screen) +{ + FREE(screen); +} + +struct pipe_screen *noop_screen_create(struct sw_winsys *winsys) +{ + struct pipe_screen *screen; + + screen = CALLOC_STRUCT(pipe_screen); + if (screen == NULL) { + return NULL; + } + + screen->winsys = (struct pipe_winsys*)winsys; + screen->destroy = noop_destroy_screen; + screen->get_name = noop_get_name; + screen->get_vendor = noop_get_vendor; + screen->get_param = noop_get_param; + screen->get_shader_param = noop_get_shader_param; + screen->get_paramf = noop_get_paramf; + screen->is_format_supported = noop_is_format_supported; + screen->context_create = noop_create_context; + screen->resource_create = noop_resource_create; + screen->resource_from_handle = noop_resource_from_handle; + screen->resource_get_handle = noop_resource_get_handle; + screen->resource_destroy = noop_resource_destroy; + screen->user_buffer_create = noop_user_buffer_create; + screen->flush_frontbuffer = noop_flush_frontbuffer; + + return screen; +} diff --git a/src/gallium/drivers/noop/noop_public.h b/src/gallium/drivers/noop/noop_public.h new file mode 100644 index 00000000000..8ce82bec698 --- /dev/null +++ b/src/gallium/drivers/noop/noop_public.h @@ -0,0 +1,30 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NOOP_PUBLIC_H +#define NOOP_PUBLIC_H + +struct sw_winsys; + +struct pipe_screen *noop_screen_create(struct sw_winsys *winsys); + +#endif diff --git a/src/gallium/drivers/noop/noop_state.c b/src/gallium/drivers/noop/noop_state.c new file mode 100644 index 00000000000..ad324774c03 --- /dev/null +++ b/src/gallium/drivers/noop/noop_state.c @@ -0,0 +1,290 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include <stdio.h> +#include <errno.h> +#include <pipe/p_defines.h> +#include <pipe/p_state.h> +#include <pipe/p_context.h> +#include <pipe/p_screen.h> +#include <util/u_memory.h> +#include <util/u_inlines.h> + +static void noop_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) +{ +} + +static void noop_set_blend_color(struct pipe_context *ctx, + const struct pipe_blend_color *state) +{ +} + +static void *noop_create_blend_state(struct pipe_context *ctx, + const struct pipe_blend_state *state) +{ + struct pipe_blend_state *nstate = CALLOC_STRUCT(pipe_blend_state); + + if (nstate == NULL) { + return NULL; + } + *nstate = *state; + return nstate; +} + +static void *noop_create_dsa_state(struct pipe_context *ctx, + const struct pipe_depth_stencil_alpha_state *state) +{ + struct pipe_depth_stencil_alpha_state *nstate = CALLOC_STRUCT(pipe_depth_stencil_alpha_state); + + if (nstate == NULL) { + return NULL; + } + *nstate = *state; + return nstate; +} + +static void *noop_create_rs_state(struct pipe_context *ctx, + const struct pipe_rasterizer_state *state) +{ + struct pipe_rasterizer_state *nstate = CALLOC_STRUCT(pipe_rasterizer_state); + + if (nstate == NULL) { + return NULL; + } + *nstate = *state; + return nstate; +} + +static void *noop_create_sampler_state(struct pipe_context *ctx, + const struct pipe_sampler_state *state) +{ + struct pipe_sampler_state *nstate = CALLOC_STRUCT(pipe_sampler_state); + + if (nstate == NULL) { + return NULL; + } + *nstate = *state; + return nstate; +} + +static struct pipe_sampler_view *noop_create_sampler_view(struct pipe_context *ctx, + struct pipe_resource *texture, + const struct pipe_sampler_view *state) +{ + struct pipe_sampler_view *sampler_view = CALLOC_STRUCT(pipe_sampler_view); + + if (sampler_view == NULL) + return NULL; + /* initialize base object */ + pipe_resource_reference(&sampler_view->texture, texture); + pipe_reference_init(&sampler_view->reference, 1); + sampler_view->context = ctx; + return sampler_view; +} + +static struct pipe_surface *noop_create_surface(struct pipe_context *ctx, + struct pipe_resource *texture, + const struct pipe_surface *surf_tmpl) +{ + struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface); + + if (surface == NULL) + return NULL; + pipe_reference_init(&surface->reference, 1); + pipe_resource_reference(&surface->texture, texture); + surface->context = ctx; + surface->format = surf_tmpl->format; + surface->width = texture->width0; + surface->height = texture->height0; + surface->usage = surf_tmpl->usage; + surface->texture = texture; + surface->u.tex.first_layer = surf_tmpl->u.tex.first_layer; + surface->u.tex.last_layer = surf_tmpl->u.tex.last_layer; + surface->u.tex.level = surf_tmpl->u.tex.level; + + return surface; +} +static void noop_set_vs_sampler_view(struct pipe_context *ctx, unsigned count, + struct pipe_sampler_view **views) +{ +} + +static void noop_set_ps_sampler_view(struct pipe_context *ctx, unsigned count, + struct pipe_sampler_view **views) +{ +} + +static void noop_bind_sampler(struct pipe_context *ctx, unsigned count, void **states) +{ +} + +static void noop_set_clip_state(struct pipe_context *ctx, + const struct pipe_clip_state *state) +{ +} + +static void noop_set_polygon_stipple(struct pipe_context *ctx, + const struct pipe_poly_stipple *state) +{ +} + +static void noop_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) +{ +} + +static void noop_set_scissor_state(struct pipe_context *ctx, + const struct pipe_scissor_state *state) +{ +} + +static void noop_set_stencil_ref(struct pipe_context *ctx, + const struct pipe_stencil_ref *state) +{ +} + +static void noop_set_viewport_state(struct pipe_context *ctx, + const struct pipe_viewport_state *state) +{ +} + +static void noop_set_framebuffer_state(struct pipe_context *ctx, + const struct pipe_framebuffer_state *state) +{ +} + +static void noop_set_constant_buffer(struct pipe_context *ctx, + uint shader, uint index, + struct pipe_resource *buffer) +{ +} + + +static void noop_sampler_view_destroy(struct pipe_context *ctx, + struct pipe_sampler_view *state) +{ + pipe_resource_reference(&state->texture, NULL); + FREE(state); +} + + +static void noop_surface_destroy(struct pipe_context *ctx, + struct pipe_surface *surface) +{ + pipe_resource_reference(&surface->texture, NULL); + FREE(surface); +} + +static void noop_bind_state(struct pipe_context *ctx, void *state) +{ +} + +static void noop_delete_state(struct pipe_context *ctx, void *state) +{ + FREE(state); +} + +static void noop_delete_vertex_element(struct pipe_context *ctx, void *state) +{ + FREE(state); +} + + +static void noop_set_index_buffer(struct pipe_context *ctx, + const struct pipe_index_buffer *ib) +{ +} + +static void noop_set_vertex_buffers(struct pipe_context *ctx, unsigned count, + const struct pipe_vertex_buffer *buffers) +{ +} + +static void *noop_create_vertex_elements(struct pipe_context *ctx, + unsigned count, + const struct pipe_vertex_element *state) +{ + struct pipe_vertex_element *nstate = CALLOC_STRUCT(pipe_vertex_element); + + if (nstate == NULL) { + return NULL; + } + *nstate = *state; + return nstate; +} + +static void *noop_create_shader_state(struct pipe_context *ctx, + const struct pipe_shader_state *state) +{ + struct pipe_shader_state *nstate = CALLOC_STRUCT(pipe_shader_state); + + if (nstate == NULL) { + return NULL; + } + *nstate = *state; + return nstate; +} + +void noop_init_state_functions(struct pipe_context *ctx); + +void noop_init_state_functions(struct pipe_context *ctx) +{ + ctx->create_blend_state = noop_create_blend_state; + ctx->create_depth_stencil_alpha_state = noop_create_dsa_state; + ctx->create_fs_state = noop_create_shader_state; + ctx->create_rasterizer_state = noop_create_rs_state; + ctx->create_sampler_state = noop_create_sampler_state; + ctx->create_sampler_view = noop_create_sampler_view; + ctx->create_surface = noop_create_surface; + ctx->create_vertex_elements_state = noop_create_vertex_elements; + ctx->create_vs_state = noop_create_shader_state; + ctx->bind_blend_state = noop_bind_state; + ctx->bind_depth_stencil_alpha_state = noop_bind_state; + ctx->bind_fragment_sampler_states = noop_bind_sampler; + ctx->bind_fs_state = noop_bind_state; + ctx->bind_rasterizer_state = noop_bind_state; + ctx->bind_vertex_elements_state = noop_bind_state; + ctx->bind_vertex_sampler_states = noop_bind_sampler; + ctx->bind_vs_state = noop_bind_state; + ctx->delete_blend_state = noop_delete_state; + ctx->delete_depth_stencil_alpha_state = noop_delete_state; + ctx->delete_fs_state = noop_delete_state; + ctx->delete_rasterizer_state = noop_delete_state; + ctx->delete_sampler_state = noop_delete_state; + ctx->delete_vertex_elements_state = noop_delete_vertex_element; + ctx->delete_vs_state = noop_delete_state; + ctx->set_blend_color = noop_set_blend_color; + ctx->set_clip_state = noop_set_clip_state; + ctx->set_constant_buffer = noop_set_constant_buffer; + ctx->set_fragment_sampler_views = noop_set_ps_sampler_view; + ctx->set_framebuffer_state = noop_set_framebuffer_state; + ctx->set_polygon_stipple = noop_set_polygon_stipple; + ctx->set_sample_mask = noop_set_sample_mask; + ctx->set_scissor_state = noop_set_scissor_state; + ctx->set_stencil_ref = noop_set_stencil_ref; + ctx->set_vertex_buffers = noop_set_vertex_buffers; + ctx->set_index_buffer = noop_set_index_buffer; + ctx->set_vertex_sampler_views = noop_set_vs_sampler_view; + ctx->set_viewport_state = noop_set_viewport_state; + ctx->sampler_view_destroy = noop_sampler_view_destroy; + ctx->surface_destroy = noop_surface_destroy; + ctx->draw_vbo = noop_draw_vbo; +} diff --git a/src/gallium/drivers/nv50/nv50_buffer.c b/src/gallium/drivers/nv50/nv50_buffer.c index dacfee9799c..45356f9f637 100644 --- a/src/gallium/drivers/nv50/nv50_buffer.c +++ b/src/gallium/drivers/nv50/nv50_buffer.c @@ -136,6 +136,7 @@ nv50_user_buffer_create(struct pipe_screen *pscreen, buffer->base.width0 = bytes; buffer->base.height0 = 1; buffer->base.depth0 = 1; + buffer->base.array_size = 1; buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes); if (!buffer->bo) diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index bf6a577188b..b2b0b72fe26 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -108,6 +108,7 @@ get_tile_depth(uint32_t tile_mode) struct nv50_surface { struct pipe_surface base; + unsigned offset; }; static INLINE struct nv50_surface * diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index dd0e8fd41b1..309b6503ca5 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -276,46 +276,53 @@ nv50_miptree_from_handle(struct pipe_screen *pscreen, */ struct pipe_surface * -nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) +nv50_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { + unsigned level = surf_tmpl->u.tex.level; struct nv50_miptree *mt = nv50_miptree(pt); struct nv50_miptree_level *lvl = &mt->level[level]; - struct pipe_surface *ps; - unsigned img = 0; + struct nv50_surface *ns; + unsigned img = 0, zslice = 0; + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); + + /* XXX can't unify these here? */ if (pt->target == PIPE_TEXTURE_CUBE) - img = face; + img = surf_tmpl->u.tex.first_layer; + else if (pt->target == PIPE_TEXTURE_3D) + zslice = surf_tmpl->u.tex.first_layer; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nv50_surface); + if (!ns) return NULL; - pipe_resource_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = u_minify(pt->width0, level); - ps->height = u_minify(pt->height0, level); - ps->usage = flags; - pipe_reference_init(&ps->reference, 1); - ps->face = face; - ps->level = level; - ps->zslice = zslice; - ps->offset = lvl->image_offset[img]; + pipe_resource_reference(&ns->base.texture, pt); + ns->base.context = pipe; + ns->base.format = pt->format; + ns->base.width = u_minify(pt->width0, level); + ns->base.height = u_minify(pt->height0, level); + ns->base.usage = surf_tmpl->usage; + pipe_reference_init(&ns->base.reference, 1); + ns->base.u.tex.level = level; + ns->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; + ns->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; + ns->offset = lvl->image_offset[img]; if (pt->target == PIPE_TEXTURE_3D) { - unsigned nb_h = util_format_get_nblocksy(pt->format, ps->height); - ps->offset += get_zslice_offset(lvl->tile_mode, zslice, + unsigned nb_h = util_format_get_nblocksy(pt->format, ns->base.height); + ns->offset += get_zslice_offset(lvl->tile_mode, zslice, lvl->pitch, nb_h); } - return ps; + return &ns->base; } void -nv50_miptree_surface_del(struct pipe_surface *ps) +nv50_miptree_surface_del(struct pipe_context *pipe, + struct pipe_surface *ps) { struct nv50_surface *s = nv50_surface(ps); - pipe_resource_reference(&ps->texture, NULL); + pipe_resource_reference(&s->base.texture, NULL); FREE(s); } diff --git a/src/gallium/drivers/nv50/nv50_resource.c b/src/gallium/drivers/nv50/nv50_resource.c index cfdb60418b5..6c0a9696355 100644 --- a/src/gallium/drivers/nv50/nv50_resource.c +++ b/src/gallium/drivers/nv50/nv50_resource.c @@ -15,7 +15,7 @@ static unsigned int nv50_resource_is_referenced(struct pipe_context *pipe, struct pipe_resource *resource, - unsigned face, unsigned level) + unsigned level, int layer) { return nouveau_reference_flags(nv50_resource(resource)->bo); } @@ -51,6 +51,9 @@ nv50_init_resource_functions(struct pipe_context *pcontext) pcontext->transfer_destroy = u_transfer_destroy_vtbl; pcontext->transfer_inline_write = u_transfer_inline_write_vtbl; pcontext->is_resource_referenced = nv50_resource_is_referenced; + + pcontext->create_surface = nv50_miptree_surface_new; + pcontext->surface_destroy = nv50_miptree_surface_del; } void @@ -61,7 +64,4 @@ nv50_screen_init_resource_functions(struct pipe_screen *pscreen) pscreen->resource_get_handle = u_resource_get_handle_vtbl; pscreen->resource_destroy = u_resource_destroy_vtbl; pscreen->user_buffer_create = nv50_user_buffer_create; - - pscreen->get_tex_surface = nv50_miptree_surface_new; - pscreen->tex_surface_destroy = nv50_miptree_surface_del; } diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h index f435a5892e5..4b2a75e11ad 100644 --- a/src/gallium/drivers/nv50/nv50_resource.h +++ b/src/gallium/drivers/nv50/nv50_resource.h @@ -87,12 +87,11 @@ nv50_user_buffer_create(struct pipe_screen *screen, struct pipe_surface * -nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags); +nv50_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl); void -nv50_miptree_surface_del(struct pipe_surface *ps); +nv50_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps); #endif diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 51eab3a0b03..edc3d54d012 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -127,6 +127,10 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 0; case PIPE_CAP_DEPTH_CLAMP: return 1; + case PIPE_CAP_SHADER_STENCIL_EXPORT: + return 0; + case PIPE_CAP_PRIMITIVE_RESTART: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; @@ -176,6 +180,8 @@ nv50_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; default: return 0; } diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index 16c2dab9af6..ae02143e352 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -63,13 +63,13 @@ validate_fb(struct nv50_context *nv50) so_data (so, fb->cbufs[i]->height); so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5); - so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM | + so_reloc (so, bo, ((struct nv50_surface *)fb->cbufs[i])->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0); - so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM | + so_reloc (so, bo, ((struct nv50_surface *)fb->cbufs[i])->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0); so_data (so, nv50_format_table[fb->cbufs[i]->format].rt); so_data (so, nv50_miptree(pt)-> - level[fb->cbufs[i]->level].tile_mode << 4); + level[fb->cbufs[i]->u.tex.level].tile_mode << 4); so_data(so, 0x00000000); so_method(so, tesla, NV50TCL_RT_ARRAY_MODE, 1); @@ -92,13 +92,13 @@ validate_fb(struct nv50_context *nv50) assert(nv50_format_table[fb->zsbuf->format].rt); so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5); - so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM | + so_reloc (so, bo, ((struct nv50_surface *)(fb->zsbuf))->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0); - so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM | + so_reloc (so, bo, ((struct nv50_surface *)(fb->zsbuf))->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0); so_data (so, nv50_format_table[fb->zsbuf->format].rt); so_data (so, nv50_miptree(pt)-> - level[fb->zsbuf->level].tile_mode << 4); + level[fb->zsbuf->u.tex.level].tile_mode << 4); so_data (so, 0x00000000); so_method(so, tesla, NV50TCL_ZETA_ENABLE, 1); diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index f70c138fe1a..ce48022db4e 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -97,23 +97,23 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) OUT_RING (chan, format); OUT_RING (chan, 1); BEGIN_RING(chan, eng2d, mthd + 0x14, 5); - OUT_RING (chan, mt->level[ps->level].pitch); + OUT_RING (chan, mt->level[ps->u.tex.level].pitch); OUT_RING (chan, ps->width); OUT_RING (chan, ps->height); - OUT_RELOCh(chan, bo, ps->offset, flags); - OUT_RELOCl(chan, bo, ps->offset, flags); + OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags); + OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags); } else { BEGIN_RING(chan, eng2d, mthd, 5); OUT_RING (chan, format); OUT_RING (chan, 0); - OUT_RING (chan, mt->level[ps->level].tile_mode << 4); + OUT_RING (chan, mt->level[ps->u.tex.level].tile_mode << 4); OUT_RING (chan, 1); OUT_RING (chan, 0); BEGIN_RING(chan, eng2d, mthd + 0x18, 4); OUT_RING (chan, ps->width); OUT_RING (chan, ps->height); - OUT_RELOCh(chan, bo, ps->offset, flags); - OUT_RELOCl(chan, bo, ps->offset, flags); + OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags); + OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags); } #if 0 @@ -173,30 +173,41 @@ nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst, static void nv50_surface_copy(struct pipe_context *pipe, - struct pipe_resource *dest, struct pipe_subresource subdst, + struct pipe_resource *dest, unsigned dst_level, unsigned destx, unsigned desty, unsigned destz, - struct pipe_resource *src, struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + struct pipe_resource *src, unsigned src_level, + const struct pipe_box *src_box) { struct nv50_context *nv50 = nv50_context(pipe); struct nv50_screen *screen = nv50->screen; - struct pipe_surface *ps_dst, *ps_src; + struct pipe_surface *ps_dst, *ps_src, surf_tmpl; + assert((src->format == dest->format) || (nv50_2d_format_faithful(src->format) && nv50_2d_format_faithful(dest->format))); - - ps_src = nv50_miptree_surface_new(pipe->screen, src, subsrc.face, - subsrc.level, srcz, 0 /* bind flags */); - ps_dst = nv50_miptree_surface_new(pipe->screen, dest, subdst.face, - subdst.level, destz, 0 /* bindflags */); - - nv50_surface_do_copy(screen, ps_dst, destx, desty, ps_src, srcx, - srcy, width, height); - - nv50_miptree_surface_del(ps_src); - nv50_miptree_surface_del(ps_dst); + assert(src_box->depth == 1); + + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = src->format; + surf_tmpl.usage = 0; /* no bind flag - not a surface */ + surf_tmpl.u.tex.level = src_level; + surf_tmpl.u.tex.first_layer = src_box->z; + surf_tmpl.u.tex.last_layer = src_box->z; + /* XXX really need surfaces here? */ + ps_src = nv50_miptree_surface_new(pipe, src, &surf_tmpl); + surf_tmpl.format = dest->format; + surf_tmpl.usage = 0; /* no bind flag - not a surface */ + surf_tmpl.u.tex.level = dst_level; + surf_tmpl.u.tex.first_layer = destz; + surf_tmpl.u.tex.last_layer = destz; + ps_dst = nv50_miptree_surface_new(pipe, dest, &surf_tmpl); + + nv50_surface_do_copy(screen, ps_dst, destx, desty, ps_src, src_box->x, + src_box->y, src_box->width, src_box->height); + + nv50_miptree_surface_del(pipe, ps_src); + nv50_miptree_surface_del(pipe, ps_dst); } static void @@ -225,10 +236,10 @@ nv50_clear_render_target(struct pipe_context *pipe, BEGIN_RING(chan, tesla, NV50TCL_RT_CONTROL, 1); OUT_RING (chan, 1); BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5); - OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCh(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RING (chan, nv50_format_table[dst->format].rt); - OUT_RING (chan, mt->level[dst->level].tile_mode << 4); + OUT_RING (chan, mt->level[dst->u.tex.level].tile_mode << 4); OUT_RING (chan, 0); BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2); OUT_RING (chan, dst->width); @@ -281,10 +292,10 @@ nv50_clear_depth_stencil(struct pipe_context *pipe, return; BEGIN_RING(chan, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5); - OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCh(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RING (chan, nv50_format_table[dst->format].rt); - OUT_RING (chan, mt->level[dst->level].tile_mode << 4); + OUT_RING (chan, mt->level[dst->u.tex.level].tile_mode << 4); OUT_RING (chan, 0); BEGIN_RING(chan, tesla, NV50TCL_ZETA_ENABLE, 1); OUT_RING (chan, 1); diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index 658324ec5be..9243f9edced 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -106,7 +106,7 @@ nv50_tex_construct(struct nv50_sampler_view *view) tic[6] = 0x03000000; - tic[7] = (view->pipe.last_level << 4) | view->pipe.first_level; + tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; return TRUE; } diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index 0cc2f4a837f..bf5af4ddc65 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -126,20 +126,23 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct pipe_transfer * nv50_miptree_transfer_new(struct pipe_context *pcontext, struct pipe_resource *pt, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box) { struct pipe_screen *pscreen = pcontext->screen; struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = nv50_miptree(pt); - struct nv50_miptree_level *lvl = &mt->level[sr.level]; + struct nv50_miptree_level *lvl = &mt->level[level]; struct nv50_transfer *tx; - unsigned nx, ny, image = 0; + unsigned nx, ny, image = 0, boxz = 0; int ret; + /* XXX can't unify these here? */ if (pt->target == PIPE_TEXTURE_CUBE) - image = sr.face; + image = box->z; + else if (pt->target == PIPE_TEXTURE_3D) + boxz = box->z; tx = CALLOC_STRUCT(nv50_transfer); if (!tx) @@ -151,21 +154,21 @@ nv50_miptree_transfer_new(struct pipe_context *pcontext, pipe_resource_reference(&tx->base.resource, pt); - tx->base.sr = sr; + tx->base.level = level; tx->base.usage = usage; tx->base.box = *box; - tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, sr.level)); - tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, sr.level)); + tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, level)); + tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, level)); tx->base.stride = tx->nblocksx * util_format_get_blocksize(pt->format); tx->base.usage = usage; tx->level_pitch = lvl->pitch; - tx->level_width = u_minify(mt->base.base.width0, sr.level); - tx->level_height = u_minify(mt->base.base.height0, sr.level); - tx->level_depth = u_minify(mt->base.base.depth0, sr.level); + tx->level_width = u_minify(mt->base.base.width0, level); + tx->level_height = u_minify(mt->base.base.height0, level); + tx->level_depth = u_minify(mt->base.base.depth0, level); tx->level_offset = lvl->image_offset[image]; tx->level_tiling = lvl->tile_mode; - tx->level_z = box->z; + tx->level_z = boxz; tx->level_x = util_format_get_nblocksx(pt->format, box->x); tx->level_y = util_format_get_nblocksy(pt->format, box->y); ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, @@ -181,7 +184,7 @@ nv50_miptree_transfer_new(struct pipe_context *pcontext, nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset, tx->level_pitch, tx->level_tiling, - box->x, box->y, box->z, + box->x, box->y, boxz, tx->nblocksx, tx->nblocksy, tx->level_depth, tx->bo, 0, diff --git a/src/gallium/drivers/nv50/nv50_transfer.h b/src/gallium/drivers/nv50/nv50_transfer.h index 663503547cb..6699bf546ea 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.h +++ b/src/gallium/drivers/nv50/nv50_transfer.h @@ -8,7 +8,7 @@ struct pipe_transfer * nv50_miptree_transfer_new(struct pipe_context *pcontext, struct pipe_resource *pt, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box); void diff --git a/src/gallium/drivers/nvfx/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c index d6ede5b40a1..951fb202ed4 100644 --- a/src/gallium/drivers/nvfx/nv30_fragtex.c +++ b/src/gallium/drivers/nvfx/nv30_fragtex.c @@ -37,12 +37,12 @@ nv30_sampler_view_init(struct pipe_context *pipe, struct pipe_resource* pt = sv->base.texture; struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format]; unsigned txf; - unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level; + unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.u.tex.first_level; assert(tf->fmt[0] >= 0); txf = sv->u.init_fmt; - txf |= (level != sv->base.last_level ? NV30_3D_TEX_FORMAT_MIPMAP : 0); + txf |= (level != sv->base.u.tex.last_level ? NV30_3D_TEX_FORMAT_MIPMAP : 0); txf |= util_logbase2(u_minify(pt->width0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT; txf |= util_logbase2(u_minify(pt->height0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT; txf |= util_logbase2(u_minify(pt->depth0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_W__SHIFT; @@ -60,8 +60,8 @@ nv30_sampler_view_init(struct pipe_context *pipe, else sv->u.nv30.rect = !!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR); - sv->lod_offset = sv->base.first_level - level; - sv->max_lod_limit = sv->base.last_level - level; + sv->lod_offset = sv->base.u.tex.first_level - level; + sv->max_lod_limit = sv->base.u.tex.last_level - level; } void diff --git a/src/gallium/drivers/nvfx/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c index d4fb73702da..e8ab403f722 100644 --- a/src/gallium/drivers/nvfx/nv40_fragtex.c +++ b/src/gallium/drivers/nvfx/nv40_fragtex.c @@ -46,7 +46,7 @@ nv40_sampler_view_init(struct pipe_context *pipe, struct nvfx_miptree* mt = (struct nvfx_miptree*)pt; struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format]; unsigned txf; - unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level; + unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.u.tex.first_level; assert(tf->fmt[4] >= 0); txf = sv->u.init_fmt; @@ -54,7 +54,7 @@ nv40_sampler_view_init(struct pipe_context *pipe, if(pt->target == PIPE_TEXTURE_CUBE) txf |= ((pt->last_level + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT); else - txf |= (((sv->base.last_level - sv->base.first_level) + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT); + txf |= (((sv->base.u.tex.last_level - sv->base.u.tex.first_level) + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT); if (!mt->linear_pitch) sv->u.nv40.npot_size2 = 0; @@ -68,8 +68,8 @@ nv40_sampler_view_init(struct pipe_context *pipe, sv->u.nv40.npot_size2 |= (u_minify(pt->depth0, level) << NV40_3D_TEX_SIZE1_DEPTH__SHIFT); - sv->lod_offset = (sv->base.first_level - level) * 256; - sv->max_lod_limit = (sv->base.last_level - level) * 256; + sv->lod_offset = (sv->base.u.tex.first_level - level) * 256; + sv->max_lod_limit = (sv->base.u.tex.last_level - level) * 256; } void diff --git a/src/gallium/drivers/nvfx/nvfx_buffer.c b/src/gallium/drivers/nvfx/nvfx_buffer.c index 041099e0e56..b407429731f 100644 --- a/src/gallium/drivers/nvfx/nvfx_buffer.c +++ b/src/gallium/drivers/nvfx/nvfx_buffer.c @@ -64,6 +64,7 @@ nvfx_user_buffer_create(struct pipe_screen *pscreen, buffer->base.base.width0 = bytes; buffer->base.base.height0 = 1; buffer->base.base.depth0 = 1; + buffer->base.base.array_size = 1; buffer->data = ptr; buffer->size = bytes; buffer->bytes_to_draw_until_static = bytes * screen->static_reuse_threshold; diff --git a/src/gallium/drivers/nvfx/nvfx_fragprog.c b/src/gallium/drivers/nvfx/nvfx_fragprog.c index 13e8beed479..1740d72a8ae 100644 --- a/src/gallium/drivers/nvfx/nvfx_fragprog.c +++ b/src/gallium/drivers/nvfx/nvfx_fragprog.c @@ -1189,12 +1189,12 @@ out_err: static inline void nvfx_fp_memcpy(void* dst, const void* src, size_t len) { -#ifndef WORDS_BIGENDIAN +#ifndef PIPE_ARCH_BIG_ENDIAN memcpy(dst, src, len); #else size_t i; for(i = 0; i < len; i += 4) { - uint32_t v = (uint32_t*)((char*)src + i); + uint32_t v = *(uint32_t*)((char*)src + i); *(uint32_t*)((char*)dst + i) = (v >> 16) | (v << 16); } #endif diff --git a/src/gallium/drivers/nvfx/nvfx_fragtex.c b/src/gallium/drivers/nvfx/nvfx_fragtex.c index 1d6b4e24cbc..fd0aff6a1a0 100644 --- a/src/gallium/drivers/nvfx/nvfx_fragtex.c +++ b/src/gallium/drivers/nvfx/nvfx_fragtex.c @@ -122,8 +122,8 @@ nvfx_create_sampler_view(struct pipe_context *pipe, } else { - sv->offset = nvfx_subresource_offset(pt, 0, sv->base.first_level, 0); - sv->npot_size = (u_minify(pt->width0, sv->base.first_level) << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | u_minify(pt->height0, sv->base.first_level); + sv->offset = nvfx_subresource_offset(pt, 0, sv->base.u.tex.first_level, 0); + sv->npot_size = (u_minify(pt->width0, sv->base.u.tex.first_level) << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | u_minify(pt->height0, sv->base.u.tex.first_level); /* apparently, we need to ignore the t coordinate for 1D textures to fix piglit tex1d-2dborder */ if(pt->target == PIPE_TEXTURE_1D) diff --git a/src/gallium/drivers/nvfx/nvfx_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c index 7677fde40cb..8c043b867ba 100644 --- a/src/gallium/drivers/nvfx/nvfx_miptree.c +++ b/src/gallium/drivers/nvfx/nvfx_miptree.c @@ -190,25 +190,27 @@ nvfx_miptree_from_handle(struct pipe_screen *pscreen, const struct pipe_resource } struct pipe_surface * -nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) +nvfx_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { - struct nvfx_miptree* mt = (struct nvfx_miptree*)pt; - struct nvfx_surface *ns; - - ns = (struct nvfx_surface*)util_surfaces_get(&mt->surfaces, sizeof(struct nvfx_surface), pscreen, pt, face, level, zslice, flags); - if(ns->base.base.offset == ~0) { - util_dirty_surface_init(&ns->base); - ns->pitch = nvfx_subresource_pitch(pt, level); - ns->base.base.offset = nvfx_subresource_offset(pt, face, level, zslice); + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; + unsigned level = surf_tmpl->u.tex.level; + struct nvfx_surface *ns = NULL; + + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); + if(util_surfaces_get(&mt->surfaces, sizeof(struct nvfx_surface), pipe, + pt, level, surf_tmpl->u.tex.first_layer, + surf_tmpl->usage, (struct pipe_surface **)&ns)) { + util_dirty_surface_init(&ns->base); + ns->pitch = nvfx_subresource_pitch(pt, level); + ns->offset = nvfx_subresource_offset(pt, surf_tmpl->u.tex.first_layer, level, surf_tmpl->u.tex.first_layer); } return &ns->base.base; } void -nvfx_miptree_surface_del(struct pipe_surface *ps) +nvfx_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps) { struct nvfx_surface* ns = (struct nvfx_surface*)ps; diff --git a/src/gallium/drivers/nvfx/nvfx_resource.c b/src/gallium/drivers/nvfx/nvfx_resource.c index 39ae893f1b3..c60a7bb8b93 100644 --- a/src/gallium/drivers/nvfx/nvfx_resource.c +++ b/src/gallium/drivers/nvfx/nvfx_resource.c @@ -7,7 +7,7 @@ static unsigned int nvfx_resource_is_referenced(struct pipe_context *pipe, struct pipe_resource *pr, - unsigned face, unsigned level) + unsigned level, int layer) { return !!nouveau_reference_flags(nvfx_resource(pr)->bo); } @@ -59,6 +59,9 @@ void nvfx_init_resource_functions(struct pipe_context *pipe) { pipe->is_resource_referenced = nvfx_resource_is_referenced; + + pipe->create_surface = nvfx_miptree_surface_new; + pipe->surface_destroy = nvfx_miptree_surface_del; } void @@ -69,7 +72,4 @@ nvfx_screen_init_resource_functions(struct pipe_screen *pscreen) pscreen->resource_get_handle = nvfx_resource_get_handle; pscreen->resource_destroy = nvfx_resource_destroy; pscreen->user_buffer_create = nvfx_user_buffer_create; - - pscreen->get_tex_surface = nvfx_miptree_surface_new; - pscreen->tex_surface_destroy = nvfx_miptree_surface_del; } diff --git a/src/gallium/drivers/nvfx/nvfx_resource.h b/src/gallium/drivers/nvfx/nvfx_resource.h index 583be4de2ae..070f8979442 100644 --- a/src/gallium/drivers/nvfx/nvfx_resource.h +++ b/src/gallium/drivers/nvfx/nvfx_resource.h @@ -74,6 +74,7 @@ struct nvfx_miptree { struct nvfx_surface { struct util_dirty_surface base; unsigned pitch; + unsigned offset; struct nvfx_miptree* temp; }; @@ -116,12 +117,11 @@ nvfx_miptree_from_handle(struct pipe_screen *pscreen, struct winsys_handle *whandle); void -nvfx_miptree_surface_del(struct pipe_surface *ps); +nvfx_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps); struct pipe_surface * -nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags); +nvfx_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl); /* only for miptrees, don't use for buffers */ diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index 8bf0907a080..92e1d330907 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -37,7 +37,7 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_POINT_SPRITE: return 1; case PIPE_CAP_MAX_RENDER_TARGETS: - return screen->use_nv4x ? 4 : 2; + return screen->use_nv4x ? 4 : 1; case PIPE_CAP_OCCLUSION_QUERY: return 1; case PIPE_CAP_TIMER_QUERY: @@ -123,6 +123,8 @@ nvfx_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, enum case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 0; + case PIPE_SHADER_CAP_SUBROUTINES: + return screen->use_nv4x ? 1 : 0; default: break; } @@ -161,6 +163,8 @@ nvfx_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, enum return 0; case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 1; default: break; } diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c index 30e48c80735..816bb89f2c6 100644 --- a/src/gallium/drivers/nvfx/nvfx_state_fb.c +++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c @@ -7,7 +7,7 @@ nvfx_surface_linear_renderable(struct pipe_surface* surf) { /* TODO: precompute this in nvfx_surface creation */ return (surf->texture->flags & NVFX_RESOURCE_FLAG_LINEAR) - && !(surf->offset & 63) + && !(((struct nvfx_surface*)surf)->offset & 63) && !(((struct nvfx_surface*)surf)->pitch & 63); } @@ -16,8 +16,8 @@ nvfx_surface_swizzled_renderable(struct pipe_framebuffer_state* fb, struct pipe_ { /* TODO: precompute this in nvfx_surface creation */ return !((struct nvfx_miptree*)surf->texture)->linear_pitch - && (surf->texture->target != PIPE_TEXTURE_3D || u_minify(surf->texture->depth0, surf->level) <= 1) - && !(surf->offset & 127) + && (surf->texture->target != PIPE_TEXTURE_3D || u_minify(surf->texture->depth0, surf->u.tex.level) <= 1) + && !(((struct nvfx_surface*)surf)->offset & 127) && (surf->width == fb->width) && (surf->height == fb->height) && !((struct nvfx_surface*)surf)->temp @@ -31,7 +31,7 @@ nvfx_surface_get_render_target(struct pipe_surface* surf, int all_swizzled, stru if(!ns->temp) { target->bo = ((struct nvfx_miptree*)surf->texture)->base.bo; - target->offset = surf->offset; + target->offset = ns->offset; target->pitch = align(ns->pitch, 64); assert(target->pitch); return FALSE; @@ -54,7 +54,7 @@ nvfx_framebuffer_prepare(struct nvfx_context *nvfx) int all_swizzled = 1; if(!nvfx->is_nv4x) - assert(fb->nr_cbufs <= 2); + assert(fb->nr_cbufs <= 1); else assert(fb->nr_cbufs <= 4); @@ -113,7 +113,9 @@ nvfx_framebuffer_validate(struct nvfx_context *nvfx, unsigned prepare_result) nvfx->state.render_temps |= nvfx_surface_get_render_target(fb->cbufs[i], prepare_result, &nvfx->hw_rt[i]) << i; for(; i < 4; ++i) - nvfx->hw_rt[i].bo = 0; + nvfx->hw_rt[i].bo = NULL; + + nvfx->hw_zeta.bo = NULL; if (fb->zsbuf) { nvfx->state.render_temps |= nvfx_surface_get_render_target(fb->zsbuf, prepare_result, &nvfx->hw_zeta) << 7; diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index 70adebc1be5..6fd6c47081b 100644 --- a/src/gallium/drivers/nvfx/nvfx_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -99,17 +99,17 @@ nvfx_region_init_for_surface(struct nv04_region* rgn, struct nvfx_surface* surf, util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(&surf->base.base), &surf->base); } else { rgn->bo = ((struct nvfx_resource*)surf->base.base.texture)->bo; - rgn->offset = surf->base.base.offset; + rgn->offset = surf->offset; if(surf->base.base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR) rgn->pitch = surf->pitch; else { rgn->pitch = 0; - rgn->z = surf->base.base.zslice; + rgn->z = surf->base.base.u.tex.first_layer; rgn->w = surf->base.base.width; rgn->h = surf->base.base.height; - rgn->d = u_minify(surf->base.base.texture->depth0, surf->base.base.level); + rgn->d = u_minify(surf->base.base.texture->depth0, surf->base.base.u.tex.level); } } @@ -119,11 +119,11 @@ nvfx_region_init_for_surface(struct nv04_region* rgn, struct nvfx_surface* surf, } static INLINE void -nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* pt, struct pipe_subresource sub, unsigned x, unsigned y, unsigned z, bool for_write) +nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* pt, unsigned level, unsigned x, unsigned y, unsigned z, bool for_write) { if(pt->target != PIPE_BUFFER) { - struct nvfx_surface* ns = (struct nvfx_surface*)util_surfaces_peek(&((struct nvfx_miptree*)pt)->surfaces, pt, sub.face, sub.level, z); + struct nvfx_surface* ns = (struct nvfx_surface*)util_surfaces_peek(&((struct nvfx_miptree*)pt)->surfaces, pt, level, z); if(ns && util_dirty_surface_is_dirty(&ns->base)) { nvfx_region_init_for_surface(rgn, ns, x, y, for_write); @@ -132,22 +132,22 @@ nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* } rgn->bo = ((struct nvfx_resource*)pt)->bo; - rgn->offset = nvfx_subresource_offset(pt, sub.face, sub.level, z); + rgn->offset = nvfx_subresource_offset(pt, z, level, z); rgn->x = x; rgn->y = y; if(pt->flags & NVFX_RESOURCE_FLAG_LINEAR) { - rgn->pitch = nvfx_subresource_pitch(pt, sub.level); + rgn->pitch = nvfx_subresource_pitch(pt, level); rgn->z = 0; } else { rgn->pitch = 0; rgn->z = z; - rgn->w = u_minify(pt->width0, sub.level); - rgn->h = u_minify(pt->height0, sub.level); - rgn->d = u_minify(pt->depth0, sub.level); + rgn->w = u_minify(pt->width0, level); + rgn->h = u_minify(pt->height0, level); + rgn->d = u_minify(pt->depth0, level); } nvfx_region_set_format(rgn, pt->format); @@ -234,11 +234,10 @@ nvfx_region_clone(struct nv04_2d_context* ctx, struct nv04_region* rgn, unsigned static void nvfx_resource_copy_region(struct pipe_context *pipe, - struct pipe_resource *dstr, struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource *srcr, struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned w, unsigned h) + struct pipe_resource *dstr, unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *srcr, unsigned src_level, + const struct pipe_box *src_box) { static int copy_threshold = -1; struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d; @@ -247,6 +246,8 @@ nvfx_resource_copy_region(struct pipe_context *pipe, int src_on_gpu; boolean small; int ret; + unsigned w = src_box->width; + unsigned h = src_box->height; if(!w || !h) return; @@ -257,8 +258,8 @@ nvfx_resource_copy_region(struct pipe_context *pipe, dst_to_gpu = dstr->usage != PIPE_USAGE_DYNAMIC && dstr->usage != PIPE_USAGE_STAGING; src_on_gpu = nvfx_resource_on_gpu(srcr); - nvfx_region_init_for_subresource(&dst, dstr, subdst, dstx, dsty, dstz, TRUE); - nvfx_region_init_for_subresource(&src, srcr, subsrc, srcx, srcy, srcz, FALSE); + nvfx_region_init_for_subresource(&dst, dstr, dst_level, dstx, dsty, dstz, TRUE); + nvfx_region_init_for_subresource(&src, srcr, src_level, src_box->x, src_box->y, src_box->z, FALSE); w = util_format_get_stride(dstr->format, w) >> dst.bpps; h = util_format_get_nblocksy(dstr->format, h); @@ -279,7 +280,7 @@ nvfx_resource_copy_region(struct pipe_context *pipe, * TODO: perhaps support reinterpreting the formats */ struct blitter_context* blitter = nvfx_get_blitter(pipe, 1); - util_blitter_copy_region(blitter, dstr, subdst, dstx, dsty, dstz, srcr, subsrc, srcx, srcy, srcz, w, h, TRUE); + util_blitter_copy_region(blitter, dstr, dst_level, dstx, dsty, dstz, srcr, src_level, src_box, TRUE); nvfx_put_blitter(pipe, blitter); } else @@ -371,7 +372,7 @@ static void nvfx_surface_copy_temp(struct pipe_context* pipe, struct pipe_surface* surf, int to_temp) { struct nvfx_surface* ns = (struct nvfx_surface*)surf; - struct pipe_subresource tempsr, surfsr; + struct pipe_box box; struct nvfx_context* nvfx = nvfx_context(pipe); struct nvfx_miptree* temp; unsigned use_vertex_buffers; @@ -387,15 +388,20 @@ nvfx_surface_copy_temp(struct pipe_context* pipe, struct pipe_surface* surf, int use_index_buffer = nvfx->use_index_buffer; base_vertex = nvfx->base_vertex; - tempsr.face = 0; - tempsr.level = 0; - surfsr.face = surf->face; - surfsr.level = surf->level; + box.x = box.y = 0; + assert(surf->u.tex.first_layer == surf->u.tex.last_layer); + box.width = surf->width; + box.height = surf->height; + box.depth = 1; - if(to_temp) - nvfx_resource_copy_region(pipe, &temp->base.base, tempsr, 0, 0, 0, surf->texture, surfsr, 0, 0, surf->zslice, surf->width, surf->height); - else - nvfx_resource_copy_region(pipe, surf->texture, surfsr, 0, 0, surf->zslice, &temp->base.base, tempsr, 0, 0, 0, surf->width, surf->height); + if(to_temp) { + box.z = surf->u.tex.first_layer; + nvfx_resource_copy_region(pipe, &temp->base.base, 0, 0, 0, 0, surf->texture, surf->u.tex.level, &box); + } + else { + box.z = 0; + nvfx_resource_copy_region(pipe, surf->texture, surf->u.tex.level, 0, 0, surf->u.tex.first_layer, &temp->base.base, 0, &box); + } /* If this triggers, it probably means we attempted to use the blitter * but failed due to non-renderability of the target. diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c index 7cb47a20f64..2debcb6eb8f 100644 --- a/src/gallium/drivers/nvfx/nvfx_transfer.c +++ b/src/gallium/drivers/nvfx/nvfx_transfer.c @@ -21,10 +21,10 @@ struct nvfx_staging_transfer struct pipe_transfer * nvfx_transfer_new(struct pipe_context *pipe, - struct pipe_resource *pt, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *pt, + unsigned level, + unsigned usage, + const struct pipe_box *box) { if((usage & (PIPE_TRANSFER_UNSYNCHRONIZED | PIPE_TRANSFER_DONTBLOCK)) == PIPE_TRANSFER_DONTBLOCK) { @@ -44,11 +44,11 @@ nvfx_transfer_new(struct pipe_context *pipe, return NULL; pipe_resource_reference(&tx->resource, pt); - tx->sr = sr; + tx->level = level; tx->usage = usage; tx->box = *box; - tx->slice_stride = tx->stride = util_format_get_stride(pt->format, box->width); + tx->layer_stride = tx->stride = util_format_get_stride(pt->format, box->width); tx->data = buffer->data + util_format_get_stride(pt->format, box->x); return tx; @@ -62,20 +62,20 @@ nvfx_transfer_new(struct pipe_context *pipe, if(!tx) return NULL; - util_staging_transfer_init(pipe, pt, sr, usage, box, direct, &tx->base); + util_staging_transfer_init(pipe, pt, level, usage, box, direct, &tx->base); if(direct) { - tx->base.base.stride = nvfx_subresource_pitch(pt, sr.level); - tx->base.base.slice_stride = tx->base.base.stride * u_minify(pt->height0, sr.level); - tx->offset = nvfx_subresource_offset(pt, sr.face, sr.level, box->z) + tx->base.base.stride = nvfx_subresource_pitch(pt, level); + tx->base.base.layer_stride = tx->base.base.stride * u_minify(pt->height0, level); + tx->offset = nvfx_subresource_offset(pt, box->z, level, box->z) + util_format_get_2d_size(pt->format, tx->base.base.stride, box->y) + util_format_get_stride(pt->format, box->x); } else { tx->base.base.stride = nvfx_subresource_pitch(tx->base.staging_resource, 0); - tx->base.base.slice_stride = tx->base.base.stride * tx->base.staging_resource->height0; + tx->base.base.layer_stride = tx->base.base.stride * tx->base.staging_resource->height0; tx->offset = 0; } @@ -187,7 +187,7 @@ nvfx_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx) static void nvfx_transfer_inline_write( struct pipe_context *pipe, struct pipe_resource *pr, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box, const void *data, @@ -196,7 +196,7 @@ static void nvfx_transfer_inline_write( struct pipe_context *pipe, { if(pr->target != PIPE_BUFFER) { - u_default_transfer_inline_write(pipe, pr, sr, usage, box, data, stride, slice_stride); + u_default_transfer_inline_write(pipe, pr, level, usage, box, data, stride, slice_stride); } else { diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.h b/src/gallium/drivers/nvfx/nvfx_transfer.h index 20f20d5b0b8..682f428b793 100644 --- a/src/gallium/drivers/nvfx/nvfx_transfer.h +++ b/src/gallium/drivers/nvfx/nvfx_transfer.h @@ -9,7 +9,7 @@ struct pipe_transfer * nvfx_transfer_new(struct pipe_context *pcontext, struct pipe_resource *pt, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box); diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 0ac4e4c6f12..6e886433bc5 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -186,12 +186,12 @@ static void r300_clear(struct pipe_context* pipe, r300_depth_clear_value(fb->zsbuf->format, depth, stencil); r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG); - if (zstex->zmask_mem[fb->zsbuf->level]) { - r300->zmask_clear.dirty = TRUE; + if (zstex->zmask_mem[fb->zsbuf->u.tex.level]) { + r300_mark_atom_dirty(r300, &r300->zmask_clear); buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; } - if (zstex->hiz_mem[fb->zsbuf->level]) - r300->hiz_clear.dirty = TRUE; + if (zstex->hiz_mem[fb->zsbuf->u.tex.level]) + r300_mark_atom_dirty(r300, &r300->hiz_clear); } /* Enable CBZB clear. */ @@ -230,7 +230,7 @@ static void r300_clear(struct pipe_context* pipe, r300_get_num_cs_end_dwords(r300); /* Reserve CS space. */ - if (dwords > (r300->cs->ndw - r300->cs->cdw)) { + if (dwords > (R300_MAX_CMDBUF_DWORDS - r300->cs->cdw)) { r300->context.flush(&r300->context, 0, NULL); } @@ -259,9 +259,9 @@ static void r300_clear(struct pipe_context* pipe, * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update * looks if zmask/hiz is in use and enables fastfill accordingly. */ if (zstex && - (zstex->zmask_in_use[fb->zsbuf->level] || - zstex->hiz_in_use[fb->zsbuf->level])) { - r300->hyperz_state.dirty = TRUE; + (zstex->zmask_in_use[fb->zsbuf->u.tex.level] || + zstex->hiz_in_use[fb->zsbuf->u.tex.level])) { + r300_mark_atom_dirty(r300, &r300->hyperz_state); } } @@ -300,58 +300,61 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe, /* Flush a depth stencil buffer. */ void r300_flush_depth_stencil(struct pipe_context *pipe, struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned zslice) + unsigned level, + unsigned layer) { struct r300_context *r300 = r300_context(pipe); - struct pipe_surface *dstsurf; + struct pipe_surface *dstsurf, surf_tmpl; struct r300_texture *tex = r300_texture(dst); - if (!tex->zmask_mem[subdst.level]) + if (!tex->zmask_mem[level]) return; - if (!tex->zmask_in_use[subdst.level]) + if (!tex->zmask_in_use[level]) return; - dstsurf = pipe->screen->get_tex_surface(pipe->screen, dst, - subdst.face, subdst.level, zslice, - PIPE_BIND_DEPTH_STENCIL); + surf_tmpl.format = dst->format; + surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; + surf_tmpl.u.tex.level = level; + surf_tmpl.u.tex.first_layer = layer; + surf_tmpl.u.tex.last_layer = layer; + dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl); + r300->z_decomp_rd = TRUE; r300_blitter_begin(r300, R300_CLEAR_SURFACE); util_blitter_flush_depth_stencil(r300->blitter, dstsurf); r300_blitter_end(r300); r300->z_decomp_rd = FALSE; - tex->zmask_in_use[subdst.level] = FALSE; + tex->zmask_in_use[level] = FALSE; } /* Copy a block of pixels from one surface to another using HW. */ static void r300_hw_copy_region(struct pipe_context* pipe, struct pipe_resource *dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { struct r300_context* r300 = r300_context(pipe); r300_blitter_begin(r300, R300_COPY); - util_blitter_copy_region(r300->blitter, dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height, - TRUE); + + /* Do a copy */ + util_blitter_copy_region(r300->blitter, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box, TRUE); r300_blitter_end(r300); } /* Copy a block of pixels from one surface to another. */ static void r300_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { enum pipe_format old_format = dst->format; enum pipe_format new_format = old_format; @@ -384,7 +387,7 @@ static void r300_resource_copy_region(struct pipe_context *pipe, is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; if (is_depth) { - r300_flush_depth_stencil(pipe, src, subsrc, srcz); + r300_flush_depth_stencil(pipe, src, src_level, src_box->z); } if (old_format != new_format) { r300_texture_reinterpret_format(pipe->screen, @@ -393,8 +396,8 @@ static void r300_resource_copy_region(struct pipe_context *pipe, src, new_format); } - r300_hw_copy_region(pipe, dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height); + r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); if (old_format != new_format) { r300_texture_reinterpret_format(pipe->screen, diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 48c24092114..583e981a4d2 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -424,4 +424,5 @@ void r300_parse_chipset(struct r300_capabilities* caps) } caps->is_rv350 = caps->family >= CHIP_FAMILY_RV350; + caps->dxtc_swizzle = caps->is_r400 || caps->is_r500; } diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index e7ca642b4f3..f2035d20092 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -79,6 +79,10 @@ struct r300_capabilities { boolean is_r500; /* Whether or not the second pixel pipe is accessed with the high bit */ boolean high_second_pipe; + /* DXTC texture swizzling. */ + boolean dxtc_swizzle; + /* Index bias (AKA index offset). */ + boolean index_bias_supported; }; /* Enumerations for legibility and telling which card we're running on. */ diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index fb099e2a7d0..67b011a145c 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -44,14 +44,14 @@ static void r300_update_num_contexts(struct r300_screen *r300screen, p_atomic_inc(&r300screen->num_contexts); if (r300screen->num_contexts > 1) - util_mempool_set_thread_safety(&r300screen->pool_buffers, - UTIL_MEMPOOL_MULTITHREADED); + util_slab_set_thread_safety(&r300screen->pool_buffers, + UTIL_SLAB_MULTITHREADED); } else { p_atomic_dec(&r300screen->num_contexts); if (r300screen->num_contexts <= 1) - util_mempool_set_thread_safety(&r300screen->pool_buffers, - UTIL_MEMPOOL_SINGLETHREADED); + util_slab_set_thread_safety(&r300screen->pool_buffers, + UTIL_SLAB_SINGLETHREADED); } } @@ -79,6 +79,9 @@ static void r300_release_referenced_objects(struct r300_context *r300) NULL); } + /* The dummy VBO. */ + pipe_resource_reference(&r300->dummy_vb, NULL); + /* The SWTCL VBO. */ pipe_resource_reference(&r300->vbo, NULL); @@ -97,23 +100,12 @@ static void r300_release_referenced_objects(struct r300_context *r300) static void r300_destroy_context(struct pipe_context* context) { struct r300_context* r300 = r300_context(context); - struct r300_atom *atom; if (r300->blitter) util_blitter_destroy(r300->blitter); if (r300->draw) draw_destroy(r300->draw); - /* Print stats, if enabled. */ - if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) { - fprintf(stderr, "r300: Stats for context %p:\n", r300); - fprintf(stderr, " : Flushes: %" PRIu64 "\n", r300->flush_counter); - foreach(atom, &r300->atom_list) { - fprintf(stderr, " : %s: %" PRIu64 " emits\n", - atom->name, atom->counter); - } - } - if (r300->upload_vb) u_upload_destroy(r300->upload_vb); if (r300->upload_ib) @@ -132,7 +124,7 @@ static void r300_destroy_context(struct pipe_context* context) r300->rws->cs_destroy(r300->cs); /* XXX: No way to tell if this was initialized or not? */ - util_mempool_destroy(&r300->pool_transfers); + util_slab_destroy(&r300->pool_transfers); r300_update_num_contexts(r300->screen, -1); @@ -174,10 +166,16 @@ void r300_flush_cb(void *data) r300->atomname.size = atomsize; \ r300->atomname.emit = r300_emit_##atomname; \ r300->atomname.dirty = FALSE; \ - insert_at_tail(&r300->atom_list, &r300->atomname); \ } while (0) -static void r300_setup_atoms(struct r300_context* r300) +#define R300_ALLOC_ATOM(atomname, statetype) \ +do { \ + r300->atomname.state = CALLOC_STRUCT(statetype); \ + if (r300->atomname.state == NULL) \ + return FALSE; \ +} while (0) + +static boolean r300_setup_atoms(struct r300_context* r300) { boolean is_rv350 = r300->screen->caps.is_rv350; boolean is_r500 = r300->screen->caps.is_r500; @@ -189,9 +187,6 @@ static void r300_setup_atoms(struct r300_context* r300) /* Create the actual atom list. * - * Each atom is examined and emitted in the order it appears here, which - * can affect performance and conformance if not handled with care. - * * Some atoms never change size, others change every emit - those have * the size of 0 here. * @@ -203,7 +198,6 @@ static void r300_setup_atoms(struct r300_context* r300) * - fb_state_pipelined (pipelined regs) * The motivation behind this is to be able to emit a strict * subset of the regs, and to have reasonable register ordering. */ - make_empty_list(&r300->atom_list); /* SC, GB (unpipelined), RB3D (unpipelined), ZB (unpipelined). */ R300_INIT_ATOM(gpu_flush, 9); R300_INIT_ATOM(aa_state, 4); @@ -258,23 +252,23 @@ static void r300_setup_atoms(struct r300_context* r300) } /* Some non-CSO atoms need explicit space to store the state locally. */ - r300->aa_state.state = CALLOC_STRUCT(r300_aa_state); - r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state); - r300->clip_state.state = CALLOC_STRUCT(r300_clip_state); - r300->fb_state.state = CALLOC_STRUCT(pipe_framebuffer_state); - r300->gpu_flush.state = CALLOC_STRUCT(pipe_framebuffer_state); - r300->hyperz_state.state = CALLOC_STRUCT(r300_hyperz_state); - r300->invariant_state.state = CALLOC_STRUCT(r300_invariant_state); - r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); - r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); - r300->textures_state.state = CALLOC_STRUCT(r300_textures_state); - r300->vap_invariant_state.state = CALLOC_STRUCT(r300_vap_invariant_state); - r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); - r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); - r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer); - r300->vs_constants.state = CALLOC_STRUCT(r300_constant_buffer); + R300_ALLOC_ATOM(aa_state, r300_aa_state); + R300_ALLOC_ATOM(blend_color_state, r300_blend_color_state); + R300_ALLOC_ATOM(clip_state, r300_clip_state); + R300_ALLOC_ATOM(hyperz_state, r300_hyperz_state); + R300_ALLOC_ATOM(invariant_state, r300_invariant_state); + R300_ALLOC_ATOM(textures_state, r300_textures_state); + R300_ALLOC_ATOM(vap_invariant_state, r300_vap_invariant_state); + R300_ALLOC_ATOM(viewport_state, r300_viewport_state); + R300_ALLOC_ATOM(ztop_state, r300_ztop_state); + R300_ALLOC_ATOM(fb_state, pipe_framebuffer_state); + R300_ALLOC_ATOM(gpu_flush, pipe_framebuffer_state); + R300_ALLOC_ATOM(scissor_state, pipe_scissor_state); + R300_ALLOC_ATOM(rs_block_state, r300_rs_block); + R300_ALLOC_ATOM(fs_constants, r300_constant_buffer); + R300_ALLOC_ATOM(vs_constants, r300_constant_buffer); if (!r300->screen->caps.has_tcl) { - r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state); + R300_ALLOC_ATOM(vertex_stream_state, r300_vertex_stream_state); } /* Some non-CSO atoms don't use the state pointer. */ @@ -286,11 +280,13 @@ static void r300_setup_atoms(struct r300_context* r300) /* Some states must be marked as dirty here to properly set up * hardware in the first command stream. */ - r300->invariant_state.dirty = TRUE; - r300->pvs_flush.dirty = TRUE; - r300->vap_invariant_state.dirty = TRUE; - r300->texture_cache_inval.dirty = TRUE; - r300->textures_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->invariant_state); + r300_mark_atom_dirty(r300, &r300->pvs_flush); + r300_mark_atom_dirty(r300, &r300->vap_invariant_state); + r300_mark_atom_dirty(r300, &r300->texture_cache_inval); + r300_mark_atom_dirty(r300, &r300->textures_state); + + return TRUE; } /* Not every state tracker calls every driver function before the first draw @@ -316,7 +312,7 @@ static void r300_init_states(struct pipe_context *pipe) pipe->set_scissor_state(pipe, &ss); /* Initialize the clip state. */ - if (r300_context(pipe)->screen->caps.has_tcl) { + if (r300->screen->caps.has_tcl) { pipe->set_clip_state(pipe, &cs); } else { BEGIN_CB(clip->cb, 2); @@ -418,9 +414,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, make_empty_list(&r300->query_list); - util_mempool_create(&r300->pool_transfers, - sizeof(struct pipe_transfer), 64, - UTIL_MEMPOOL_SINGLETHREADED); + util_slab_create(&r300->pool_transfers, + sizeof(struct pipe_transfer), 64, + UTIL_SLAB_SINGLETHREADED); r300->cs = rws->cs_create(rws); if (r300->cs == NULL) @@ -429,6 +425,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300screen->caps.has_tcl) { /* Create a Draw. This is used for SW TCL. */ r300->draw = draw_create(&r300->context); + if (r300->draw == NULL) + goto fail; /* Enable our renderer. */ draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); /* Disable converting points/lines to triangles. */ @@ -436,7 +434,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, draw_wide_point_threshold(r300->draw, 10000000.f); } - r300_setup_atoms(r300); + if (!r300_setup_atoms(r300)) + goto fail; r300_init_blit_functions(r300); r300_init_flush_functions(r300); @@ -488,6 +487,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, rtempl.target = PIPE_TEXTURE_2D; rtempl.format = PIPE_FORMAT_I8_UNORM; rtempl.bind = PIPE_BIND_SAMPLER_VIEW; + rtempl.usage = PIPE_USAGE_IMMUTABLE; rtempl.width0 = 1; rtempl.height0 = 1; rtempl.depth0 = 1; @@ -501,6 +501,19 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, pipe_resource_reference(&tex, NULL); } + { + struct pipe_resource vb = {}; + vb.target = PIPE_BUFFER; + vb.format = PIPE_FORMAT_R8_UNORM; + vb.bind = PIPE_BIND_VERTEX_BUFFER; + vb.usage = PIPE_USAGE_IMMUTABLE; + vb.width0 = sizeof(float) * 16; + vb.height0 = 1; + vb.depth0 = 1; + + r300->dummy_vb = screen->resource_create(screen, &vb); + } + return &r300->context; fail: diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index b59bc002610..39dcde06106 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -43,12 +43,8 @@ struct r300_vertex_shader; struct r300_stencilref_context; struct r300_atom { - /* List pointers. */ - struct r300_atom *prev, *next; /* Name, for debugging. */ const char* name; - /* Stat counter. */ - uint64_t counter; /* Opaque state. */ void* state; /* Emit the state to the context. */ @@ -258,6 +254,8 @@ struct r300_constant_buffer { uint32_t *ptr; /* Remapping table. */ unsigned *remap_table; + /* const buffer base */ + uint32_t buffer_base; }; /* Query object. @@ -282,6 +280,7 @@ struct r300_query { /* The buffer where query results are stored. */ struct r300_winsys_buffer *buffer; + struct r300_winsys_cs_buffer *cs_buffer; /* The size of the buffer. */ unsigned buffer_size; /* The domain of the buffer. */ @@ -313,6 +312,7 @@ struct r300_surface { /* Winsys buffer backing the texture. */ struct r300_winsys_buffer *buffer; + struct r300_winsys_cs_buffer *cs_buffer; enum r300_buffer_domain domain; @@ -396,6 +396,7 @@ struct r300_texture { /* Pipe buffer backing this texture. */ struct r300_winsys_buffer *buffer; + struct r300_winsys_cs_buffer *cs_buffer; /* Registers carrying texture format data. */ /* Only format-independent bits should be filled in. */ @@ -480,6 +481,10 @@ struct r300_context { * dummy texture there. */ struct r300_sampler_view *texkill_sampler; + /* When no vertex buffer is set, this one is used instead to prevent + * hardlocks. */ + struct pipe_resource *dummy_vb; + /* The currently active query. */ struct r300_query *query_current; /* The saved query for blitter operations. */ @@ -488,65 +493,68 @@ struct r300_context { struct r300_query query_list; /* Various CSO state objects. */ - /* Beginning of atom list. */ - struct r300_atom atom_list; + + /* Each atom is emitted in the order it appears here, which can affect + * performance and stability if not handled with care. */ + /* GPU flush. */ + struct r300_atom gpu_flush; /* Anti-aliasing (MSAA) state. */ struct r300_atom aa_state; + /* Framebuffer state. */ + struct r300_atom fb_state; + /* HyperZ state (various SC/ZB bits). */ + struct r300_atom hyperz_state; + /* ZTOP state. */ + struct r300_atom ztop_state; + /* Depth, stencil, and alpha state. */ + struct r300_atom dsa_state; /* Blend state. */ struct r300_atom blend_state; /* Blend color state. */ struct r300_atom blend_color_state; + /* Scissor state. */ + struct r300_atom scissor_state; + /* Invariant state. This must be emitted to get the engine started. */ + struct r300_atom invariant_state; + /* Viewport state. */ + struct r300_atom viewport_state; + /* PVS flush. */ + struct r300_atom pvs_flush; + /* VAP invariant state. */ + struct r300_atom vap_invariant_state; + /* Vertex stream formatting state. */ + struct r300_atom vertex_stream_state; + /* Vertex shader. */ + struct r300_atom vs_state; /* User clip planes. */ struct r300_atom clip_state; - /* Depth, stencil, and alpha state. */ - struct r300_atom dsa_state; + /* RS block state + VAP (vertex shader) output mapping state. */ + struct r300_atom rs_block_state; + /* Rasterizer state. */ + struct r300_atom rs_state; + /* Framebuffer state (pipelined regs). */ + struct r300_atom fb_state_pipelined; /* Fragment shader. */ struct r300_atom fs; /* Fragment shader RC_CONSTANT_STATE variables. */ struct r300_atom fs_rc_constant_state; /* Fragment shader constant buffer. */ struct r300_atom fs_constants; - /* Framebuffer state. */ - struct r300_atom fb_state; - /* Framebuffer state (pipelined regs). */ - struct r300_atom fb_state_pipelined; - /* HyperZ state (various SC/ZB bits). */ - struct r300_atom hyperz_state; - /* Occlusion query. */ - struct r300_atom query_start; - /* Rasterizer state. */ - struct r300_atom rs_state; - /* RS block state + VAP (vertex shader) output mapping state. */ - struct r300_atom rs_block_state; - /* Scissor state. */ - struct r300_atom scissor_state; - /* Textures state. */ - struct r300_atom textures_state; - /* Vertex stream formatting state. */ - struct r300_atom vertex_stream_state; - /* Vertex shader. */ - struct r300_atom vs_state; /* Vertex shader constant buffer. */ struct r300_atom vs_constants; - /* Viewport state. */ - struct r300_atom viewport_state; - /* ZTOP state. */ - struct r300_atom ztop_state; - /* PVS flush. */ - struct r300_atom pvs_flush; - /* VAP invariant state. */ - struct r300_atom vap_invariant_state; /* Texture cache invalidate. */ struct r300_atom texture_cache_inval; - /* GPU flush. */ - struct r300_atom gpu_flush; + /* Textures state. */ + struct r300_atom textures_state; /* HiZ clear */ struct r300_atom hiz_clear; /* zmask clear */ struct r300_atom zmask_clear; + /* Occlusion query. */ + struct r300_atom query_start; - /* Invariant state. This must be emitted to get the engine started. */ - struct r300_atom invariant_state; + /* The pointers to the first and the last atom. */ + struct r300_atom *first_dirty, *last_dirty; /* Vertex buffers for Gallium. */ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; @@ -595,12 +603,29 @@ struct r300_context { struct u_upload_mgr *upload_vb; struct u_upload_mgr *upload_ib; - struct util_mempool pool_transfers; + struct util_slab_mempool pool_transfers; /* Stat counter. */ uint64_t flush_counter; + + /* const tracking for VS */ + int vs_const_base; + + /* AOS (PACKET3_3D_LOAD_VBPNTR) command buffer for the case offset=0. */ + uint32_t aos_cb[(16 * 3 + 1) / 2]; + boolean aos_dirty; + + /* Whether any buffer (FB, textures, VBOs) has been set, but buffers + * haven't been validated yet. */ + boolean validate_buffers; }; +#define foreach_atom(r300, atom) \ + for (atom = &r300->gpu_flush; atom != (&r300->query_start)+1; atom++) + +#define foreach_dirty_atom(r300, atom) \ + for (atom = r300->first_dirty; atom != r300->last_dirty; atom++) + /* Convenience cast wrappers. */ static INLINE struct r300_query* r300_query(struct pipe_query* q) { @@ -645,8 +670,8 @@ void r300_init_resource_functions(struct r300_context* r300); /* r300_blit.c */ void r300_flush_depth_stencil(struct pipe_context *pipe, struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned zslice); + unsigned level, + unsigned layer); /* r300_query.c */ void r300_resume_query(struct r300_context *r300, @@ -666,7 +691,6 @@ void r300_plug_in_stencil_ref_fallback(struct r300_context *r300); /* r300_render.c */ void r300_draw_flush_vbuf(struct r300_context *r300); -boolean r500_index_bias_supported(struct r300_context *r300); void r500_emit_index_bias(struct r300_context *r300, int index_bias); /* r300_state.c */ @@ -680,6 +704,22 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, enum r300_fb_state_change change); void r300_mark_fs_code_dirty(struct r300_context *r300); +static INLINE void r300_mark_atom_dirty(struct r300_context *r300, + struct r300_atom *atom) +{ + atom->dirty = TRUE; + + if (!r300->first_dirty) { + r300->first_dirty = atom; + r300->last_dirty = atom+1; + } else { + if (atom < r300->first_dirty) + r300->first_dirty = atom; + if (atom+1 > r300->last_dirty) + r300->last_dirty = atom+1; + } +} + /* r300_debug.c */ void r500_dump_rs_block(struct r300_rs_block *rs); diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index c194d6a1b08..67fb0096a8c 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -51,7 +51,7 @@ int cs_count = 0; (void) cs_count; (void) cs_winsys; #define BEGIN_CS(size) do { \ - assert(size <= (cs_copy->ndw - cs_copy->cdw)); \ + assert(size <= (R300_MAX_CMDBUF_DWORDS - cs_copy->cdw)); \ CS_DEBUG(cs_count = size;) \ } while (0) @@ -72,7 +72,7 @@ */ #define OUT_CS(value) do { \ - cs_copy->ptr[cs_copy->cdw++] = (value); \ + cs_copy->buf[cs_copy->cdw++] = (value); \ CS_DEBUG(cs_count--;) \ } while (0) @@ -96,7 +96,7 @@ OUT_CS(CP_PACKET3(op, count)) #define OUT_CS_TABLE(values, count) do { \ - memcpy(cs_copy->ptr + cs_copy->cdw, values, count * 4); \ + memcpy(cs_copy->buf + cs_copy->cdw, values, count * 4); \ cs_copy->cdw += count; \ CS_DEBUG(cs_count -= count;) \ } while (0) @@ -115,17 +115,17 @@ #define OUT_CS_BUF_RELOC(bo, offset, rd, wd) do { \ assert(bo); \ - OUT_CS_RELOC(r300_buffer(bo)->buf, offset, rd, wd); \ + OUT_CS_RELOC(r300_buffer(bo)->cs_buf, offset, rd, wd); \ } while (0) #define OUT_CS_TEX_RELOC(tex, offset, rd, wd) do { \ assert(tex); \ - OUT_CS_RELOC(tex->buffer, offset, rd, wd); \ + OUT_CS_RELOC(tex->cs_buffer, offset, rd, wd); \ } while (0) #define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd) do { \ assert(bo); \ - cs_winsys->cs_write_reloc(cs_copy, r300_buffer(bo)->buf, rd, wd); \ + cs_winsys->cs_write_reloc(cs_copy, r300_buffer(bo)->cs_buf, rd, wd); \ CS_DEBUG(cs_count -= 2;) \ } while (0) @@ -136,7 +136,7 @@ #define WRITE_CS_TABLE(values, count) do { \ CS_DEBUG(assert(cs_count == 0);) \ - memcpy(cs_copy->ptr + cs_copy->cdw, (values), (count) * 4); \ + memcpy(cs_copy->buf + cs_copy->cdw, (values), (count) * 4); \ cs_copy->cdw += (count); \ } while (0) diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index f78fe34790c..52031dd97b5 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -40,7 +40,6 @@ static const struct debug_named_value debug_options[] = { { "rs", DBG_RS, "Log rasterizer" }, { "fb", DBG_FB, "Log framebuffer" }, { "cbzb", DBG_CBZB, "Log fast color clear info" }, - { "stats", DBG_STATS, "Log emission statistics" }, { "hyperz", DBG_HYPERZ, "Log HyperZ info" }, { "scissor", DBG_SCISSOR, "Log scissor info" }, { "fakeocc", DBG_FAKE_OCC, "Use fake occlusion queries" }, diff --git a/src/gallium/drivers/r300/r300_defines.h b/src/gallium/drivers/r300/r300_defines.h index 896aeef395d..2d111f9158d 100644 --- a/src/gallium/drivers/r300/r300_defines.h +++ b/src/gallium/drivers/r300/r300_defines.h @@ -43,8 +43,8 @@ enum r300_buffer_tiling { }; enum r300_buffer_domain { /* bitfield */ - R300_DOMAIN_GTT = 1, - R300_DOMAIN_VRAM = 2 + R300_DOMAIN_GTT = 2, + R300_DOMAIN_VRAM = 4 }; #endif diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index c187f115da4..04a5bd92d12 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -29,6 +29,7 @@ #include "util/u_simple_list.h" #include "r300_context.h" +#include "r300_cb.h" #include "r300_cs.h" #include "r300_emit.h" #include "r300_fs.h" @@ -83,16 +84,20 @@ void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state) } } -static const float * get_rc_constant_state( +static void get_rc_constant_state( + float vec[4], struct r300_context * r300, struct rc_constant * constant) { struct r300_textures_state* texstate = r300->textures_state.state; - static float vec[4] = { 0.0, 0.0, 0.0, 1.0 }; struct r300_texture *tex; assert(constant->Type == RC_CONSTANT_STATE); + /* vec should either be (0, 0, 0, 1), which should be a relatively safe + * RGBA or STRQ value, or it could be one of the RC_CONSTANT_STATE + * state factors. */ + switch (constant->u.State[0]) { /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ @@ -100,6 +105,8 @@ static const float * get_rc_constant_state( tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); vec[0] = 1.0 / tex->desc.width0; vec[1] = 1.0 / tex->desc.height0; + vec[2] = 0; + vec[3] = 1; break; case RC_STATE_R300_TEXSCALE_FACTOR: @@ -108,29 +115,31 @@ static const float * get_rc_constant_state( vec[0] = tex->desc.b.b.width0 / (tex->desc.width0 + 0.001f); vec[1] = tex->desc.b.b.height0 / (tex->desc.height0 + 0.001f); vec[2] = tex->desc.b.b.depth0 / (tex->desc.depth0 + 0.001f); + vec[3] = 1; break; case RC_STATE_R300_VIEWPORT_SCALE: vec[0] = r300->viewport.scale[0]; vec[1] = r300->viewport.scale[1]; vec[2] = r300->viewport.scale[2]; + vec[3] = 1; break; case RC_STATE_R300_VIEWPORT_OFFSET: vec[0] = r300->viewport.translate[0]; vec[1] = r300->viewport.translate[1]; vec[2] = r300->viewport.translate[2]; + vec[3] = 1; break; default: fprintf(stderr, "r300: Implementation error: " "Unknown RC_CONSTANT type %d\n", constant->u.State[0]); + vec[0] = 0; + vec[1] = 0; + vec[2] = 0; + vec[3] = 1; } - - /* This should either be (0, 0, 0, 1), which should be a relatively safe - * RGBA or STRQ value, or it could be one of the RC_CONSTANT_STATE - * state factors. */ - return vec; } /* Convert a normal single-precision float into the 7.16 format @@ -220,8 +229,9 @@ void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo BEGIN_CS(size); for(i = first; i < end; ++i) { if (constants->Constants[i].Type == RC_CONSTANT_STATE) { - const float *data = - get_rc_constant_state(r300, &constants->Constants[i]); + float data[4]; + + get_rc_constant_state(data, r300, &constants->Constants[i]); OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); for (j = 0; j < 4; j++) @@ -279,8 +289,9 @@ void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo BEGIN_CS(size); for(i = first; i < end; ++i) { if (constants->Constants[i].Type == RC_CONSTANT_STATE) { - const float *data = - get_rc_constant_state(r300, &constants->Constants[i]); + float data[4]; + + get_rc_constant_state(data, r300, &constants->Constants[i]); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST | @@ -343,10 +354,10 @@ void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state) if (aa->dest) { OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1); - OUT_CS_RELOC(aa->dest->buffer, aa->dest->offset, 0, aa->dest->domain); + OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->offset, 0, aa->dest->domain); OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1); - OUT_CS_RELOC(aa->dest->buffer, aa->dest->pitch, 0, aa->dest->domain); + OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->pitch, 0, aa->dest->domain); } OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl); @@ -377,10 +388,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) surf = r300_surface(fb->cbufs[i]); OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); - OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain); + OUT_CS_RELOC(surf->cs_buffer, surf->offset, 0, surf->domain); OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); - OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain); + OUT_CS_RELOC(surf->cs_buffer, surf->pitch, 0, surf->domain); } /* Set up the ZB part of the CBZB clear. */ @@ -390,10 +401,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format); OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(surf->buffer, surf->cbzb_midpoint_offset, 0, surf->domain); + OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_midpoint_offset, 0, surf->domain); OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(surf->buffer, surf->cbzb_pitch, 0, surf->domain); + OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_pitch, 0, surf->domain); DBG(r300, DBG_CBZB, "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format, @@ -406,15 +417,15 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_FORMAT, surf->format); OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain); + OUT_CS_RELOC(surf->cs_buffer, surf->offset, 0, surf->domain); OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain); + OUT_CS_RELOC(surf->cs_buffer, surf->pitch, 0, surf->domain); if (can_hyperz) { uint32_t surf_pitch; struct r300_texture *tex; - int level = surf->base.level; + int level = surf->base.u.tex.level; tex = r300_texture(surf->base.texture); surf_pitch = surf->pitch & R300_DEPTHPITCH_MASK; @@ -549,7 +560,7 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; - struct r300_winsys_buffer *buf = r300->query_current->buffer; + struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); assert(caps->num_frag_pipes); @@ -605,7 +616,7 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, static void rv530_emit_query_end_single_z(struct r300_context *r300, struct r300_query *query) { - struct r300_winsys_buffer *buf = r300->query_current->buffer; + struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); BEGIN_CS(8); @@ -619,7 +630,7 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300, static void rv530_emit_query_end_double_z(struct r300_context *r300, struct r300_query *query) { - struct r300_winsys_buffer *buf = r300->query_current->buffer; + struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); BEGIN_CS(14); @@ -796,39 +807,83 @@ void r300_emit_textures_state(struct r300_context *r300, END_CS; } -void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) +static void r300_update_aos_cb(struct r300_context *r300, unsigned packet_size) { struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; - struct r300_buffer *buf; - int i; unsigned *hw_format_size = r300->velems->hw_format_size; unsigned size1, size2, aos_count = r300->velems->count; - unsigned packet_size = (aos_count * 3 + 1) / 2; - CS_LOCALS(r300); - - BEGIN_CS(2 + packet_size + aos_count * 2); - OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); - OUT_CS(aos_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); + int i; + CB_LOCALS; + BEGIN_CB(r300->aos_cb, packet_size); for (i = 0; i < aos_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; size1 = hw_format_size[i]; size2 = hw_format_size[i+1]; - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | + OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); - OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); + OUT_CB(vb1->buffer_offset + velem[i].src_offset); + OUT_CB(vb2->buffer_offset + velem[i+1].src_offset); } if (aos_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; size1 = hw_format_size[i]; - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); + OUT_CB(vb1->buffer_offset + velem[i].src_offset); + } + END_CB; + + r300->aos_dirty = FALSE; +} + +void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) +{ + struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; + struct pipe_vertex_element *velem = r300->velems->velem; + struct r300_buffer *buf; + int i; + unsigned aos_count = r300->velems->count; + unsigned packet_size = (aos_count * 3 + 1) / 2; + CS_LOCALS(r300); + + BEGIN_CS(2 + packet_size + aos_count * 2); + OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); + OUT_CS(aos_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); + + if (!offset) { + if (r300->aos_dirty) { + r300_update_aos_cb(r300, packet_size); + } + OUT_CS_TABLE(r300->aos_cb, packet_size); + } else { + struct pipe_vertex_buffer *vb1, *vb2; + unsigned *hw_format_size = r300->velems->hw_format_size; + unsigned size1, size2; + + for (i = 0; i < aos_count - 1; i += 2) { + vb1 = &vbuf[velem[i].vertex_buffer_index]; + vb2 = &vbuf[velem[i+1].vertex_buffer_index]; + size1 = hw_format_size[i]; + size2 = hw_format_size[i+1]; + + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | + R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); + } + + if (aos_count & 1) { + vb1 = &vbuf[velem[i].vertex_buffer_index]; + size1 = hw_format_size[i]; + + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + } } for (i = 0; i < aos_count; i++) { @@ -914,7 +969,6 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) struct r300_vertex_program_code* code = &vs->code; struct r300_screen* r300screen = r300->screen; unsigned instruction_count = code->length / 4; - unsigned i; unsigned vtx_mem_size = r300screen->caps.is_r500 ? 128 : 72; unsigned input_count = MAX2(util_bitcount(code->InputsRead), 1); @@ -925,10 +979,6 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) vtx_mem_size / output_count, 10); unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 5); - unsigned imm_first = vs->externals_count; - unsigned imm_end = vs->code.constants.Count; - unsigned imm_count = vs->immediates_count; - CS_LOCALS(r300); BEGIN_CS(size); @@ -937,12 +987,10 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) * R300_VAP_PVS_CONST_CNTL * R300_VAP_PVS_CODE_CNTL_1 * See the r5xx docs for instructions on how to use these. */ - OUT_CS_REG_SEQ(R300_VAP_PVS_CODE_CNTL_0, 3); - OUT_CS(R300_PVS_FIRST_INST(0) | - R300_PVS_XYZW_VALID_INST(instruction_count - 1) | - R300_PVS_LAST_INST(instruction_count - 1)); - OUT_CS(R300_PVS_MAX_CONST_ADDR(code->constants.Count - 1)); - OUT_CS(instruction_count - 1); + OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_0, R300_PVS_FIRST_INST(0) | + R300_PVS_XYZW_VALID_INST(instruction_count - 1) | + R300_PVS_LAST_INST(instruction_count - 1)); + OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_1, instruction_count - 1); OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length); @@ -954,19 +1002,6 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) R300_PVS_VF_MAX_VTX_NUM(12) | (r300screen->caps.is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0)); - /* Emit immediates. */ - if (imm_count) { - OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, - (r300->screen->caps.is_r500 ? - R500_PVS_CONST_START : R300_PVS_CONST_START) + - imm_first); - OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, imm_count * 4); - for (i = imm_first; i < imm_end; i++) { - const float *data = vs->code.constants.Constants[i].u.Immediate; - OUT_CS_TABLE(data, 4); - } - } - /* Emit flow control instructions. */ if (code->num_fc_ops) { @@ -991,24 +1026,43 @@ void r300_emit_vs_constants(struct r300_context* r300, unsigned count = ((struct r300_vertex_shader*)r300->vs_state.state)->externals_count; struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; + struct r300_vertex_shader *vs = (struct r300_vertex_shader*)r300->vs_state.state; unsigned i; + int imm_first = vs->externals_count; + int imm_end = vs->code.constants.Count; + int imm_count = vs->immediates_count; CS_LOCALS(r300); - if (!count) - return; - BEGIN_CS(size); - OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, - (r300->screen->caps.is_r500 ? - R500_PVS_CONST_START : R300_PVS_CONST_START)); - OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, count * 4); - if (buf->remap_table){ - for (i = 0; i < count; i++) { - uint32_t *data = &buf->ptr[buf->remap_table[i]*4]; + OUT_CS_REG(R300_VAP_PVS_CONST_CNTL, + R300_PVS_CONST_BASE_OFFSET(buf->buffer_base) | + R300_PVS_MAX_CONST_ADDR(MAX2(imm_end - 1, 0))); + if (vs->externals_count) { + OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, + (r300->screen->caps.is_r500 ? + R500_PVS_CONST_START : R300_PVS_CONST_START) + buf->buffer_base); + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, count * 4); + if (buf->remap_table){ + for (i = 0; i < count; i++) { + uint32_t *data = &buf->ptr[buf->remap_table[i]*4]; + OUT_CS_TABLE(data, 4); + } + } else { + OUT_CS_TABLE(buf->ptr, count * 4); + } + } + + /* Emit immediates. */ + if (imm_count) { + OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, + (r300->screen->caps.is_r500 ? + R500_PVS_CONST_START : R300_PVS_CONST_START) + + buf->buffer_base + imm_first); + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, imm_count * 4); + for (i = imm_first; i < imm_end; i++) { + const float *data = vs->code.constants.Constants[i].u.Immediate; OUT_CS_TABLE(data, 4); } - } else { - OUT_CS_TABLE(buf->ptr, count * 4); } END_CS; } @@ -1063,8 +1117,8 @@ void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state) tex = r300_texture(fb->zsbuf->texture); - offset = tex->hiz_mem[fb->zsbuf->level]->ofs; - stride = tex->desc.stride_in_pixels[fb->zsbuf->level]; + offset = tex->hiz_mem[fb->zsbuf->u.tex.level]->ofs; + stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level]; /* convert from pixels to 4x4 blocks */ stride = ALIGN_DIVUP(stride, 4); @@ -1086,7 +1140,7 @@ void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state) z->current_func = -1; /* Mark the current zbuffer's hiz ram as in use. */ - tex->hiz_in_use[fb->zsbuf->level] = TRUE; + tex->hiz_in_use[fb->zsbuf->u.tex.level] = TRUE; } void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state) @@ -1100,9 +1154,9 @@ void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state int mult, offset_shift; tex = r300_texture(fb->zsbuf->texture); - stride = tex->desc.stride_in_pixels[fb->zsbuf->level]; + stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level]; - offset = tex->zmask_mem[fb->zsbuf->level]->ofs; + offset = tex->zmask_mem[fb->zsbuf->u.tex.level]->ofs; if (r300->z_compression == RV350_Z_COMPRESS_88) mult = 8; @@ -1128,7 +1182,7 @@ void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state } /* Mark the current zbuffer's zmask as in use. */ - tex->zmask_in_use[fb->zsbuf->level] = TRUE; + tex->zmask_in_use[fb->zsbuf->u.tex.level] = TRUE; } void r300_emit_ztop_state(struct r300_context* r300, @@ -1165,12 +1219,6 @@ boolean r300_emit_buffer_validate(struct r300_context *r300, struct pipe_resource *pbuf; unsigned i; - /* upload buffers first */ - if (r300->screen->caps.has_tcl && r300->any_user_vbs) { - r300_upload_user_buffers(r300); - r300->any_user_vbs = false; - } - /* Clean out BOs. */ r300->rws->cs_reset_buffers(r300->cs); @@ -1178,14 +1226,14 @@ boolean r300_emit_buffer_validate(struct r300_context *r300, for (i = 0; i < fb->nr_cbufs; i++) { tex = r300_texture(fb->cbufs[i]->texture); assert(tex && tex->buffer && "cbuf is marked, but NULL!"); - r300->rws->cs_add_buffer(r300->cs, tex->buffer, 0, + r300->rws->cs_add_buffer(r300->cs, tex->cs_buffer, 0, r300_surface(fb->cbufs[i])->domain); } /* ...depth buffer... */ if (fb->zsbuf) { tex = r300_texture(fb->zsbuf->texture); assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); - r300->rws->cs_add_buffer(r300->cs, tex->buffer, 0, + r300->rws->cs_add_buffer(r300->cs, tex->cs_buffer, 0, r300_surface(fb->zsbuf)->domain); } /* ...textures... */ @@ -1195,28 +1243,30 @@ boolean r300_emit_buffer_validate(struct r300_context *r300, } tex = r300_texture(texstate->sampler_views[i]->base.texture); - r300->rws->cs_add_buffer(r300->cs, tex->buffer, tex->domain, 0); + r300->rws->cs_add_buffer(r300->cs, tex->cs_buffer, tex->domain, 0); } /* ...occlusion query buffer... */ if (r300->query_current) - r300->rws->cs_add_buffer(r300->cs, r300->query_current->buffer, + r300->rws->cs_add_buffer(r300->cs, r300->query_current->cs_buffer, 0, r300->query_current->domain); /* ...vertex buffer for SWTCL path... */ if (r300->vbo) - r300->rws->cs_add_buffer(r300->cs, r300_buffer(r300->vbo)->buf, + r300->rws->cs_add_buffer(r300->cs, r300_buffer(r300->vbo)->cs_buf, r300_buffer(r300->vbo)->domain, 0); /* ...vertex buffers for HWTCL path... */ if (do_validate_vertex_buffers) { for (i = 0; i < r300->velems->count; i++) { pbuf = vbuf[velem[i].vertex_buffer_index].buffer; + if (!pbuf) + continue; - r300->rws->cs_add_buffer(r300->cs, r300_buffer(pbuf)->buf, + r300->rws->cs_add_buffer(r300->cs, r300_buffer(pbuf)->cs_buf, r300_buffer(pbuf)->domain, 0); } } /* ...and index buffer for HWTCL path. */ if (index_buffer) - r300->rws->cs_add_buffer(r300->cs, r300_buffer(index_buffer)->buf, + r300->rws->cs_add_buffer(r300->cs, r300_buffer(index_buffer)->cs_buf, r300_buffer(index_buffer)->domain, 0); if (!r300->rws->cs_validate(r300->cs)) { @@ -1231,7 +1281,7 @@ unsigned r300_get_num_dirty_dwords(struct r300_context *r300) struct r300_atom* atom; unsigned dwords = 0; - foreach(atom, &r300->atom_list) { + foreach_dirty_atom(r300, atom) { if (atom->dirty) { dwords += atom->size; } @@ -1250,7 +1300,7 @@ unsigned r300_get_num_cs_end_dwords(struct r300_context *r300) /* Emitted in flush. */ dwords += 26; /* emit_query_end */ dwords += r300->hyperz_state.size + 2; /* emit_hyperz_end + zcache flush */ - if (r500_index_bias_supported(r300)) + if (r300->screen->caps.index_bias_supported) dwords += 2; return dwords; @@ -1259,17 +1309,16 @@ unsigned r300_get_num_cs_end_dwords(struct r300_context *r300) /* Emit all dirty state. */ void r300_emit_dirty_state(struct r300_context* r300) { - struct r300_atom* atom; + struct r300_atom *atom; - foreach(atom, &r300->atom_list) { + foreach_dirty_atom(r300, atom) { if (atom->dirty) { atom->emit(r300, atom->size, atom->state); - if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) { - atom->counter++; - } atom->dirty = FALSE; } } + r300->first_dirty = NULL; + r300->last_dirty = NULL; r300->dirty_hw++; } diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 1afd27f0938..451fe525b40 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -49,7 +49,7 @@ static void r300_flush(struct pipe_context* pipe, if (r300->dirty_hw) { r300_emit_hyperz_end(r300); r300_emit_query_end(r300); - if (r500_index_bias_supported(r300)) + if (r300->screen->caps.index_bias_supported) r500_emit_index_bias(r300, 0); r300->flush_counter++; @@ -57,9 +57,9 @@ static void r300_flush(struct pipe_context* pipe, r300->dirty_hw = 0; /* New kitchen sink, baby. */ - foreach(atom, &r300->atom_list) { + foreach_atom(r300, atom) { if (atom->state || atom->allow_null_state) { - atom->dirty = TRUE; + r300_mark_atom_dirty(r300, atom); } } @@ -68,6 +68,8 @@ static void r300_flush(struct pipe_context* pipe, r300->vs_state.dirty = FALSE; r300->vs_constants.dirty = FALSE; } + + r300->validate_buffers = TRUE; } /* reset flushed query */ diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index c91532eb7b3..2936c3486e2 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -390,7 +390,6 @@ static void r300_translate_fragment_shader( compiler.Base.max_temp_regs = compiler.Base.is_r500 ? 128 : 32; compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32; compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64; - compiler.Base.remove_unused_constants = TRUE; compiler.AllocateHwInputs = &allocate_hardware_inputs; compiler.UserData = &shader->inputs; @@ -408,6 +407,11 @@ static void r300_translate_fragment_shader( r300_tgsi_to_rc(&ttr, tokens); + if (!r300->screen->caps.is_r500 || + compiler.Base.Program.Constants.Count > 200) { + compiler.Base.remove_unused_constants = TRUE; + } + /** * Transform the program to support WPOS. * diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c index 79f7f8abe9b..c22e307c679 100644 --- a/src/gallium/drivers/r300/r300_hyperz.c +++ b/src/gallium/drivers/r300/r300_hyperz.c @@ -158,8 +158,8 @@ static void r300_update_hyperz(struct r300_context* r300) if (!r300->rws->get_value(r300->rws, R300_CAN_HYPERZ)) return; - zmask_in_use = zstex->zmask_in_use[fb->zsbuf->level]; - hiz_in_use = zstex->hiz_in_use[fb->zsbuf->level]; + zmask_in_use = zstex->zmask_in_use[fb->zsbuf->u.tex.level]; + hiz_in_use = zstex->hiz_in_use[fb->zsbuf->u.tex.level]; /* Z fastfill. */ if (zmask_in_use) { @@ -282,7 +282,7 @@ static void r300_update_ztop(struct r300_context* r300) ztop_state->z_buffer_top = R300_ZTOP_ENABLE; } if (ztop_state->z_buffer_top != old_ztop) - r300->ztop_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->ztop_state); } #define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y)) @@ -333,7 +333,7 @@ void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf) { struct r300_texture *tex; uint32_t zsize, ndw; - int level = surf->base.level; + int level = surf->base.u.tex.level; tex = r300_texture(surf->base.texture); @@ -352,7 +352,7 @@ void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf { int bsize = 256; uint32_t zsize, ndw; - int level = surf->base.level; + int level = surf->base.u.tex.level; struct r300_texture *tex; tex = r300_texture(surf->base.texture); diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 5f34fcb2744..6223e043210 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -60,6 +60,7 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, q->buffer = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096, PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM, q->domain); + q->cs_buffer = r300->rws->buffer_get_cs_handle(r300->rws, q->buffer); return (struct pipe_query*)q; } @@ -79,7 +80,7 @@ void r300_resume_query(struct r300_context *r300, struct r300_query *query) { r300->query_current = query; - r300->query_start.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->query_start); } static void r300_begin_query(struct pipe_context* pipe, diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 6bea783f697..613186e8156 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -427,7 +427,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_PVS_CONST_START 512 # define R500_PVS_CONST_START 1024 # define R300_MAX_PVS_CONST_VECS 256 -# define R500_MAX_PVS_CONST_VECS 1024 +# define R500_MAX_PVS_CONST_VECS 256 # define R300_PVS_UCP_START 1024 # define R500_PVS_UCP_START 1536 # define R300_POINT_VPORT_SCALE_OFFSET 1030 @@ -553,6 +553,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* Addresses are relative to the vertex program parameters area. */ #define R300_VAP_PVS_CONST_CNTL 0x22D4 # define R300_PVS_CONST_BASE_OFFSET_SHIFT 0 +# define R300_PVS_CONST_BASE_OFFSET(x) (x) # define R300_PVS_MAX_CONST_ADDR_SHIFT 16 # define R300_PVS_MAX_CONST_ADDR(x) ((x) << 16) #define R300_VAP_PVS_CODE_CNTL_1 0x22D8 @@ -1520,11 +1521,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_TRI_PERF_3_8 (3<<15) # define R300_ANISO_THRESHOLD_MASK (7<<17) +# define R400_DXTC_SWIZZLE_ENABLE (1<<21) # define R500_MACRO_SWITCH (1<<22) # define R500_TX_MAX_ANISO(x) ((x) << 23) # define R500_TX_MAX_ANISO_MASK (63 << 23) # define R500_TX_ANISO_HIGH_QUALITY (1 << 30) - # define R500_BORDER_FIX (1<<31) #define R300_TX_FORMAT0_0 0x4480 diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 2f00c878f5b..1d26eb9f918 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -118,12 +118,6 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, return color_control; } -boolean r500_index_bias_supported(struct r300_context *r300) -{ - return r300->screen->caps.is_r500 && - r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); -} - void r500_emit_index_bias(struct r300_context *r300, int index_bias) { CS_LOCALS(r300); @@ -193,13 +187,12 @@ static boolean r300_reserve_cs_dwords(struct r300_context *r300, boolean first_draw = flags & PREP_FIRST_DRAW; boolean emit_aos = flags & PREP_EMIT_AOS; boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL; - boolean hw_index_bias = r500_index_bias_supported(r300); /* Add dirty state, index offset, and AOS. */ if (first_draw) { cs_dwords += r300_get_num_dirty_dwords(r300); - if (hw_index_bias) + if (r300->screen->caps.index_bias_supported) cs_dwords += 2; /* emit_index_offset */ if (emit_aos) @@ -212,7 +205,7 @@ static boolean r300_reserve_cs_dwords(struct r300_context *r300, cs_dwords += r300_get_num_cs_end_dwords(r300); /* Reserve requested CS space. */ - if (cs_dwords > (r300->cs->ndw - r300->cs->cdw)) { + if (cs_dwords > (R300_MAX_CMDBUF_DWORDS - r300->cs->cdw)) { r300->context.flush(&r300->context, 0, NULL); flushed = TRUE; } @@ -239,19 +232,32 @@ static boolean r300_emit_states(struct r300_context *r300, boolean emit_aos = flags & PREP_EMIT_AOS; boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL; boolean indexed = flags & PREP_INDEXED; - boolean hw_index_bias = r500_index_bias_supported(r300); + boolean validate_vbos = flags & PREP_VALIDATE_VBOS; /* Validate buffers and emit dirty state if needed. */ if (first_draw) { - if (!r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS, - index_buffer)) { - fprintf(stderr, "r300: CS space validation failed. " - "(not enough memory?) Skipping rendering.\n"); - return FALSE; + /* upload buffers first */ + if (r300->screen->caps.has_tcl && r300->any_user_vbs) { + r300_upload_user_buffers(r300); + r300->any_user_vbs = false; + } + + if (r300->validate_buffers) { + if (!r300_emit_buffer_validate(r300, validate_vbos, + index_buffer)) { + fprintf(stderr, "r300: CS space validation failed. " + "(not enough memory?) Skipping rendering.\n"); + return FALSE; + } + + /* Consider the validation done only if everything was validated. */ + if (validate_vbos) { + r300->validate_buffers = FALSE; + } } r300_emit_dirty_state(r300); - if (hw_index_bias) { + if (r300->screen->caps.index_bias_supported) { if (r300->screen->caps.has_tcl) r500_emit_index_bias(r300, index_bias); else @@ -535,30 +541,9 @@ static void r300_draw_range_elements(struct pipe_context* pipe, r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ - boolean translate = FALSE; unsigned new_offset; - if (r300->skip_rendering) { - return; - } - - if (!u_trim_pipe_prim(mode, &count)) { - return; - } - - /* Index buffer range checking. */ - if ((start + count) * indexSize > indexBuffer->width0) { - fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); - return; - } - - /* Set up fallback for incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300); - translate = TRUE; - } - - if (indexBias && !r500_index_bias_supported(r300)) { + if (indexBias && !r300->screen->caps.index_bias_supported) { r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset); } @@ -566,7 +551,27 @@ static void r300_draw_range_elements(struct pipe_context* pipe, &start, count); r300_update_derived_state(r300); - r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count, &new_offset); + + /* Fallback for misaligned ushort indices. */ + if (indexSize == 2 && start % 2 == 1) { + struct pipe_transfer *transfer; + struct pipe_resource *userbuf; + uint16_t *ptr = pipe_buffer_map(pipe, indexBuffer, + PIPE_TRANSFER_READ, &transfer); + + /* Copy the mapped index buffer directly to the upload buffer. + * The start index will be aligned simply from the fact that + * every sub-buffer in u_upload_mgr is aligned. */ + userbuf = pipe->screen->user_buffer_create(pipe->screen, + ptr + start, count * 2, + PIPE_BIND_INDEX_BUFFER); + indexBuffer = userbuf; + r300_upload_index_buffer(r300, &indexBuffer, indexSize, 0, count, &new_offset); + pipe_resource_reference(&userbuf, NULL); + pipe_buffer_unmap(pipe, indexBuffer, transfer); + } else { + r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count, &new_offset); + } start = new_offset; @@ -603,10 +608,6 @@ done: if (indexBuffer != orgIndexBuffer) { pipe_resource_reference( &indexBuffer, NULL ); } - - if (translate) { - r300_end_vertex_translate(r300); - } } static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, @@ -617,21 +618,6 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, count > 65536 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; - boolean translate = FALSE; - - if (r300->skip_rendering) { - return; - } - - if (!u_trim_pipe_prim(mode, &count)) { - return; - } - - /* Set up fallback for incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300); - translate = TRUE; - } r300_update_derived_state(r300); @@ -642,7 +628,7 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, start, 0)) - goto done; + return; if (alt_num_verts || count <= 65535) { r300_emit_draw_arrays(r300, mode, count); @@ -659,32 +645,53 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, start, 0)) - goto done; + return; } } while (count); } } - -done: - if (translate) { - r300_end_vertex_translate(r300); - } } static void r300_draw_vbo(struct pipe_context* pipe, const struct pipe_draw_info *info) { struct r300_context* r300 = r300_context(pipe); + unsigned count = info->count; + boolean translate = FALSE; + boolean indexed = info->indexed && r300->index_buffer.buffer; + unsigned start_indexed = 0; - if (!r300->velems->count || !r300->vertex_buffer_count) - return; + if (r300->skip_rendering) { + return; + } - if (info->indexed && r300->index_buffer.buffer) { - unsigned offset; + if (!u_trim_pipe_prim(info->mode, &count)) { + return; + } + /* Index buffer range checking. */ + if (indexed) { assert(r300->index_buffer.offset % r300->index_buffer.index_size == 0); - offset = r300->index_buffer.offset / r300->index_buffer.index_size; + /* Compute start for draw_elements, taking the offset into account. */ + start_indexed = + info->start + + (r300->index_buffer.offset / r300->index_buffer.index_size); + + if ((start_indexed + count) * r300->index_buffer.index_size > + r300->index_buffer.buffer->width0) { + fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); + return; + } + } + + /* Set up fallback for incompatible vertex layout if needed. */ + if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { + r300_begin_vertex_translate(r300); + translate = TRUE; + } + + if (indexed) { r300_draw_range_elements(pipe, r300->index_buffer.buffer, r300->index_buffer.index_size, @@ -692,14 +699,17 @@ static void r300_draw_vbo(struct pipe_context* pipe, info->min_index, info->max_index, info->mode, - info->start + offset, - info->count); - } - else { + start_indexed, + count); + } else { r300_draw_arrays(pipe, info->mode, info->start, - info->count); + count); + } + + if (translate) { + r300_end_vertex_translate(r300); } } @@ -826,6 +836,7 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, R300_MAX_DRAW_VBO_SIZE); r300->draw_vbo_offset = 0; r300->draw_vbo_size = R300_MAX_DRAW_VBO_SIZE; + r300->validate_buffers = TRUE; } r300render->vertex_size = vertex_size; @@ -983,7 +994,7 @@ static void r300_render_draw_elements(struct vbuf_render* render, end_cs_dwords = r300_get_num_cs_end_dwords(r300); while (count) { - free_dwords = r300->cs->ndw - r300->cs->cdw; + free_dwords = R300_MAX_CMDBUF_DWORDS - r300->cs->cdw; short_count = MIN2(count, (free_dwords - end_cs_dwords - 6) * 2); @@ -1104,6 +1115,8 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter, const float zeros[4] = {0, 0, 0, 0}; CS_LOCALS(r300); + r300->context.set_vertex_buffers(&r300->context, 0, NULL); + if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) r300->sprite_coord_enable = 1; @@ -1160,37 +1173,45 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter, done: /* Restore the state. */ - r300->clip_state.dirty = TRUE; - r300->rs_state.dirty = TRUE; - r300->viewport_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->clip_state); + r300_mark_atom_dirty(r300, &r300->rs_state); + r300_mark_atom_dirty(r300, &r300->viewport_state); r300->sprite_coord_enable = last_sprite_coord_enable; } static void r300_resource_resolve(struct pipe_context* pipe, struct pipe_resource* dest, - struct pipe_subresource subdest, + unsigned dst_layer, struct pipe_resource* src, - struct pipe_subresource subsrc) + unsigned src_layer) { struct r300_context* r300 = r300_context(pipe); + struct pipe_surface* srcsurf, surf_tmpl; struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; - struct pipe_surface* srcsurf = src->screen->get_tex_surface(src->screen, - src, subsrc.face, subsrc.level, 0, 0); float color[] = {0, 0, 0, 0}; + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = src->format; + surf_tmpl.usage = 0; /* not really a surface hence no bind flags */ + surf_tmpl.u.tex.level = 0; /* msaa resources cannot have mipmaps */ + surf_tmpl.u.tex.first_layer = src_layer; + surf_tmpl.u.tex.last_layer = src_layer; + srcsurf = pipe->create_surface(pipe, src, &surf_tmpl); + surf_tmpl.format = dest->format; + surf_tmpl.u.tex.first_layer = dst_layer; + surf_tmpl.u.tex.last_layer = dst_layer; + DBG(r300, DBG_DRAW, "r300: Resolving resource...\n"); /* Enable AA resolve. */ - aa->dest = r300_surface( - dest->screen->get_tex_surface(dest->screen, dest, subdest.face, - subdest.level, 0, 0)); + aa->dest = r300_surface(pipe->create_surface(pipe, dest, &surf_tmpl)); aa->aaresolve_ctl = R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE | R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE; r300->aa_state.size = 12; - r300->aa_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->aa_state); /* Resolve the surface. */ r300->context.clear_render_target(pipe, @@ -1199,7 +1220,7 @@ static void r300_resource_resolve(struct pipe_context* pipe, /* Disable AA resolve. */ aa->aaresolve_ctl = 0; r300->aa_state.size = 4; - r300->aa_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->aa_state); pipe_surface_reference((struct pipe_surface**)&srcsurf, NULL); pipe_surface_reference((struct pipe_surface**)&aa->dest, NULL); diff --git a/src/gallium/drivers/r300/r300_render_stencilref.c b/src/gallium/drivers/r300/r300_render_stencilref.c index 1f035d64a28..747594afaf2 100644 --- a/src/gallium/drivers/r300/r300_render_stencilref.c +++ b/src/gallium/drivers/r300/r300_render_stencilref.c @@ -66,7 +66,7 @@ static void r300_stencilref_begin(struct r300_context *r300) /* We *cull* pixels, therefore no need to mask out the bits. */ rs->cb_main[rs->cull_mode_index] |= R300_CULL_BACK; - r300->rs_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->rs_state); } /* Set drawing for back faces. */ @@ -80,8 +80,8 @@ static void r300_stencilref_switch_side(struct r300_context *r300) dsa->stencil_ref_mask = dsa->stencil_ref_bf; r300->stencil_ref.ref_value[0] = r300->stencil_ref.ref_value[1]; - r300->rs_state.dirty = TRUE; - r300->dsa_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->rs_state); + r300_mark_atom_dirty(r300, &r300->dsa_state); } /* Restore the original state. */ @@ -96,8 +96,8 @@ static void r300_stencilref_end(struct r300_context *r300) dsa->stencil_ref_mask = sr->zb_stencilrefmask; r300->stencil_ref.ref_value[0] = sr->ref_value_front; - r300->rs_state.dirty = TRUE; - r300->dsa_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->rs_state); + r300_mark_atom_dirty(r300, &r300->dsa_state); } static void r300_stencilref_draw_vbo(struct pipe_context *pipe, diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c index 9247064508f..90b2f40be5f 100644 --- a/src/gallium/drivers/r300/r300_render_translate.c +++ b/src/gallium/drivers/r300/r300_render_translate.c @@ -145,6 +145,7 @@ void r300_begin_vertex_translate(struct r300_context *r300) vb->max_index = num_verts - 1; vb->stride = key.output_stride; r300->tran.vb_slot = i; + r300->validate_buffers = TRUE; break; } } @@ -199,12 +200,14 @@ void r300_translate_index_buffer(struct r300_context *r300, util_shorten_ubyte_elts(&r300->context, index_buffer, index_offset, *start, count); *index_size = 2; *start = 0; + r300->validate_buffers = TRUE; break; case 2: - if (*start % 2 != 0 || index_offset) { + if (index_offset) { util_rebuild_ushort_elts(&r300->context, index_buffer, index_offset, *start, count); *start = 0; + r300->validate_buffers = TRUE; } break; @@ -212,6 +215,7 @@ void r300_translate_index_buffer(struct r300_context *r300, if (index_offset) { util_rebuild_uint_elts(&r300->context, index_buffer, index_offset, *start, count); *start = 0; + r300->validate_buffers = TRUE; } break; } diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c index f6f33028dc6..dd1df970594 100644 --- a/src/gallium/drivers/r300/r300_resource.c +++ b/src/gallium/drivers/r300/r300_resource.c @@ -58,6 +58,8 @@ void r300_init_resource_functions(struct r300_context *r300) r300->context.transfer_destroy = u_transfer_destroy_vtbl; r300->context.transfer_inline_write = u_transfer_inline_write_vtbl; r300->context.is_resource_referenced = u_is_resource_referenced_vtbl; + r300->context.create_surface = r300_create_surface; + r300->context.surface_destroy = r300_surface_destroy; } void r300_init_screen_resource_functions(struct r300_screen *r300screen) @@ -67,7 +69,4 @@ void r300_init_screen_resource_functions(struct r300_screen *r300screen) r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl; r300screen->screen.resource_destroy = u_resource_destroy_vtbl; r300screen->screen.user_buffer_create = r300_user_buffer_create; - - r300screen->screen.get_tex_surface = r300_get_tex_surface; - r300screen->screen.tex_surface_destroy = r300_tex_surface_destroy; } diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 37563b5a940..921d6f1e676 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -32,6 +32,8 @@ #include "r300_winsys.h" #include "r300_public.h" +#include "draw/draw_context.h" + /* Return the identifier behind whom the brave coders responsible for this * amalgamation of code, sweat, and duct tape, routinely obscure their names. * @@ -114,8 +116,9 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_TEXTURE_MIRROR_REPEAT: case PIPE_CAP_BLEND_EQUATION_SEPARATE: - case PIPE_CAP_TEXTURE_SWIZZLE: return 1; + case PIPE_CAP_TEXTURE_SWIZZLE: + return util_format_s3tc_enabled ? r300screen->caps.dxtc_swizzle : 1; /* Unsupported features (boolean caps). */ case PIPE_CAP_TIMER_QUERY: @@ -212,9 +215,15 @@ static int r300_get_shader_param(struct pipe_screen *pscreen, unsigned shader, e case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 0; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; } break; case PIPE_SHADER_VERTEX: + if (!r300screen->caps.has_tcl) { + return draw_get_shader_param(shader, param); + } + switch (param) { case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: @@ -245,6 +254,8 @@ static int r300_get_shader_param(struct pipe_screen *pscreen, unsigned shader, e return 0; case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; default: break; } @@ -277,6 +288,13 @@ static float r300_get_paramf(struct pipe_screen* pscreen, enum pipe_cap param) return 16.0f; case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: return 16.0f; + case PIPE_CAP_GUARD_BAND_LEFT: + case PIPE_CAP_GUARD_BAND_TOP: + case PIPE_CAP_GUARD_BAND_RIGHT: + case PIPE_CAP_GUARD_BAND_BOTTOM: + /* XXX I don't know what these should be but the least we can do is + * silence the potential error message */ + return 0.0f; default: debug_printf("r300: Warning: Unknown CAP %d in get_paramf.\n", param); @@ -382,7 +400,7 @@ static void r300_destroy_screen(struct pipe_screen* pscreen) struct r300_screen* r300screen = r300_screen(pscreen); struct r300_winsys_screen *rws = r300_winsys_screen(pscreen); - util_mempool_destroy(&r300screen->pool_buffers); + util_slab_destroy(&r300screen->pool_buffers); if (rws) rws->destroy(rws); @@ -439,9 +457,13 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) r300_init_debug(r300screen); r300_parse_chipset(&r300screen->caps); - util_mempool_create(&r300screen->pool_buffers, - sizeof(struct r300_buffer), 64, - UTIL_MEMPOOL_SINGLETHREADED); + r300screen->caps.index_bias_supported = + r300screen->caps.is_r500 && + rws->get_value(rws, R300_VID_DRM_2_3_0); + + util_slab_create(&r300screen->pool_buffers, + sizeof(struct r300_buffer), 64, + UTIL_SLAB_SINGLETHREADED); r300screen->rws = rws; r300screen->screen.winsys = (struct pipe_winsys*)rws; diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 8b7f1fab61b..5847fe1ffc8 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -28,7 +28,7 @@ #include "r300_chipset.h" -#include "util/u_mempool.h" +#include "util/u_slab.h" #include <stdio.h> @@ -44,7 +44,7 @@ struct r300_screen { struct r300_capabilities caps; /* Memory pools. */ - struct util_mempool pool_buffers; + struct util_slab_mempool pool_buffers; /** Combination of DBG_xxx flags */ unsigned debug; @@ -101,7 +101,6 @@ r300_winsys_screen(struct pipe_screen *screen) { #define DBG_NO_OPT (1 << 20) #define DBG_NO_CBZB (1 << 21) /* Statistics. */ -#define DBG_STATS (1 << 24) #define DBG_P_STAT (1 << 25) /*@}*/ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index 37a080ba48b..44364435221 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -43,7 +43,7 @@ unsigned r300_buffer_is_referenced(struct pipe_context *context, if (r300_buffer_is_user_buffer(buf)) return PIPE_UNREFERENCED; - if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->buf, domain)) + if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf, domain)) return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; return PIPE_UNREFERENCED; @@ -51,7 +51,7 @@ unsigned r300_buffer_is_referenced(struct pipe_context *context, static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context, struct pipe_resource *buf, - unsigned face, unsigned level) + unsigned level, int layer) { return r300_buffer_is_referenced(context, buf, R300_REF_CS); } @@ -118,6 +118,7 @@ int r300_upload_user_buffers(struct r300_context *r300) pipe_resource_reference(&vb->buffer, NULL); vb->buffer = upload_buffer; vb->buffer_offset = upload_offset; + r300->validate_buffers = TRUE; } } return ret; @@ -136,26 +137,26 @@ static void r300_buffer_destroy(struct pipe_screen *screen, if (rbuf->buf) rws->buffer_reference(rws, &rbuf->buf, NULL); - util_mempool_free(&r300screen->pool_buffers, rbuf); + util_slab_free(&r300screen->pool_buffers, rbuf); } static struct pipe_transfer* -r300_default_get_transfer(struct pipe_context *context, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) +r300_buffer_get_transfer(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct r300_context *r300 = r300_context(context); struct pipe_transfer *transfer = - util_mempool_malloc(&r300->pool_transfers); + util_slab_alloc(&r300->pool_transfers); transfer->resource = resource; - transfer->sr = sr; + transfer->level = level; transfer->usage = usage; transfer->box = *box; transfer->stride = 0; - transfer->slice_stride = 0; + transfer->layer_stride = 0; transfer->data = NULL; /* Note strides are zero, this is ok for buffers, but not for @@ -164,11 +165,11 @@ r300_default_get_transfer(struct pipe_context *context, return transfer; } -static void r300_default_transfer_destroy(struct pipe_context *pipe, - struct pipe_transfer *transfer) +static void r300_buffer_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) { struct r300_context *r300 = r300_context(pipe); - util_mempool_free(&r300->pool_transfers, transfer); + util_slab_free(&r300->pool_transfers, transfer); } static void * @@ -206,6 +207,9 @@ r300_buffer_transfer_map( struct pipe_context *pipe, rbuf->b.b.bind, rbuf->b.b.usage, rbuf->domain); + rbuf->cs_buf = + r300screen->rws->buffer_get_cs_handle(r300screen->rws, + rbuf->buf); break; } } @@ -265,17 +269,45 @@ static void r300_buffer_transfer_unmap( struct pipe_context *pipe, } } +static void r300_buffer_transfer_inline_write(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct r300_buffer *rbuf = r300_buffer(resource); + struct pipe_transfer *transfer = NULL; + uint8_t *map = NULL; + + if (rbuf->constant_buffer) { + memcpy(rbuf->constant_buffer + box->x, data, box->width); + return; + } + + transfer = r300_buffer_get_transfer(pipe, resource, 0, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, box); + map = r300_buffer_transfer_map(pipe, transfer); + + memcpy(map, data, box->width); + + r300_buffer_transfer_unmap(pipe, transfer); + r300_buffer_transfer_destroy(pipe, transfer); +} + struct u_resource_vtbl r300_buffer_vtbl = { u_default_resource_get_handle, /* get_handle */ r300_buffer_destroy, /* resource_destroy */ r300_buffer_is_referenced_by_cs, /* is_buffer_referenced */ - r300_default_get_transfer, /* get_transfer */ - r300_default_transfer_destroy, /* transfer_destroy */ + r300_buffer_get_transfer, /* get_transfer */ + r300_buffer_transfer_destroy, /* transfer_destroy */ r300_buffer_transfer_map, /* transfer_map */ r300_buffer_transfer_flush_region, /* transfer_flush_region */ r300_buffer_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ + r300_buffer_transfer_inline_write /* transfer_inline_write */ }; struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, @@ -285,7 +317,7 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, struct r300_buffer *rbuf; unsigned alignment = 16; - rbuf = util_mempool_malloc(&r300screen->pool_buffers); + rbuf = util_slab_alloc(&r300screen->pool_buffers); rbuf->magic = R300_BUFFER_MAGIC; @@ -310,9 +342,11 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, rbuf->b.b.width0, alignment, rbuf->b.b.bind, rbuf->b.b.usage, rbuf->domain); + rbuf->cs_buf = + r300screen->rws->buffer_get_cs_handle(r300screen->rws, rbuf->buf); if (!rbuf->buf) { - util_mempool_free(&r300screen->pool_buffers, rbuf); + util_slab_free(&r300screen->pool_buffers, rbuf); return NULL; } @@ -327,7 +361,7 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, struct r300_screen *r300screen = r300_screen(screen); struct r300_buffer *rbuf; - rbuf = util_mempool_malloc(&r300screen->pool_buffers); + rbuf = util_slab_alloc(&r300screen->pool_buffers); rbuf->magic = R300_BUFFER_MAGIC; @@ -341,6 +375,7 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, rbuf->b.b.width0 = bytes; rbuf->b.b.height0 = 1; rbuf->b.b.depth0 = 1; + rbuf->b.b.array_size = 1; rbuf->b.b.flags = 0; rbuf->domain = R300_DOMAIN_GTT; rbuf->num_ranges = 0; diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index cafa9f96f20..0b3555dd813 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -51,11 +51,12 @@ struct r300_buffer uint32_t magic; struct r300_winsys_buffer *buf; + struct r300_winsys_cs_buffer *cs_buf; enum r300_buffer_domain domain; - void *user_buffer; - void *constant_buffer; + uint8_t *user_buffer; + uint8_t *constant_buffer; struct r300_buffer_range ranges[R300_BUFFER_MAX_RANGES]; unsigned num_ranges; }; @@ -86,11 +87,7 @@ unsigned r300_buffer_is_referenced(struct pipe_context *context, static INLINE struct r300_buffer *r300_buffer(struct pipe_resource *buffer) { - if (buffer) { - assert(((struct r300_buffer *)buffer)->magic == R300_BUFFER_MAGIC); - return (struct r300_buffer *)buffer; - } - return NULL; + return (struct r300_buffer *)buffer; } static INLINE boolean r300_buffer_is_user_buffer(struct pipe_resource *buffer) diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index bd08bf2d3fd..f902db54cc1 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -52,7 +52,7 @@ #define UPDATE_STATE(cso, atom) \ if (cso != atom.state) { \ atom.state = cso; \ - atom.dirty = TRUE; \ + r300_mark_atom_dirty(r300, &(atom)); \ } static boolean blend_discard_if_src_alpha_0(unsigned srcRGB, unsigned srcA, @@ -417,7 +417,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, END_CB; } - r300->blend_color_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->blend_color_state); } static void r300_set_clip_state(struct pipe_context* pipe, @@ -446,7 +446,7 @@ static void r300_set_clip_state(struct pipe_context* pipe, (state->depth_clamp ? R300_CLIP_DISABLE : 0)); END_CB; - r300->clip_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->clip_state); } else { draw_set_clip_state(r300->draw, state); } @@ -594,7 +594,7 @@ static void r300_bind_dsa_state(struct pipe_context* pipe, UPDATE_STATE(state, r300->dsa_state); - r300->hyperz_state.dirty = TRUE; /* Will be updated before the emission. */ + r300_mark_atom_dirty(r300, &r300->hyperz_state); /* Will be updated before the emission. */ r300_dsa_inject_stencilref(r300); } @@ -613,7 +613,7 @@ static void r300_set_stencil_ref(struct pipe_context* pipe, r300->stencil_ref = *sr; r300_dsa_inject_stencilref(r300); - r300->dsa_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->dsa_state); } static void r300_tex_set_tiling_flags(struct r300_context *r300, @@ -626,7 +626,7 @@ static void r300_tex_set_tiling_flags(struct r300_context *r300, /* Tiling determines how DRM treats the buffer data. * We must flush CS when changing it if the buffer is referenced. */ if (r300->rws->cs_is_buffer_referenced(r300->cs, - tex->buffer, R300_REF_CS)) + tex->cs_buffer, R300_REF_CS)) r300->context.flush(&r300->context, 0, NULL); r300->rws->buffer_set_tiling(r300->rws, tex->buffer, @@ -647,12 +647,12 @@ static void r300_fb_set_tiling_flags(struct r300_context *r300, for (i = 0; i < state->nr_cbufs; i++) { r300_tex_set_tiling_flags(r300, r300_texture(state->cbufs[i]->texture), - state->cbufs[i]->level); + state->cbufs[i]->u.tex.level); } if (state->zsbuf) { r300_tex_set_tiling_flags(r300, r300_texture(state->zsbuf->texture), - state->zsbuf->level); + state->zsbuf->u.tex.level); } } @@ -663,14 +663,14 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, struct r300_texture *rtex = r300_texture(tex); fprintf(stderr, - "r300: %s[%i] Dim: %ix%i, Offset: %i, ZSlice: %i, " - "Face: %i, Level: %i, Format: %s\n" + "r300: %s[%i] Dim: %ix%i, Firstlayer: %i, " + "Lastlayer: %i, Level: %i, Format: %s\n" "r300: TEX: Macro: %s, Micro: %s, Pitch: %i, " "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n", - binding, index, surf->width, surf->height, surf->offset, - surf->zslice, surf->face, surf->level, + binding, index, surf->width, surf->height, + surf->u.tex.first_layer, surf->u.tex.last_layer, surf->u.tex.level, util_format_short_name(surf->format), rtex->desc.macrotile[0] ? "YES" : " NO", @@ -687,13 +687,13 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ); /* What is marked as dirty depends on the enum r300_fb_state_change. */ - r300->gpu_flush.dirty = TRUE; - r300->fb_state.dirty = TRUE; - r300->hyperz_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->gpu_flush); + r300_mark_atom_dirty(r300, &r300->fb_state); + r300_mark_atom_dirty(r300, &r300->hyperz_state); if (change == R300_CHANGED_FB_STATE) { - r300->aa_state.dirty = TRUE; - r300->fb_state_pipelined.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->aa_state); + r300_mark_atom_dirty(r300, &r300->fb_state_pipelined); } /* Now compute the fb_state atom size. */ @@ -738,11 +738,11 @@ static void /* If nr_cbufs is changed from zero to non-zero or vice versa... */ if (!!old_state->nr_cbufs != !!state->nr_cbufs) { - r300->blend_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->blend_state); } /* If zsbuf is set from NULL to non-NULL or vice versa.. */ if (!!old_state->zsbuf != !!state->zsbuf) { - r300->dsa_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->dsa_state); } /* The tiling flags are dependent on the surface miplevel, unfortunately. */ @@ -751,6 +751,7 @@ static void util_copy_framebuffer_state(r300->fb_state.state, state); r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE); + r300->validate_buffers = TRUE; r300->z_compression = false; @@ -768,7 +769,7 @@ static void struct r300_surface *zs_surf = r300_surface(state->zsbuf); struct r300_texture *tex; int compress = r300->screen->caps.is_rv350 ? RV350_Z_COMPRESS_88 : R300_Z_COMPRESS_44; - int level = zs_surf->base.level; + int level = zs_surf->base.u.tex.level; tex = r300_texture(zs_surf->base.texture); @@ -795,7 +796,7 @@ static void r300->zbuffer_bpp = zbuffer_bpp; if (r300->polygon_offset_enabled) - r300->rs_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->rs_state); } } @@ -853,9 +854,9 @@ void r300_mark_fs_code_dirty(struct r300_context *r300) { struct r300_fragment_shader* fs = r300_fs(r300); - r300->fs.dirty = TRUE; - r300->fs_rc_constant_state.dirty = TRUE; - r300->fs_constants.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->fs); + r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state); + r300_mark_atom_dirty(r300, &r300->fs_constants); r300->fs.size = fs->shader->cb_code_size; if (r300->screen->caps.is_r500) { @@ -885,7 +886,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) r300_pick_fragment_shader(r300); r300_mark_fs_code_dirty(r300); - r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ + r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */ } /* Delete fragment shader state. */ @@ -1137,7 +1138,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (last_sprite_coord_enable != r300->sprite_coord_enable || last_two_sided_color != r300->two_sided_color) { - r300->rs_block_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->rs_block_state); } } @@ -1235,7 +1236,7 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, memcpy(state->sampler_states, states, sizeof(void*) * count); state->sampler_state_count = count; - r300->textures_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->textures_state); } static void r300_lacks_vertex_textures(struct pipe_context* pipe, @@ -1297,29 +1298,27 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, } for (i = 0; i < count; i++) { - if (&state->sampler_views[i]->base != views[i]) { - pipe_sampler_view_reference( - (struct pipe_sampler_view**)&state->sampler_views[i], - views[i]); + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->sampler_views[i], + views[i]); - if (!views[i]) { - continue; - } + if (!views[i]) { + continue; + } - /* A new sampler view (= texture)... */ - dirty_tex = TRUE; + /* A new sampler view (= texture)... */ + dirty_tex = TRUE; - /* Set the texrect factor in the fragment shader. + /* Set the texrect factor in the fragment shader. * Needed for RECT and NPOT fallback. */ - texture = r300_texture(views[i]->texture); - if (texture->desc.is_npot) { - r300->fs_rc_constant_state.dirty = TRUE; - } + texture = r300_texture(views[i]->texture); + if (texture->desc.is_npot) { + r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state); + } - state->sampler_views[i]->texcache_region = + state->sampler_views[i]->texcache_region = r300_assign_texture_cache_region(view_index, real_num_views); - view_index++; - } + view_index++; } for (i = count; i < tex_units; i++) { @@ -1332,10 +1331,11 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, state->sampler_view_count = count; - r300->textures_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->textures_state); + r300->validate_buffers = TRUE; if (dirty_tex) { - r300->texture_cache_inval.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->texture_cache_inval); } } @@ -1347,6 +1347,7 @@ r300_create_sampler_view(struct pipe_context *pipe, struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); struct r300_texture *tex = r300_texture(texture); boolean is_r500 = r300_screen(pipe->screen)->caps.is_r500; + boolean dxtc_swizzle = r300_screen(pipe->screen)->caps.dxtc_swizzle; if (view) { view->base = *templ; @@ -1363,7 +1364,8 @@ r300_create_sampler_view(struct pipe_context *pipe, view->format = tex->tx_format; view->format.format1 |= r300_translate_texformat(templ->format, view->swizzle, - is_r500); + is_r500, + dxtc_swizzle); if (is_r500) { view->format.format2 |= r500_tx_format_msb_bit(templ->format); } @@ -1388,7 +1390,7 @@ static void r300_set_scissor_state(struct pipe_context* pipe, memcpy(r300->scissor_state.state, state, sizeof(struct pipe_scissor_state)); - r300->scissor_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->scissor_state); } static void r300_set_viewport_state(struct pipe_context* pipe, @@ -1434,9 +1436,9 @@ static void r300_set_viewport_state(struct pipe_context* pipe, viewport->vte_control |= R300_VPORT_Z_OFFSET_ENA; } - r300->viewport_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->viewport_state); if (r300->fs.state && r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) { - r300->fs_rc_constant_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state); } } @@ -1448,6 +1450,15 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, struct pipe_vertex_buffer *vbo; unsigned i, max_index = (1 << 24) - 1; boolean any_user_buffer = FALSE; + struct pipe_vertex_buffer dummy_vb = {0}; + + /* There must be at least one vertex buffer set, otherwise it locks up. */ + if (!count) { + dummy_vb.buffer = r300->dummy_vb; + dummy_vb.max_index = r300->dummy_vb->width0 / 4; + buffers = &dummy_vb; + count = 1; + } if (count == r300->vertex_buffer_count && memcmp(r300->vertex_buffer, buffers, @@ -1483,14 +1494,14 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, any_user_buffer = TRUE; } + /* The stride of zero means we will be fetching only the first + * vertex, so don't care about max_index. */ + if (!vbo->stride) + continue; + if (vbo->max_index == ~0) { - /* if no VBO stride then only one vertex value so max index is 1 */ - /* should think about converting to VS constants like svga does */ - if (!vbo->stride) - vbo->max_index = 1; - else - vbo->max_index = - (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; + vbo->max_index = + (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; } max_index = MIN2(vbo->max_index, max_index); @@ -1498,7 +1509,8 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, r300->any_user_vbs = any_user_buffer; r300->vertex_buffer_max_index = max_index; - + r300->aos_dirty = TRUE; + r300->validate_buffers = TRUE; } else { /* SW TCL. */ draw_set_vertex_buffers(r300->draw, count, buffers); @@ -1534,10 +1546,10 @@ static void r300_set_index_buffer(struct pipe_context* pipe, } if (r300->screen->caps.has_tcl) { - /* TODO make this more like a state */ + r300->validate_buffers = TRUE; } else { - draw_set_index_buffer(r300->draw, ib); + draw_set_index_buffer(r300->draw, ib); } } @@ -1601,6 +1613,14 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, struct r300_vertex_element_state *velems; unsigned i; enum pipe_format *format; + struct pipe_vertex_element dummy_attrib = {0}; + + /* R300 Programmable Stream Control (PSC) doesn't support 0 vertex elements. */ + if (!count) { + dummy_attrib.src_format = PIPE_FORMAT_R8G8B8A8_UNORM; + attribs = &dummy_attrib; + count = 1; + } assert(count <= PIPE_MAX_ATTRIBS); velems = CALLOC_STRUCT(r300_vertex_element_state); @@ -1667,7 +1687,8 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, * swizzles are already set up. * Also compute the vertex size. */ for (i = 0; i < count; i++) { - /* This is OK because we check for aligned strides too. */ + /* This is OK because we check for aligned strides too + * elsewhere. */ velems->hw_format_size[i] = align(util_format_get_blocksize(velems->hw_format[i]), 4); velems->vertex_size_dwords += velems->hw_format_size[i] / 4; @@ -1696,6 +1717,7 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2; + r300->aos_dirty = TRUE; } static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state) @@ -1738,27 +1760,25 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) r300->vs_state.state = vs; /* The majority of the RS block bits is dependent on the vertex shader. */ - r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ + r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */ if (r300->screen->caps.has_tcl) { unsigned fc_op_dwords = r300->screen->caps.is_r500 ? 3 : 2; - r300->vs_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->vs_state); r300->vs_state.size = vs->code.length + 9 + - (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0) + (vs->code.num_fc_ops ? vs->code.num_fc_ops * fc_op_dwords + 4 : 0); - if (vs->externals_count) { - r300->vs_constants.dirty = TRUE; - r300->vs_constants.size = vs->externals_count * 4 + 3; - } else { - r300->vs_constants.size = 0; - } + r300_mark_atom_dirty(r300, &r300->vs_constants); + r300->vs_constants.size = + 2 + + (vs->externals_count ? vs->externals_count * 4 + 3 : 0) + + (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0); ((struct r300_constant_buffer*)r300->vs_constants.state)->remap_table = vs->code.constants_remap_table; - r300->pvs_flush.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->pvs_flush); } else { draw_bind_vertex_shader(r300->draw, (struct draw_vertex_shader*)vs->draw_vs); @@ -1799,33 +1819,44 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, cbuf = (struct r300_constant_buffer*)r300->fs_constants.state; break; default: - assert(0); return; } if (buf == NULL || buf->width0 == 0 || - (mapped = r300_buffer(buf)->constant_buffer) == NULL) { + (mapped = (uint32_t*)r300_buffer(buf)->constant_buffer) == NULL) { return; } if (shader == PIPE_SHADER_FRAGMENT || (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) { assert((buf->width0 % (4 * sizeof(float))) == 0); - cbuf->ptr = mapped + index*4; + cbuf->ptr = mapped; } if (shader == PIPE_SHADER_VERTEX) { if (r300->screen->caps.has_tcl) { - if (r300->vs_constants.size) { - r300->vs_constants.dirty = TRUE; + struct r300_vertex_shader *vs = + (struct r300_vertex_shader*)r300->vs_state.state; + + if (!vs) { + cbuf->buffer_base = 0; + return; + } + + cbuf->buffer_base = r300->vs_const_base; + r300->vs_const_base += vs->code.constants.Count; + if (r300->vs_const_base > R500_MAX_PVS_CONST_VECS) { + r300->vs_const_base = vs->code.constants.Count; + cbuf->buffer_base = 0; + r300_mark_atom_dirty(r300, &r300->pvs_flush); } - r300->pvs_flush.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->vs_constants); } else if (r300->draw) { draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, 0, mapped, buf->width0); } } else if (shader == PIPE_SHADER_FRAGMENT) { - r300->fs_constants.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->fs_constants); } } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 50366e32c2b..d5fc8ece252 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -25,6 +25,7 @@ #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_pack_color.h" #include "r300_context.h" #include "r300_fs.h" @@ -192,7 +193,7 @@ static void r300_swtcl_vertex_psc(struct r300_context *r300) (R300_LAST_VEC << (i & 1 ? 16 : 0)); vstream->count = (i >> 1) + 1; - r300->vertex_stream_state.dirty = TRUE; + r300_mark_atom_dirty(r300, &r300->vertex_stream_state); r300->vertex_stream_state.size = (1 + vstream->count) * 2; } @@ -433,6 +434,8 @@ static void r300_update_rs_block(struct r300_context *r300) fp_offset++; col_count++; DBG(r300, DBG_RS, "r300: Rasterized FACE written to FS.\n"); + } else if (fs_inputs->face != ATTR_UNUSED) { + fprintf(stderr, "r300: ERROR: FS input FACE unassigned.\n"); } /* Rasterize texture coordinates. */ @@ -484,12 +487,10 @@ static void r300_update_rs_block(struct r300_context *r300) } } - if (DBG_ON(r300, DBG_RS)) { - for (; i < ATTR_GENERIC_COUNT; i++) { - if (fs_inputs->generic[i] != ATTR_UNUSED) { - DBG(r300, DBG_RS, - "r300: FS input generic %i unassigned.\n", i); - } + for (; i < ATTR_GENERIC_COUNT; i++) { + if (fs_inputs->generic[i] != ATTR_UNUSED) { + fprintf(stderr, "r300: ERROR: FS input generic %i unassigned, " + "not enough hardware slots.\n", i); } } @@ -520,7 +521,12 @@ static void r300_update_rs_block(struct r300_context *r300) if (fs_inputs->fog != ATTR_UNUSED) { fp_offset++; - DBG(r300, DBG_RS, "r300: FS input fog unassigned.\n"); + if (tex_count < 8) { + DBG(r300, DBG_RS, "r300: FS input fog unassigned.\n"); + } else { + fprintf(stderr, "r300: ERROR: FS input fog unassigned, " + "not enough hardware slots.\n"); + } } } @@ -543,6 +549,11 @@ static void r300_update_rs_block(struct r300_context *r300) fp_offset++; tex_count++; tex_ptr += 4; + } else { + if (fs_inputs->wpos != ATTR_UNUSED && tex_count >= 8) { + fprintf(stderr, "r300: ERROR: FS input WPOS unassigned, " + "not enough hardware slots.\n"); + } } /* Invalidate the rest of the no-TCL (GA) stream locations. */ @@ -581,62 +592,93 @@ static void r300_update_rs_block(struct r300_context *r300) } static uint32_t r300_get_border_color(enum pipe_format format, - const float border[4]) + const float border[4], + boolean is_r500) { const struct util_format_description *desc; - float border_swizzled[4] = { - border[2], - border[1], - border[0], - border[3] - }; - uint32_t r; + float border_swizzled[4] = {0}; + unsigned i; + union util_color uc = {0}; desc = util_format_description(format); - /* We don't use util_pack_format because it does not handle the formats - * we want, e.g. R4G4B4A4 is non-existent in Gallium. */ + /* Do depth formats first. */ + if (util_format_is_depth_or_stencil(format)) { + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + return util_pack_z(PIPE_FORMAT_Z16_UNORM, border[0]); + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + if (is_r500) { + return util_pack_z(PIPE_FORMAT_X8Z24_UNORM, border[0]); + } else { + return util_pack_z(PIPE_FORMAT_Z16_UNORM, border[0]) << 16; + } + default: + assert(0); + return 0; + } + } + + /* Apply inverse swizzle of the format. */ + for (i = 0; i < 4; i++) { + switch (desc->swizzle[i]) { + case UTIL_FORMAT_SWIZZLE_X: + border_swizzled[2] = border[i]; + break; + case UTIL_FORMAT_SWIZZLE_Y: + border_swizzled[1] = border[i]; + break; + case UTIL_FORMAT_SWIZZLE_Z: + border_swizzled[0] = border[i]; + break; + case UTIL_FORMAT_SWIZZLE_W: + border_swizzled[3] = border[i]; + break; + } + } + + /* Compressed formats. */ + if (util_format_is_compressed(format)) { + util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_UNORM, &uc); + return uc.ui; + } + switch (desc->channel[0].size) { case 4: - r = ((float_to_ubyte(border_swizzled[0]) & 0xf0) >> 4) | - ((float_to_ubyte(border_swizzled[1]) & 0xf0) << 0) | - ((float_to_ubyte(border_swizzled[2]) & 0xf0) << 4) | - ((float_to_ubyte(border_swizzled[3]) & 0xf0) << 8); + util_pack_color(border_swizzled, PIPE_FORMAT_B4G4R4A4_UNORM, &uc); break; case 5: if (desc->channel[1].size == 5) { - r = ((float_to_ubyte(border_swizzled[0]) & 0xf8) >> 3) | - ((float_to_ubyte(border_swizzled[1]) & 0xf8) << 2) | - ((float_to_ubyte(border_swizzled[2]) & 0xf8) << 7) | - ((float_to_ubyte(border_swizzled[3]) & 0x80) << 8); + util_pack_color(border_swizzled, PIPE_FORMAT_B5G5R5A1_UNORM, &uc); } else if (desc->channel[1].size == 6) { - r = ((float_to_ubyte(border_swizzled[0]) & 0xf8) >> 3) | - ((float_to_ubyte(border_swizzled[1]) & 0xfc) << 3) | - ((float_to_ubyte(border_swizzled[2]) & 0xf8) << 8); + util_pack_color(border_swizzled, PIPE_FORMAT_B5G6R5_UNORM, &uc); } else { assert(0); - r = 0; } break; - case 16: - r = ((float_to_ubyte(border_swizzled[2]) & 0xff) << 0) | - ((float_to_ubyte(border_swizzled[1]) & 0xff) << 8) | - ((float_to_ubyte(border_swizzled[0]) & 0xff) << 16) | - ((float_to_ubyte(border_swizzled[3]) & 0xff) << 24); + default: + case 8: + util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); break; - case 8: - default: - r = ((float_to_ubyte(border_swizzled[0]) & 0xff) << 0) | - ((float_to_ubyte(border_swizzled[1]) & 0xff) << 8) | - ((float_to_ubyte(border_swizzled[2]) & 0xff) << 16) | - ((float_to_ubyte(border_swizzled[3]) & 0xff) << 24); + case 10: + util_pack_color(border_swizzled, PIPE_FORMAT_B10G10R10A2_UNORM, &uc); + break; + + case 16: + if (desc->nr_channels <= 2) { + border_swizzled[0] = border_swizzled[2]; + util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc); + } else { + util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); + } break; } - return r; + return uc.ui; } static void r300_merge_textures_and_samplers(struct r300_context* r300) @@ -675,12 +717,13 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) /* Set the border color. */ texstate->border_color = r300_get_border_color(view->base.format, - sampler->state.border_color); + sampler->state.border_color, + r300->screen->caps.is_r500); /* determine min/max levels */ - max_level = MIN3(sampler->max_lod + view->base.first_level, - tex->desc.b.b.last_level, view->base.last_level); - min_level = MIN2(sampler->min_lod + view->base.first_level, + max_level = MIN3(sampler->max_lod + view->base.u.tex.first_level, + tex->desc.b.b.last_level, view->base.u.tex.last_level); + min_level = MIN2(sampler->min_lod + view->base.u.tex.first_level, max_level); if (tex->desc.is_npot && min_level > 0) { @@ -721,13 +764,18 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) if (sampler->state.compare_mode == PIPE_TEX_COMPARE_NONE) { texstate->format.format1 |= r300_get_swizzle_combined(depth_swizzle, - view->swizzle); + view->swizzle, FALSE); } else { texstate->format.format1 |= - r300_get_swizzle_combined(depth_swizzle, 0); + r300_get_swizzle_combined(depth_swizzle, 0, FALSE); } } + if (r300->screen->caps.dxtc_swizzle && + util_format_is_compressed(tex->desc.b.b.format)) { + texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE; + } + /* to emulate 1D textures through 2D ones correctly */ if (tex->desc.b.b.target == PIPE_TEXTURE_1D) { texstate->filter0 &= ~R300_TX_WRAP_T_MASK; @@ -839,9 +887,8 @@ static void r300_flush_depth_textures(struct r300_context *r300) for (level = 0; level <= tex->last_level; level++) if (r300_texture(tex)->zmask_in_use[level]) { /* We don't handle 3D textures and cubemaps yet. */ - r300_flush_depth_stencil(&r300->context, tex, - u_subresource(0, level), 0); - } + r300_flush_depth_stencil(&r300->context, tex, level, 0); + } } } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index cee56bccdcd..6d86bc282ff 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -40,7 +40,8 @@ #include "pipe/p_screen.h" unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, - const unsigned char *swizzle_view) + const unsigned char *swizzle_view, + boolean dxtc_swizzle) { unsigned i; unsigned char swizzle[4]; @@ -51,10 +52,10 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, R300_TX_FORMAT_B_SHIFT, R300_TX_FORMAT_A_SHIFT }; - const uint32_t swizzle_bit[4] = { - R300_TX_FORMAT_X, + uint32_t swizzle_bit[4] = { + dxtc_swizzle ? R300_TX_FORMAT_Z : R300_TX_FORMAT_X, R300_TX_FORMAT_Y, - R300_TX_FORMAT_Z, + dxtc_swizzle ? R300_TX_FORMAT_X : R300_TX_FORMAT_Z, R300_TX_FORMAT_W }; @@ -107,7 +108,8 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */ uint32_t r300_translate_texformat(enum pipe_format format, const unsigned char *swizzle_view, - boolean is_r500) + boolean is_r500, + boolean dxtc_swizzle) { uint32_t result = 0; const struct util_format_description *desc; @@ -169,7 +171,8 @@ uint32_t r300_translate_texformat(enum pipe_format format, } } - result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view); + result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, + util_format_is_compressed(format) && dxtc_swizzle); /* S3TC formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { @@ -571,7 +574,7 @@ boolean r300_is_zs_format_supported(enum pipe_format format) boolean r300_is_sampler_format_supported(enum pipe_format format) { - return r300_translate_texformat(format, 0, TRUE) != ~0; + return r300_translate_texformat(format, 0, TRUE, FALSE) != ~0; } void r300_texture_setup_format_state(struct r300_screen *screen, @@ -665,21 +668,21 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen, } static unsigned r300_texture_is_referenced(struct pipe_context *context, - struct pipe_resource *texture, - unsigned face, unsigned level) + struct pipe_resource *texture, + unsigned level, int layer) { struct r300_context *r300 = r300_context(context); struct r300_texture *rtex = (struct r300_texture *)texture; if (r300->rws->cs_is_buffer_referenced(r300->cs, - rtex->buffer, R300_REF_CS)) + rtex->cs_buffer, R300_REF_CS)) return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; return PIPE_UNREFERENCED; } static void r300_texture_destroy(struct pipe_screen *screen, - struct pipe_resource* texture) + struct pipe_resource* texture) { struct r300_texture* tex = (struct r300_texture*)texture; struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; @@ -774,6 +777,8 @@ r300_texture_create_object(struct r300_screen *rscreen, } } + tex->cs_buffer = rws->buffer_get_cs_handle(rws, tex->buffer); + rws->buffer_set_tiling(rws, tex->buffer, tex->desc.microtile, tex->desc.macrotile[0], tex->desc.stride_in_bytes[0]); @@ -848,38 +853,40 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, /* Not required to implement u_resource_vtbl, consider moving to another file: */ -struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, - struct pipe_resource* texture, - unsigned face, - unsigned level, - unsigned zslice, - unsigned flags) +struct pipe_surface* r300_create_surface(struct pipe_context * ctx, + struct pipe_resource* texture, + const struct pipe_surface *surf_tmpl) { struct r300_texture* tex = r300_texture(texture); struct r300_surface* surface = CALLOC_STRUCT(r300_surface); + unsigned level = surf_tmpl->u.tex.level; + + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); if (surface) { uint32_t offset, tile_height; pipe_reference_init(&surface->base.reference, 1); pipe_resource_reference(&surface->base.texture, texture); - surface->base.format = texture->format; + surface->base.context = ctx; + surface->base.format = surf_tmpl->format; surface->base.width = u_minify(texture->width0, level); surface->base.height = u_minify(texture->height0, level); - surface->base.usage = flags; - surface->base.zslice = zslice; - surface->base.face = face; - surface->base.level = level; + surface->base.usage = surf_tmpl->usage; + surface->base.u.tex.level = level; + surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; + surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; surface->buffer = tex->buffer; + surface->cs_buffer = tex->cs_buffer; /* Prefer VRAM if there are multiple domains to choose from. */ surface->domain = tex->domain; if (surface->domain & R300_DOMAIN_VRAM) surface->domain &= ~R300_DOMAIN_GTT; - surface->offset = r300_texture_get_offset(&tex->desc, - level, zslice, face); + surface->offset = r300_texture_get_offset(&tex->desc, level, + surf_tmpl->u.tex.first_layer); surface->pitch = tex->fb_state.pitch[level]; surface->format = tex->fb_state.format; @@ -892,7 +899,7 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, tex->desc.b.b.nr_samples, tex->desc.microtile, tex->desc.macrotile[level], - DIM_HEIGHT); + DIM_HEIGHT, 0); surface->cbzb_height = align((surface->base.height + 1) / 2, tile_height); @@ -910,13 +917,13 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, else surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z; - SCREEN_DBG(r300_screen(screen), DBG_CBZB, - "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n", - surface->cbzb_allowed ? "YES" : " NO", - surface->cbzb_width, surface->cbzb_height, - offset & 2047, - tex->desc.microtile ? "YES" : " NO", - tex->desc.macrotile[level] ? "YES" : " NO"); + DBG(r300_context(ctx), DBG_CBZB, + "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n", + surface->cbzb_allowed ? "YES" : " NO", + surface->cbzb_width, surface->cbzb_height, + offset & 2047, + tex->desc.microtile ? "YES" : " NO", + tex->desc.macrotile[level] ? "YES" : " NO"); } return &surface->base; @@ -924,7 +931,7 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, /* Not required to implement u_resource_vtbl, consider moving to another file: */ -void r300_tex_surface_destroy(struct pipe_surface* s) +void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s) { pipe_resource_reference(&s->texture, NULL); FREE(s); diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index c4588a0c90b..0ab22f747e4 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -27,6 +27,7 @@ #include "pipe/p_format.h" struct pipe_screen; +struct pipe_context; struct pipe_resource; struct winsys_handle; struct r300_texture_format_state; @@ -35,11 +36,13 @@ struct r300_texture; struct r300_screen; unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, - const unsigned char *swizzle_view); + const unsigned char *swizzle_view, + boolean dxtc_swizzle); uint32_t r300_translate_texformat(enum pipe_format format, const unsigned char *swizzle_view, - boolean is_r500); + boolean is_r500, + boolean dxtc_swizzle); uint32_t r500_tx_format_msb_bit(enum pipe_format format); @@ -68,13 +71,10 @@ r300_texture_create(struct pipe_screen* screen, const struct pipe_resource* templ); -struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, - struct pipe_resource* texture, - unsigned face, - unsigned level, - unsigned zslice, - unsigned flags); +struct pipe_surface* r300_create_surface(struct pipe_context *ctx, + struct pipe_resource* texture, + const struct pipe_surface *surf_tmpl); -void r300_tex_surface_destroy(struct pipe_surface* s); +void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s); #endif /* R300_TEXTURE_H */ diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index 543d0fdc15b..7b1739142d4 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -34,7 +34,7 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, unsigned num_samples, enum r300_buffer_tiling microtile, enum r300_buffer_tiling macrotile, - enum r300_dim dim) + enum r300_dim dim, boolean is_rs690) { static const unsigned table[2][5][3][2] = { @@ -57,6 +57,7 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ } }; + static const unsigned aa_block[2] = {4, 8}; unsigned tile = 0; unsigned pixsize = util_format_get_blocksize(format); @@ -74,6 +75,14 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, } else { /* Standard alignment. */ tile = table[macrotile][util_logbase2(pixsize)][microtile][dim]; + if (macrotile == 0 && is_rs690 && dim == DIM_WIDTH) { + int align; + int h_tile; + h_tile = table[macrotile][util_logbase2(pixsize)][microtile][DIM_HEIGHT]; + align = 64 / (pixsize * h_tile); + if (tile < align) + tile = align; + } } assert(tile); @@ -89,7 +98,7 @@ static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, unsigned tile, texdim; tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, - desc->microtile, R300_BUFFER_TILED, dim); + desc->microtile, R300_BUFFER_TILED, dim, 0); if (dim == DIM_WIDTH) { texdim = u_minify(desc->width0, level); } else { @@ -113,6 +122,9 @@ static unsigned r300_texture_get_stride(struct r300_screen *screen, unsigned level) { unsigned tile_width, width, stride; + boolean is_rs690 = (screen->caps.family == CHIP_FAMILY_RS600 || + screen->caps.family == CHIP_FAMILY_RS690 || + screen->caps.family == CHIP_FAMILY_RS740); if (desc->stride_in_bytes_override) return desc->stride_in_bytes_override; @@ -131,38 +143,14 @@ static unsigned r300_texture_get_stride(struct r300_screen *screen, desc->b.b.nr_samples, desc->microtile, desc->macrotile[level], - DIM_WIDTH); + DIM_WIDTH, is_rs690); width = align(width, tile_width); stride = util_format_get_stride(desc->b.b.format, width); - - /* Some IGPs need a minimum stride of 64 bytes, hmm... */ - if (!desc->macrotile[level] && - (screen->caps.family == CHIP_FAMILY_RS600 || - screen->caps.family == CHIP_FAMILY_RS690 || - screen->caps.family == CHIP_FAMILY_RS740)) { - unsigned min_stride; - - if (desc->microtile) { - unsigned tile_height = - r300_get_pixel_alignment(desc->b.b.format, - desc->b.b.nr_samples, - desc->microtile, - desc->macrotile[level], - DIM_HEIGHT); - - min_stride = 64 / tile_height; - } else { - min_stride = 64; - } - - return stride < min_stride ? min_stride : stride; - } - /* The alignment to 32 bytes is sort of implied by the layout... */ return stride; } else { - return align(util_format_get_stride(desc->b.b.format, width), 32); + return align(util_format_get_stride(desc->b.b.format, width), is_rs690 ? 64 : 32); } } @@ -179,7 +167,7 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, desc->b.b.nr_samples, desc->microtile, desc->macrotile[level], - DIM_HEIGHT); + DIM_HEIGHT, 0); height = align(height, tile_height); /* This is needed for the kernel checker, unfortunately. */ @@ -474,22 +462,17 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, } unsigned r300_texture_get_offset(struct r300_texture_desc *desc, - unsigned level, unsigned zslice, - unsigned face) + unsigned level, unsigned layer) { unsigned offset = desc->offset_in_bytes[level]; switch (desc->b.b.target) { case PIPE_TEXTURE_3D: - assert(face == 0); - return offset + zslice * desc->layer_size_in_bytes[level]; - case PIPE_TEXTURE_CUBE: - assert(zslice == 0); - return offset + face * desc->layer_size_in_bytes[level]; + return offset + layer * desc->layer_size_in_bytes[level]; default: - assert(zslice == 0 && face == 0); + assert(layer == 0); return offset; } } diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h index 3d7fe1fb473..121d215b4cb 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.h +++ b/src/gallium/drivers/r300/r300_texture_desc.h @@ -41,7 +41,7 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, unsigned num_samples, enum r300_buffer_tiling microtile, enum r300_buffer_tiling macrotile, - enum r300_dim dim); + enum r300_dim dim, boolean is_rs690); boolean r300_texture_desc_init(struct r300_screen *rscreen, struct r300_texture_desc *desc, @@ -52,7 +52,6 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, unsigned max_buffer_size); unsigned r300_texture_get_offset(struct r300_texture_desc *desc, - unsigned level, unsigned zslice, - unsigned face); + unsigned level, unsigned layer); #endif diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index a4911b9a2a6..15a323989b2 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -57,7 +57,7 @@ static unsigned translate_opcode(unsigned opcode) /* case TGSI_OPCODE_DP2A: return RC_OPCODE_DP2A; */ /* gap */ case TGSI_OPCODE_FRC: return RC_OPCODE_FRC; - /* case TGSI_OPCODE_CLAMP: return RC_OPCODE_CLAMP; */ + case TGSI_OPCODE_CLAMP: return RC_OPCODE_CLAMP; case TGSI_OPCODE_FLR: return RC_OPCODE_FLR; /* case TGSI_OPCODE_ROUND: return RC_OPCODE_ROUND; */ case TGSI_OPCODE_EX2: return RC_OPCODE_EX2; @@ -363,10 +363,7 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, break; case TGSI_TOKEN_TYPE_INSTRUCTION: inst = &parser.FullToken.FullInstruction; - /* This hack with the RET opcode woudn't work with - * conditionals. */ - if (inst->Instruction.Opcode == TGSI_OPCODE_END || - inst->Instruction.Opcode == TGSI_OPCODE_RET) { + if (inst->Instruction.Opcode == TGSI_OPCODE_END) { break; } diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index e9333b35ef5..3b95af79bcf 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -27,6 +27,7 @@ #include "util/u_memory.h" #include "util/u_format.h" +#include "util/u_box.h" struct r300_transfer { /* Parent class */ @@ -52,16 +53,10 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, { struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - struct pipe_subresource subdst; - subdst.face = 0; - subdst.level = 0; - - ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, subdst, - 0, 0, 0, - tex, transfer->sr, - transfer->box.x, transfer->box.y, transfer->box.z, - transfer->box.width, transfer->box.height); + ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, 0, + 0, 0, 0, + tex, transfer->level, &transfer->box); } /* Copy a detiled texture to a tiled one. */ @@ -70,26 +65,22 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, { struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - struct pipe_subresource subsrc; - - subsrc.face = 0; - subsrc.level = 0; + struct pipe_box src_box; + u_box_origin_2d(transfer->box.width, transfer->box.height, &src_box); - ctx->resource_copy_region(ctx, tex, transfer->sr, - transfer->box.x, transfer->box.y, transfer->box.z, - &r300transfer->linear_texture->desc.b.b, subsrc, - 0, 0, 0, - transfer->box.width, transfer->box.height); + ctx->resource_copy_region(ctx, tex, transfer->level, + transfer->box.x, transfer->box.y, transfer->box.z, + &r300transfer->linear_texture->desc.b.b, 0, &src_box); ctx->flush(ctx, 0, NULL); } struct pipe_transfer* r300_texture_get_transfer(struct pipe_context *ctx, - struct pipe_resource *texture, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *texture, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct r300_context *r300 = r300_context(ctx); struct r300_texture *tex = r300_texture(texture); @@ -99,13 +90,13 @@ r300_texture_get_transfer(struct pipe_context *ctx, referenced_cs = r300->rws->cs_is_buffer_referenced(r300->cs, - tex->buffer, R300_REF_CS); + tex->cs_buffer, R300_REF_CS); if (referenced_cs) { referenced_hw = TRUE; } else { referenced_hw = r300->rws->cs_is_buffer_referenced(r300->cs, - tex->buffer, R300_REF_HW); + tex->cs_buffer, R300_REF_HW); } blittable = ctx->screen->is_format_supported( @@ -116,25 +107,27 @@ r300_texture_get_transfer(struct pipe_context *ctx, if (trans) { /* Initialize the transfer object. */ pipe_resource_reference(&trans->transfer.resource, texture); - trans->transfer.sr = sr; + trans->transfer.level = level; trans->transfer.usage = usage; trans->transfer.box = *box; /* If the texture is tiled, we must create a temporary detiled texture * for this transfer. * Also make write transfers pipelined. */ - if (tex->desc.microtile || tex->desc.macrotile[sr.level] || + if (tex->desc.microtile || tex->desc.macrotile[level] || ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) { base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; base.height0 = box->height; - base.depth0 = 0; + /* XXX: was depth0 = 0 */ + base.depth0 = 1; + base.array_size = 1; base.last_level = 0; base.nr_samples = 0; base.usage = PIPE_USAGE_DYNAMIC; base.bind = 0; - base.flags = R300_RESOURCE_FLAG_TRANSFER; + base.flags = R300_RESOURCE_FLAG_TRANSFER; /* For texture reading, the temporary (detiled) texture is used as * a render target when blitting from a tiled texture. */ @@ -164,7 +157,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, if (!trans->linear_texture) { /* For linear textures, it's safe to fallback to * an unpipelined transfer. */ - if (!tex->desc.microtile && !tex->desc.macrotile[sr.level]) { + if (!tex->desc.microtile && !tex->desc.macrotile[level]) { goto unpipelined; } @@ -182,7 +175,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, /* Set the stride. * * Even though we are using an internal texture for this, - * the transfer sr, box and usage parameters still reflect + * the transfer level, box and usage parameters still reflect * the arguments received to get_transfer. We just do the * right thing internally. */ @@ -202,9 +195,8 @@ r300_texture_get_transfer(struct pipe_context *ctx, unpipelined: /* Unpipelined transfer. */ - trans->transfer.stride = tex->desc.stride_in_bytes[sr.level]; - trans->offset = r300_texture_get_offset(&tex->desc, - sr.level, box->z, sr.face); + trans->transfer.stride = tex->desc.stride_in_bytes[level]; + trans->offset = r300_texture_get_offset(&tex->desc, level, box->z); if (referenced_cs) ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h index 0d32a68d1fa..7977ef516f2 100644 --- a/src/gallium/drivers/r300/r300_transfer.h +++ b/src/gallium/drivers/r300/r300_transfer.h @@ -30,22 +30,22 @@ struct r300_context; struct pipe_transfer* r300_texture_get_transfer(struct pipe_context *ctx, - struct pipe_resource *texture, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box); + struct pipe_resource *texture, + unsigned level, + unsigned usage, + const struct pipe_box *box); void r300_texture_transfer_destroy(struct pipe_context *ctx, - struct pipe_transfer *trans); + struct pipe_transfer *trans); void* r300_texture_transfer_map(struct pipe_context *ctx, - struct pipe_transfer *transfer); + struct pipe_transfer *transfer); void r300_texture_transfer_unmap(struct pipe_context *ctx, - struct pipe_transfer *transfer); + struct pipe_transfer *transfer); #endif diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 65696555ac3..78021e2c5d4 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -213,7 +213,6 @@ void r300_translate_vertex_shader(struct r300_context *r300, compiler.Base.max_temp_regs = 32; compiler.Base.max_constants = 256; compiler.Base.max_alu_insts = r300->screen->caps.is_r500 ? 1024 : 256; - compiler.Base.remove_unused_constants = TRUE; if (compiler.Base.Debug & RC_DBG_LOG) { DBG(r300, DBG_VP, "r300: Initial vertex program\n"); @@ -227,6 +226,10 @@ void r300_translate_vertex_shader(struct r300_context *r300, r300_tgsi_to_rc(&ttr, vs->state.tokens); + if (compiler.Base.Program.Constants.Count > 200) { + compiler.Base.remove_unused_constants = TRUE; + } + compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1)); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 4597332399a..0dd330d101f 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -33,15 +33,17 @@ #include "r300_defines.h" +#define R300_MAX_CMDBUF_DWORDS (16 * 1024) + struct winsys_handle; struct r300_winsys_screen; -struct r300_winsys_buffer; +struct r300_winsys_buffer; /* for map/unmap etc. */ +struct r300_winsys_cs_buffer; /* for write_reloc etc. */ struct r300_winsys_cs { - uint32_t *ptr; /* Pointer to the beginning of the CS. */ unsigned cdw; /* Number of used dwords. */ - unsigned ndw; /* Size of the CS in dwords. */ + uint32_t *buf; /* The command buffer. */ }; enum r300_value_id { @@ -102,6 +104,10 @@ struct r300_winsys_screen { unsigned usage, enum r300_buffer_domain domain); + struct r300_winsys_cs_buffer *(*buffer_get_cs_handle)( + struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf); + /** * Reference a buffer object (assign with reference counting). * @@ -242,7 +248,7 @@ struct r300_winsys_screen { * of the R300_DOMAIN_* flags. */ void (*cs_add_buffer)(struct r300_winsys_cs *cs, - struct r300_winsys_buffer *buf, + struct r300_winsys_cs_buffer *buf, enum r300_buffer_domain rd, enum r300_buffer_domain wd); @@ -263,7 +269,7 @@ struct r300_winsys_screen { * \param wd A write domain containing a bitmask of the R300_DOMAIN_* flags. */ void (*cs_write_reloc)(struct r300_winsys_cs *cs, - struct r300_winsys_buffer *buf, + struct r300_winsys_cs_buffer *buf, enum r300_buffer_domain rd, enum r300_buffer_domain wd); @@ -303,7 +309,7 @@ struct r300_winsys_screen { * \param domain A bitmask of the R300_REF_* enums. */ boolean (*cs_is_buffer_referenced)(struct r300_winsys_cs *cs, - struct r300_winsys_buffer *buf, + struct r300_winsys_cs_buffer *buf, enum r300_reference_domain domain); }; diff --git a/src/gallium/drivers/r600/Makefile b/src/gallium/drivers/r600/Makefile index a484f38e9f1..b476b9af3b8 100644 --- a/src/gallium/drivers/r600/Makefile +++ b/src/gallium/drivers/r600/Makefile @@ -21,6 +21,7 @@ C_SOURCES = \ evergreen_state.c \ eg_asm.c \ r600_translate.c \ - r600_state_common.c + r600_state_common.c \ + r600_upload.c include ../../Makefile.template diff --git a/src/gallium/drivers/r600/SConscript b/src/gallium/drivers/r600/SConscript index 3fc1fa94c27..64980140963 100644 --- a/src/gallium/drivers/r600/SConscript +++ b/src/gallium/drivers/r600/SConscript @@ -28,6 +28,7 @@ r600 = env.ConvenienceLibrary( 'r600_state_common.c', 'r600_texture.c', 'r600_translate.c', + 'r600_upload.c', 'r700_asm.c', 'evergreen_state.c', 'eg_asm.c', diff --git a/src/gallium/drivers/r600/eg_asm.c b/src/gallium/drivers/r600/eg_asm.c index c30f09c394b..b79875c7c75 100644 --- a/src/gallium/drivers/r600/eg_asm.c +++ b/src/gallium/drivers/r600/eg_asm.c @@ -27,6 +27,7 @@ #include "r600_asm.h" #include "eg_sq.h" #include "r600_opcodes.h" +#include "evergreend.h" int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) { @@ -74,6 +75,8 @@ int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) case EG_V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END: case EG_V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: case EG_V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK: + case EG_V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: + case EG_V_SQ_CF_WORD1_SQ_CF_INST_RETURN: bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->cf_addr >> 1); bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) | S_SQ_CF_WORD1_BARRIER(1) | @@ -87,3 +90,37 @@ int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) } return 0; } + +void eg_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) +{ + struct r600_pipe_state *rstate; + unsigned i = 0; + + if (count > 8) { + bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(EG_V_SQ_CF_WORD1_SQ_CF_INST_VTX) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(8 - 1); + bytecode[i++] = S_SQ_CF_WORD0_ADDR(40 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(EG_V_SQ_CF_WORD1_SQ_CF_INST_VTX) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(count - 8 - 1); + } else { + bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(EG_V_SQ_CF_WORD1_SQ_CF_INST_VTX) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(count - 1); + } + bytecode[i++] = S_SQ_CF_WORD0_ADDR(0); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(EG_V_SQ_CF_WORD1_SQ_CF_INST_RETURN) | + S_SQ_CF_WORD1_BARRIER(1); + + rstate = &ve->rstate; + rstate->id = R600_PIPE_STATE_FETCH_SHADER; + rstate->nregs = 0; + r600_pipe_state_add_reg(rstate, R_0288A8_SQ_PGM_RESOURCES_FS, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_0288A4_SQ_PGM_START_FS, + (r600_bo_offset(ve->fetch_shader)) >> 8, + 0xFFFFFFFF, ve->fetch_shader); +} diff --git a/src/gallium/drivers/r600/eg_state_inlines.h b/src/gallium/drivers/r600/eg_state_inlines.h index 59641976403..ecea1db4f15 100644 --- a/src/gallium/drivers/r600/eg_state_inlines.h +++ b/src/gallium/drivers/r600/eg_state_inlines.h @@ -290,6 +290,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) switch (format) { /* 8-bit buffers. */ case PIPE_FORMAT_A8_UNORM: + return V_028C70_SWAP_ALT_REV; case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: case PIPE_FORMAT_R8_UNORM: @@ -311,6 +312,8 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) case PIPE_FORMAT_Z16_UNORM: return V_028C70_SWAP_STD; + case PIPE_FORMAT_L8A8_UNORM: + return V_028C70_SWAP_ALT; case PIPE_FORMAT_R8G8_UNORM: return V_028C70_SWAP_STD; @@ -400,6 +403,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_Z16_UNORM: return V_028C70_COLOR_16; + case PIPE_FORMAT_L8A8_UNORM: case PIPE_FORMAT_R8G8_UNORM: return V_028C70_COLOR_8_8; @@ -447,8 +451,10 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) return V_028C70_COLOR_16_16; /* 64-bit buffers. */ - case PIPE_FORMAT_R16G16B16A16_SSCALED: + case PIPE_FORMAT_R16G16B16_USCALED: + case PIPE_FORMAT_R16G16B16A16_USCALED: case PIPE_FORMAT_R16G16B16_SSCALED: + case PIPE_FORMAT_R16G16B16A16_SSCALED: case PIPE_FORMAT_R16G16B16A16_UNORM: case PIPE_FORMAT_R16G16B16A16_SNORM: return V_028C70_COLOR_16_16_16_16; @@ -460,6 +466,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_R32G32_FLOAT: return V_028C70_COLOR_32_32_FLOAT; + case PIPE_FORMAT_R32G32_USCALED: case PIPE_FORMAT_R32G32_SSCALED: return V_028C70_COLOR_32_32; @@ -634,38 +641,4 @@ out_unknown: return ~0; } -static INLINE uint32_t r600_translate_vertex_data_swizzle(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - unsigned i; - uint32_t word3; - - assert(format); - - if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { - fprintf(stderr, "r600: Bad format %s in %s:%d\n", - util_format_short_name(format), __FUNCTION__, __LINE__); - return 0; - } - - word3 = 0; - for (i = 0; i < desc->nr_channels; i++) { - switch (i) { - case 0: - word3 |= S_03000C_DST_SEL_X(desc->swizzle[0]); - break; - case 1: - word3 |= S_03000C_DST_SEL_Y(desc->swizzle[1]); - break; - case 2: - word3 |= S_03000C_DST_SEL_Z(desc->swizzle[2]); - break; - case 3: - word3 |= S_03000C_DST_SEL_W(desc->swizzle[3]); - break; - } - } - return word3; -} - #endif diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 4725b5e75e2..07496ebf51e 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -323,11 +323,11 @@ static void *evergreen_create_sampler_state(struct pipe_context *ctx, S_03C000_BORDER_COLOR_TYPE(uc.ui ? V_03C000_SQ_TEX_BORDER_COLOR_REGISTER : 0), 0xFFFFFFFF, NULL); /* FIXME LOD it depends on texture base level ... */ r600_pipe_state_add_reg(rstate, R_03C004_SQ_TEX_SAMPLER_WORD1_0, - S_03C004_MIN_LOD(S_FIXED(CLAMP(state->min_lod, 0, 15), 6)) | - S_03C004_MAX_LOD(S_FIXED(CLAMP(state->max_lod, 0, 15), 6)), + S_03C004_MIN_LOD(S_FIXED(CLAMP(state->min_lod, 0, 15), 8)) | + S_03C004_MAX_LOD(S_FIXED(CLAMP(state->max_lod, 0, 15), 8)), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_03C008_SQ_TEX_SAMPLER_WORD2_0, - S_03C008_LOD_BIAS(S_FIXED(CLAMP(state->lod_bias, -16, 16), 6)) | + S_03C008_LOD_BIAS(S_FIXED(CLAMP(state->lod_bias, -16, 16), 8)) | S_03C008_TYPE(1), 0xFFFFFFFF, NULL); @@ -410,9 +410,9 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4, word4 | S_030010_NUM_FORMAT_ALL(V_030010_SQ_NUM_FORMAT_NORM) | S_030010_SRF_MODE_ALL(V_030010_SFR_MODE_NO_ZERO) | - S_030010_BASE_LEVEL(state->first_level), 0xFFFFFFFF, NULL); + S_030010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5, - S_030014_LAST_LEVEL(state->last_level) | + S_030014_LAST_LEVEL(state->u.tex.last_level) | S_030014_BASE_ARRAY(0) | S_030014_LAST_ARRAY(0), 0xffffffff, NULL); r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6, 0x0, 0xFFFFFFFF, NULL); @@ -431,7 +431,7 @@ static void evergreen_set_vs_sampler_view(struct pipe_context *ctx, unsigned cou for (int i = 0; i < count; i++) { if (resource[i]) { - evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state, i + PIPE_MAX_ATTRIBS); + evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state, i); } } } @@ -501,16 +501,16 @@ static void evergreen_set_clip_state(struct pipe_context *ctx, rstate->id = R600_PIPE_STATE_CLIP; for (int i = 0; i < state->nr; i++) { r600_pipe_state_add_reg(rstate, - R_0285BC_PA_CL_UCP0_X + i * 4, + R_0285BC_PA_CL_UCP0_X + i * 16, fui(state->ucp[i][0]), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_0285C0_PA_CL_UCP0_Y + i * 4, + R_0285C0_PA_CL_UCP0_Y + i * 16, fui(state->ucp[i][1]) , 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_0285C4_PA_CL_UCP0_Z + i * 4, + R_0285C4_PA_CL_UCP0_Z + i * 16, fui(state->ucp[i][2]), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_0285C8_PA_CL_UCP0_W + i * 4, + R_0285C8_PA_CL_UCP0_W + i * 16, fui(state->ucp[i][3]), 0xFFFFFFFF, NULL); } r600_pipe_state_add_reg(rstate, R_028810_PA_CL_CLIP_CNTL, @@ -633,10 +633,11 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state struct r600_resource_texture *rtex; struct r600_resource *rbuffer; struct r600_surface *surf; - unsigned level = state->cbufs[cb]->level; + unsigned level = state->cbufs[cb]->u.tex.level; unsigned pitch, slice; unsigned color_info; unsigned format, swap, ntype; + unsigned offset; const struct util_format_description *desc; struct r600_bo *bo[3]; @@ -647,6 +648,9 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state bo[1] = rbuffer->bo; bo[2] = rbuffer->bo; + /* XXX quite sure for dx10+ hw don't need any offset hacks */ + offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture, + level, state->cbufs[cb]->u.tex.first_layer); pitch = rtex->pitch_in_pixels[level] / 8 - 1; slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; ntype = 0; @@ -660,13 +664,13 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state S_028C70_COMP_SWAP(swap) | S_028C70_BLEND_CLAMP(1) | S_028C70_NUMBER_TYPE(ntype); - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) + if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) color_info |= S_028C70_SOURCE_FORMAT(1); /* FIXME handle enabling of CB beyond BASE8 which has different offset */ r600_pipe_state_add_reg(rstate, R_028C60_CB_COLOR0_BASE + cb * 0x3C, - (state->cbufs[cb]->offset + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]); + (offset + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]); r600_pipe_state_add_reg(rstate, R_028C78_CB_COLOR0_DIM + cb * 0x3C, 0x0, 0xFFFFFFFF, NULL); @@ -698,11 +702,12 @@ static void evergreen_db(struct r600_pipe_context *rctx, struct r600_pipe_state struct r600_surface *surf; unsigned level; unsigned pitch, slice, format, stencil_format; + unsigned offset; if (state->zsbuf == NULL) return; - level = state->zsbuf->level; + level = state->zsbuf->u.tex.level; surf = (struct r600_surface *)state->zsbuf; rtex = (struct r600_resource_texture*)state->zsbuf->texture; @@ -712,24 +717,27 @@ static void evergreen_db(struct r600_pipe_context *rctx, struct r600_pipe_state rtex->depth = 1; rbuffer = &rtex->resource; + /* XXX quite sure for dx10+ hw don't need any offset hacks */ + offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, + level, state->zsbuf->u.tex.first_layer); pitch = rtex->pitch_in_pixels[level] / 8 - 1; slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; format = r600_translate_dbformat(state->zsbuf->texture->format); stencil_format = r600_translate_stencilformat(state->zsbuf->texture->format); r600_pipe_state_add_reg(rstate, R_028048_DB_Z_READ_BASE, - (state->zsbuf->offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); + (offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); r600_pipe_state_add_reg(rstate, R_028050_DB_Z_WRITE_BASE, - (state->zsbuf->offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); + (offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); if (stencil_format) { uint32_t stencil_offset; stencil_offset = ((surf->aligned_height * rtex->pitch_in_bytes[level]) + 255) & ~255; r600_pipe_state_add_reg(rstate, R_02804C_DB_STENCIL_READ_BASE, - (state->zsbuf->offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); + (offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE, - (state->zsbuf->offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); + (offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); } r600_pipe_state_add_reg(rstate, R_028008_DB_DEPTH_VIEW, 0x00000000, 0xFFFFFFFF, NULL); @@ -825,6 +833,10 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx, free(rctx->states[R600_PIPE_STATE_FRAMEBUFFER]); rctx->states[R600_PIPE_STATE_FRAMEBUFFER] = rstate; r600_context_pipe_state_set(&rctx->ctx, rstate); + + if (state->zsbuf) { + evergreen_polygon_offset_update(rctx); + } } static void evergreen_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, @@ -1036,11 +1048,33 @@ void evergreen_init_config(struct r600_pipe_context *rctx) num_hs_stack_entries = 85; num_ls_stack_entries = 85; break; + case CHIP_PALM: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 16; + num_gs_threads = 16; + num_es_threads = 16; + num_hs_threads = 16; + num_ls_threads = 16; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; } tmp = 0x00000000; switch (family) { case CHIP_CEDAR: + case CHIP_PALM: break; default: tmp |= S_008C00_VC_ENABLE(1); @@ -1172,29 +1206,101 @@ void evergreen_init_config(struct r600_pipe_context *rctx) r600_pipe_state_add_reg(rstate, R_0283F8_SQ_VTX_SEMANTIC_30, 0x0, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_0283FC_SQ_VTX_SEMANTIC_31, 0x0, 0xFFFFFFFF, NULL); -r600_pipe_state_add_reg(rstate, R_028810_PA_CL_CLIP_CNTL, - 0x0, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_028810_PA_CL_CLIP_CNTL, 0x0, 0xFFFFFFFF, NULL); r600_context_pipe_state_set(&rctx->ctx, rstate); } -int r600_conv_pipe_prim(unsigned pprim, unsigned *prim); -void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) +void evergreen_polygon_offset_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_state state; + + state.id = R600_PIPE_STATE_POLYGON_OFFSET; + state.nregs = 0; + if (rctx->rasterizer && rctx->framebuffer.zsbuf) { + float offset_units = rctx->rasterizer->offset_units; + unsigned offset_db_fmt_cntl = 0, depth; + + switch (rctx->framebuffer.zsbuf->texture->format) { + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + depth = -24; + offset_units *= 2.0f; + break; + case PIPE_FORMAT_Z32_FLOAT: + depth = -23; + offset_units *= 1.0f; + offset_db_fmt_cntl |= S_028B78_POLY_OFFSET_DB_IS_FLOAT_FMT(1); + break; + case PIPE_FORMAT_Z16_UNORM: + depth = -16; + offset_units *= 4.0f; + break; + default: + return; + } + /* FIXME some of those reg can be computed with cso */ + offset_db_fmt_cntl |= S_028B78_POLY_OFFSET_NEG_NUM_DB_BITS(depth); + r600_pipe_state_add_reg(&state, + R_028B80_PA_SU_POLY_OFFSET_FRONT_SCALE, + fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028B84_PA_SU_POLY_OFFSET_FRONT_OFFSET, + fui(offset_units), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028B88_PA_SU_POLY_OFFSET_BACK_SCALE, + fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028B8C_PA_SU_POLY_OFFSET_BACK_OFFSET, + fui(offset_units), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028B78_PA_SU_POLY_OFFSET_DB_FMT_CNTL, + offset_db_fmt_cntl, 0xFFFFFFFF, NULL); + r600_context_pipe_state_set(&rctx->ctx, &state); + } +} + +static void evergreen_spi_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_shader *shader = rctx->ps_shader; + struct r600_pipe_state rstate; + struct r600_shader *rshader = &shader->shader; + unsigned i, tmp; + + rstate.nregs = 0; + for (i = 0; i < rshader->ninput; i++) { + tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i)); + if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || + rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || + rshader->input[i].name == TGSI_SEMANTIC_POSITION) { + tmp |= S_028644_FLAT_SHADE(rctx->flatshade); + } + if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && + rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { + tmp |= S_028644_PT_SPRITE_TEX(1); + } + r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL); + } + r600_context_pipe_state_set(&rctx->ctx, &rstate); +} + +void evergreen_vertex_buffer_update(struct r600_pipe_context *rctx) { - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_pipe_state *rstate; struct r600_resource *rbuffer; - unsigned i, j, offset, prim; - u32 vgt_dma_index_type, vgt_draw_initiator, mask; struct pipe_vertex_buffer *vertex_buffer; - struct r600_draw rdraw; - struct r600_pipe_state vgt; - struct r600_drawl draw; - boolean translate = FALSE; + unsigned i, offset; + + /* we don't update until we know vertex elements */ + if (rctx->vertex_elements == NULL || !rctx->nvertex_buffer) + return; if (rctx->vertex_elements->incompatible_layout) { + /* translate rebind new vertex elements so + * return once translated + */ r600_begin_vertex_translate(rctx); - translate = TRUE; + return; } if (rctx->any_user_vbs) { @@ -1202,6 +1308,72 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) rctx->any_user_vbs = FALSE; } + if (rctx->vertex_elements->vbuffer_need_offset) { + /* one resource per vertex elements */ + rctx->nvs_resource = rctx->vertex_elements->count; + } else { + /* bind vertex buffer once */ + rctx->nvs_resource = rctx->nvertex_buffer; + } + + for (i = 0 ; i < rctx->nvs_resource; i++) { + rstate = &rctx->vs_resource[i]; + rstate->id = R600_PIPE_STATE_RESOURCE; + rstate->nregs = 0; + + if (rctx->vertex_elements->vbuffer_need_offset) { + /* one resource per vertex elements */ + unsigned vbuffer_index; + vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index; + vertex_buffer = &rctx->vertex_buffer[vbuffer_index]; + rbuffer = (struct r600_resource*)vertex_buffer->buffer; + offset = rctx->vertex_elements->vbuffer_offset[i] + + vertex_buffer->buffer_offset + + r600_bo_offset(rbuffer->bo); + } else { + /* bind vertex buffer once */ + vertex_buffer = &rctx->vertex_buffer[i]; + rbuffer = (struct r600_resource*)vertex_buffer->buffer; + offset = vertex_buffer->buffer_offset + + r600_bo_offset(rbuffer->bo); + } + + r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0, + offset, 0xFFFFFFFF, rbuffer->bo); + r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1, + rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2, + S_030008_STRIDE(vertex_buffer->stride), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3, + S_03000C_DST_SEL_X(V_03000C_SQ_SEL_X) | + S_03000C_DST_SEL_Y(V_03000C_SQ_SEL_Y) | + S_03000C_DST_SEL_Z(V_03000C_SQ_SEL_Z) | + S_03000C_DST_SEL_W(V_03000C_SQ_SEL_W), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_03001C_RESOURCE0_WORD7, + 0xC0000000, 0xFFFFFFFF, NULL); + evergreen_fs_resource_set(&rctx->ctx, rstate, i); + } +} + +int r600_conv_pipe_prim(unsigned pprim, unsigned *prim); +void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) +{ + struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + struct r600_resource *rbuffer; + u32 vgt_dma_index_type, vgt_draw_initiator, mask; + struct r600_draw rdraw; + struct r600_pipe_state vgt; + struct r600_drawl draw; + unsigned prim; + memset(&draw, 0, sizeof(struct r600_drawl)); draw.ctx = ctx; draw.mode = info->mode; @@ -1250,45 +1422,23 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) } if (r600_conv_pipe_prim(draw.mode, &prim)) return; - - /* rebuild vertex shader if input format changed */ - if (r600_pipe_shader_update(&rctx->context, rctx->vs_shader)) + if (unlikely(rctx->ps_shader == NULL)) { + R600_ERR("missing vertex shader\n"); return; - if (r600_pipe_shader_update(&rctx->context, rctx->ps_shader)) + } + if (unlikely(rctx->vs_shader == NULL)) { + R600_ERR("missing vertex shader\n"); + return; + } + /* there should be enough input */ + if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) { + R600_ERR("%d resources provided, expecting %d\n", + rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource); return; - - for (i = 0 ; i < rctx->vertex_elements->count; i++) { - uint32_t word3, word2; - uint32_t format; - rstate = &rctx->vs_resource[i]; - - rstate->id = R600_PIPE_STATE_RESOURCE; - rstate->nregs = 0; - - j = rctx->vertex_elements->elements[i].vertex_buffer_index; - vertex_buffer = &rctx->vertex_buffer[j]; - rbuffer = (struct r600_resource*)vertex_buffer->buffer; - offset = rctx->vertex_elements->elements[i].src_offset + - vertex_buffer->buffer_offset + - r600_bo_offset(rbuffer->bo); - - format = r600_translate_vertex_data_type(rctx->vertex_elements->hw_format[i]); - - word2 = format | S_030008_STRIDE(vertex_buffer->stride); - - word3 = r600_translate_vertex_data_swizzle(rctx->vertex_elements->hw_format[i]); - - r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0, offset, 0xFFFFFFFF, rbuffer->bo); - r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1, rbuffer->size - offset - 1, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2, word2, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3, word3, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4, 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5, 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6, 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_03001C_RESOURCE0_WORD7, 0xC0000000, 0xFFFFFFFF, NULL); - evergreen_vs_resource_set(&rctx->ctx, rstate, i); } + evergreen_spi_update(rctx); + mask = 0; for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) { mask |= (0xF << (i * 4)); @@ -1303,46 +1453,6 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) r600_pipe_state_add_reg(&vgt, R_028404_VGT_MIN_VTX_INDX, draw.min_index, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL); - - if (rctx->rasterizer && rctx->framebuffer.zsbuf) { - float offset_units = rctx->rasterizer->offset_units; - unsigned offset_db_fmt_cntl = 0, depth; - - switch (rctx->framebuffer.zsbuf->texture->format) { - case PIPE_FORMAT_Z24X8_UNORM: - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - depth = -24; - offset_units *= 2.0f; - break; - case PIPE_FORMAT_Z32_FLOAT: - depth = -23; - offset_units *= 1.0f; - offset_db_fmt_cntl |= S_028B78_POLY_OFFSET_DB_IS_FLOAT_FMT(1); - break; - case PIPE_FORMAT_Z16_UNORM: - depth = -16; - offset_units *= 4.0f; - break; - default: - return; - } - offset_db_fmt_cntl |= S_028B78_POLY_OFFSET_NEG_NUM_DB_BITS(depth); - r600_pipe_state_add_reg(&vgt, - R_028B80_PA_SU_POLY_OFFSET_FRONT_SCALE, - fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028B84_PA_SU_POLY_OFFSET_FRONT_OFFSET, - fui(offset_units), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028B88_PA_SU_POLY_OFFSET_BACK_SCALE, - fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028B8C_PA_SU_POLY_OFFSET_BACK_OFFSET, - fui(offset_units), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028B78_PA_SU_POLY_OFFSET_DB_FMT_CNTL, - offset_db_fmt_cntl, 0xFFFFFFFF, NULL); - } r600_context_pipe_state_set(&rctx->ctx, &vgt); rdraw.vgt_num_indices = draw.count; @@ -1357,28 +1467,22 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) } evergreen_context_draw(&rctx->ctx, &rdraw); - if (translate) - r600_end_vertex_translate(rctx); - pipe_resource_reference(&draw.index_buffer, NULL); } void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader) { - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_pipe_state *rstate = &shader->rstate; struct r600_shader *rshader = &shader->shader; - unsigned i, tmp, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1; + unsigned i, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1; int pos_index = -1, face_index = -1; int ninterp = 0; boolean have_linear = FALSE, have_centroid = FALSE, have_perspective = FALSE; unsigned spi_baryc_cntl; - /* clear previous register */ rstate->nregs = 0; for (i = 0; i < rshader->ninput; i++) { - tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i)); /* evergreen NUM_INTERP only contains values interpolated into the LDS, POSITION goes via GPRs from the SC so isn't counted */ if (rshader->input[i].name == TGSI_SEMANTIC_POSITION) @@ -1396,16 +1500,6 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader if (rshader->input[i].centroid) have_centroid = TRUE; } - if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || - rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || - rshader->input[i].name == TGSI_SEMANTIC_POSITION) { - tmp |= S_028644_FLAT_SHADE(rshader->flat_shade); - } - if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && - rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { - tmp |= S_028644_PT_SPRITE_TEX(1); - } - r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL); } for (i = 0; i < rshader->noutput; i++) { if (rshader->output[i].name == TGSI_SEMANTIC_POSITION) @@ -1464,8 +1558,8 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader S_0286E0_PERSP_CENTROID_ENA(have_centroid); if (have_linear) spi_baryc_cntl |= S_0286E0_LINEAR_CENTER_ENA(1) | - S_0286E0_LINEAR_CENTROID_ENA(have_centroid); - + S_0286E0_LINEAR_CENTROID_ENA(have_centroid); + r600_pipe_state_add_reg(rstate, R_0286CC_SPI_PS_IN_CONTROL_0, spi_ps_in_control_0, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_0286D0_SPI_PS_IN_CONTROL_1, @@ -1544,14 +1638,8 @@ void evergreen_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader R_028864_SQ_PGM_RESOURCES_2_VS, 0x0, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_0288A8_SQ_PGM_RESOURCES_FS, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_02885C_SQ_PGM_START_VS, (r600_bo_offset(shader->bo)) >> 8, 0xFFFFFFFF, shader->bo); - r600_pipe_state_add_reg(rstate, - R_0288A4_SQ_PGM_START_FS, - (r600_bo_offset(shader->bo)) >> 8, 0xFFFFFFFF, shader->bo); r600_pipe_state_add_reg(rstate, R_03A200_SQ_LOOP_CONST_0 + (32 * 4), 0x01000FFF, diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h index a337916c098..e67254b2560 100644 --- a/src/gallium/drivers/r600/evergreend.h +++ b/src/gallium/drivers/r600/evergreend.h @@ -45,6 +45,15 @@ #define EVENT_TYPE_ZPASS_DONE 0x15 #define EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT 0x16 +#define EVENT_TYPE(x) ((x) << 0) +#define EVENT_INDEX(x) ((x) << 8) + /* 0 - any non-TS event + * 1 - ZPASS_DONE + * 2 - SAMPLE_PIPELINESTAT + * 3 - SAMPLE_STREAMOUTSTAT* + * 4 - *S_PARTIAL_FLUSH + * 5 - TS events + */ #define R600_TEXEL_PITCH_ALIGNMENT_MASK 0x7 diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h index 17858b2d381..aa456d493f7 100644 --- a/src/gallium/drivers/r600/r600.h +++ b/src/gallium/drivers/r600/r600.h @@ -91,6 +91,7 @@ enum radeon_family { CHIP_JUNIPER, CHIP_CYPRESS, CHIP_HEMLOCK, + CHIP_PALM, CHIP_LAST, }; @@ -264,6 +265,7 @@ void r600_context_fini(struct r600_context *ctx); void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_state *state); void r600_context_pipe_state_set_ps_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); void r600_context_pipe_state_set_vs_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); +void r600_context_pipe_state_set_fs_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); void r600_context_pipe_state_set_ps_sampler(struct r600_context *ctx, struct r600_pipe_state *state, unsigned id); void r600_context_pipe_state_set_vs_sampler(struct r600_context *ctx, struct r600_pipe_state *state, unsigned id); void r600_context_flush(struct r600_context *ctx); @@ -284,10 +286,14 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon); void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *draw); void evergreen_ps_resource_set(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); void evergreen_vs_resource_set(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); +void evergreen_fs_resource_set(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); void evergreen_context_pipe_state_set_ps_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); void evergreen_context_pipe_state_set_vs_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); +void evergreen_context_pipe_state_set_fs_resource(struct r600_context *ctx, struct r600_pipe_state *state, unsigned rid); void evergreen_context_pipe_state_set_ps_sampler(struct r600_context *ctx, struct r600_pipe_state *state, unsigned id); void evergreen_context_pipe_state_set_vs_sampler(struct r600_context *ctx, struct r600_pipe_state *state, unsigned id); +struct radeon *radeon_decref(struct radeon *radeon); + #endif diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c index 8a7f3ce575c..1f41269534a 100644 --- a/src/gallium/drivers/r600/r600_asm.c +++ b/src/gallium/drivers/r600/r600_asm.c @@ -22,11 +22,15 @@ */ #include <stdio.h> #include <errno.h> +#include "util/u_format.h" #include "util/u_memory.h" +#include "pipe/p_shader_tokens.h" #include "r600_pipe.h" #include "r600_sq.h" #include "r600_opcodes.h" #include "r600_asm.h" +#include "r600_formats.h" +#include "r600d.h" static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu) { @@ -55,8 +59,8 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu) case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4_IEEE: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE: - return 2; - + return 2; + case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR: case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT: @@ -74,7 +78,7 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu) default: R600_ERR( "Need instruction operand number for 0x%x.\n", alu->inst); }; - + return 3; } @@ -137,20 +141,21 @@ int r600_bc_init(struct r600_bc *bc, enum radeon_family family) case CHIP_RV635: case CHIP_RS780: case CHIP_RS880: - bc->chiprev = 0; + bc->chiprev = CHIPREV_R600; break; case CHIP_RV770: case CHIP_RV730: case CHIP_RV710: case CHIP_RV740: - bc->chiprev = 1; + bc->chiprev = CHIPREV_R700; break; case CHIP_CEDAR: case CHIP_REDWOOD: case CHIP_JUNIPER: case CHIP_CYPRESS: case CHIP_HEMLOCK: - bc->chiprev = 2; + case CHIP_PALM: + bc->chiprev = CHIPREV_EVERGREEN; break; default: R600_ERR("unknown family %d\n", bc->family); @@ -199,9 +204,9 @@ const unsigned bank_swizzle_vec[8] = {SQ_ALU_VEC_210, //000 SQ_ALU_VEC_012}; //111 const unsigned bank_swizzle_scl[8] = {SQ_ALU_SCL_210, //000 - SQ_ALU_SCL_122, //001 + SQ_ALU_SCL_122, //001 SQ_ALU_SCL_122, //010 - + SQ_ALU_SCL_221, //011 SQ_ALU_SCL_212, //100 SQ_ALU_SCL_122, //101 @@ -592,10 +597,34 @@ int r600_bc_add_cfinst(struct r600_bc *bc, int inst) /* common to all 3 families */ static int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsigned id) { - bc->bytecode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vtx->buffer_id) | - S_SQ_VTX_WORD0_SRC_GPR(vtx->src_gpr) | - S_SQ_VTX_WORD0_SRC_SEL_X(vtx->src_sel_x) | - S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(vtx->mega_fetch_count); + unsigned fetch_resource_start = 0; + + /* check if we are fetch shader */ + /* fetch shader can also access vertex resource, + * first fetch shader resource is at 160 + */ + if (bc->type == -1) { + switch (bc->chiprev) { + /* r600 */ + case CHIPREV_R600: + /* r700 */ + case CHIPREV_R700: + fetch_resource_start = 160; + break; + /* evergreen */ + case CHIPREV_EVERGREEN: + fetch_resource_start = 0; + break; + default: + fprintf(stderr, "%s:%s:%d unknown chiprev %d\n", + __FILE__, __func__, __LINE__, bc->chiprev); + break; + } + } + bc->bytecode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vtx->buffer_id + fetch_resource_start) | + S_SQ_VTX_WORD0_SRC_GPR(vtx->src_gpr) | + S_SQ_VTX_WORD0_SRC_SEL_X(vtx->src_sel_x) | + S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(vtx->mega_fetch_count); bc->bytecode[id++] = S_SQ_VTX_WORD1_DST_SEL_X(vtx->dst_sel_x) | S_SQ_VTX_WORD1_DST_SEL_Y(vtx->dst_sel_y) | S_SQ_VTX_WORD1_DST_SEL_Z(vtx->dst_sel_z) | @@ -678,8 +707,8 @@ static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsign S_SQ_ALU_WORD1_OP2_WRITE_MASK(alu->dst.write) | S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) | S_SQ_ALU_WORD1_BANK_SWIZZLE(alu->bank_swizzle) | - S_SQ_ALU_WORD1_OP2_UPDATE_EXECUTE_MASK(alu->predicate) | - S_SQ_ALU_WORD1_OP2_UPDATE_PRED(alu->predicate); + S_SQ_ALU_WORD1_OP2_UPDATE_EXECUTE_MASK(alu->predicate) | + S_SQ_ALU_WORD1_OP2_UPDATE_PRED(alu->predicate); } if (alu->last) { if (alu->nliteral && !alu->literal_added) { @@ -710,7 +739,7 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) S_SQ_CF_ALU_WORD1_KCACHE_ADDR0(cf->kcache0_addr) | S_SQ_CF_ALU_WORD1_KCACHE_ADDR1(cf->kcache1_addr) | S_SQ_CF_ALU_WORD1_BARRIER(1) | - S_SQ_CF_ALU_WORD1_USES_WATERFALL(bc->chiprev == 0 ? cf->r6xx_uses_waterfall : 0) | + S_SQ_CF_ALU_WORD1_USES_WATERFALL(bc->chiprev == CHIPREV_R600 ? cf->r6xx_uses_waterfall : 0) | S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1); break; case V_SQ_CF_WORD1_SQ_CF_INST_TEX: @@ -742,6 +771,8 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf) case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END: case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK: + case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: + case V_SQ_CF_WORD1_SQ_CF_INST_RETURN: bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->cf_addr >> 1); bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) | S_SQ_CF_WORD1_BARRIER(1) | @@ -766,7 +797,10 @@ int r600_bc_build(struct r600_bc *bc) int r; if (bc->callstack[0].max > 0) - bc->nstack = ((bc->callstack[0].max + 3) >> 2) + 2; + bc->nstack = ((bc->callstack[0].max + 3) >> 2) + 2; + if (bc->type == TGSI_PROCESSOR_VERTEX && !bc->nstack) { + bc->nstack = 1; + } /* first path compute addr of each CF block */ /* addr start after all the CF instructions */ @@ -795,6 +829,8 @@ int r600_bc_build(struct r600_bc *bc) case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END: case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK: + case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: + case V_SQ_CF_WORD1_SQ_CF_INST_RETURN: break; default: R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst); @@ -810,7 +846,7 @@ int r600_bc_build(struct r600_bc *bc) return -ENOMEM; LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) { addr = cf->addr; - if (bc->chiprev == 2) + if (bc->chiprev == CHIPREV_EVERGREEN) r = eg_bc_cf_build(bc, cf); else r = r600_bc_cf_build(bc, cf); @@ -821,11 +857,11 @@ int r600_bc_build(struct r600_bc *bc) case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3): LIST_FOR_EACH_ENTRY(alu, &cf->alu, list) { switch(bc->chiprev) { - case 0: + case CHIPREV_R600: r = r600_bc_alu_build(bc, alu, addr); break; - case 1: - case 2: /* eg alu is same encoding as r700 */ + case CHIPREV_R700: + case CHIPREV_EVERGREEN: /* eg alu is same encoding as r700 */ r = r700_bc_alu_build(bc, alu, addr); break; default: @@ -868,6 +904,8 @@ int r600_bc_build(struct r600_bc *bc) case V_SQ_CF_WORD1_SQ_CF_INST_JUMP: case V_SQ_CF_WORD1_SQ_CF_INST_ELSE: case V_SQ_CF_WORD1_SQ_CF_INST_POP: + case V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS: + case V_SQ_CF_WORD1_SQ_CF_INST_RETURN: break; default: R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst); @@ -912,3 +950,342 @@ void r600_bc_clear(struct r600_bc *bc) LIST_INITHEAD(&cf->list); } + +void r600_bc_dump(struct r600_bc *bc) +{ + unsigned i; + char chip = '6'; + + switch (bc->chiprev) { + case 1: + chip = '7'; + break; + case 2: + chip = 'E'; + break; + case 0: + default: + chip = '6'; + break; + } + fprintf(stderr, "bytecode %d dw -----------------------\n", bc->ndw); + fprintf(stderr, " %c\n", chip); + for (i = 0; i < bc->ndw; i++) { + fprintf(stderr, "0x%08X\n", bc->bytecode[i]); + } + fprintf(stderr, "--------------------------------------\n"); +} + +void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) +{ + struct r600_pipe_state *rstate; + unsigned i = 0; + + if (count > 8) { + bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(8 - 1); + bytecode[i++] = S_SQ_CF_WORD0_ADDR(40 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(count - 8 - 1); + } else { + bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(count - 1); + } + bytecode[i++] = S_SQ_CF_WORD0_ADDR(0); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_RETURN) | + S_SQ_CF_WORD1_BARRIER(1); + + rstate = &ve->rstate; + rstate->id = R600_PIPE_STATE_FETCH_SHADER; + rstate->nregs = 0; + r600_pipe_state_add_reg(rstate, R_0288A4_SQ_PGM_RESOURCES_FS, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_0288DC_SQ_PGM_CF_OFFSET_FS, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_028894_SQ_PGM_START_FS, + r600_bo_offset(ve->fetch_shader) >> 8, + 0xFFFFFFFF, ve->fetch_shader); +} + +void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned count) +{ + struct r600_pipe_state *rstate; + unsigned i = 0; + + if (count > 8) { + bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(8 - 1); + bytecode[i++] = S_SQ_CF_WORD0_ADDR(40 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT((count - 8) - 1); + } else { + bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) | + S_SQ_CF_WORD1_BARRIER(1) | + S_SQ_CF_WORD1_COUNT(count - 1); + } + bytecode[i++] = S_SQ_CF_WORD0_ADDR(0); + bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_RETURN) | + S_SQ_CF_WORD1_BARRIER(1); + + rstate = &ve->rstate; + rstate->id = R600_PIPE_STATE_FETCH_SHADER; + rstate->nregs = 0; + r600_pipe_state_add_reg(rstate, R_0288A4_SQ_PGM_RESOURCES_FS, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_0288DC_SQ_PGM_CF_OFFSET_FS, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_028894_SQ_PGM_START_FS, + r600_bo_offset(ve->fetch_shader) >> 8, + 0xFFFFFFFF, ve->fetch_shader); +} + +static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format, + unsigned *num_format, unsigned *format_comp) +{ + const struct util_format_description *desc; + unsigned i; + + *format = 0; + *num_format = 0; + *format_comp = 0; + + desc = util_format_description(pformat); + if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { + goto out_unknown; + } + + /* Find the first non-VOID channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + + switch (desc->channel[i].type) { + /* Half-floats, floats, doubles */ + case UTIL_FORMAT_TYPE_FLOAT: + switch (desc->channel[i].size) { + case 16: + switch (desc->nr_channels) { + case 1: + *format = FMT_16_FLOAT; + break; + case 2: + *format = FMT_16_16_FLOAT; + break; + case 3: + *format = FMT_16_16_16_FLOAT; + break; + case 4: + *format = FMT_16_16_16_16_FLOAT; + break; + } + break; + case 32: + switch (desc->nr_channels) { + case 1: + *format = FMT_32_FLOAT; + break; + case 2: + *format = FMT_32_32_FLOAT; + break; + case 3: + *format = FMT_32_32_32_FLOAT; + break; + case 4: + *format = FMT_32_32_32_32_FLOAT; + break; + } + break; + default: + goto out_unknown; + } + break; + /* Unsigned ints */ + case UTIL_FORMAT_TYPE_UNSIGNED: + /* Signed ints */ + case UTIL_FORMAT_TYPE_SIGNED: + switch (desc->channel[i].size) { + case 8: + switch (desc->nr_channels) { + case 1: + *format = FMT_8; + break; + case 2: + *format = FMT_8_8; + break; + case 3: + // *format = FMT_8_8_8; /* fails piglit draw-vertices test */ + // break; + case 4: + *format = FMT_8_8_8_8; + break; + } + break; + case 16: + switch (desc->nr_channels) { + case 1: + *format = FMT_16; + break; + case 2: + *format = FMT_16_16; + break; + case 3: + // *format = FMT_16_16_16; /* fails piglit draw-vertices test */ + // break; + case 4: + *format = FMT_16_16_16_16; + break; + } + break; + case 32: + switch (desc->nr_channels) { + case 1: + *format = FMT_32; + break; + case 2: + *format = FMT_32_32; + break; + case 3: + *format = FMT_32_32_32; + break; + case 4: + *format = FMT_32_32_32_32; + break; + } + break; + default: + goto out_unknown; + } + break; + default: + goto out_unknown; + } + + if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { + *format_comp = 1; + } + if (desc->channel[i].normalized) { + *num_format = 0; + } else { + *num_format = 2; + } + return; +out_unknown: + R600_ERR("unsupported vertex format %s\n", util_format_name(pformat)); +} + +static void r600_bc(unsigned ndw, unsigned chiprev, u32 *bytecode) +{ + unsigned i; + char chip = '6'; + + switch (chiprev) { + case 1: + chip = '7'; + break; + case 2: + chip = 'E'; + break; + case 0: + default: + chip = '6'; + break; + } + fprintf(stderr, "bytecode %d dw -----------------------\n", ndw); + fprintf(stderr, " %c\n", chip); + for (i = 0; i < ndw; i++) { + fprintf(stderr, "0x%08X\n", bytecode[i]); + } + fprintf(stderr, "--------------------------------------\n"); +} + +int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, struct r600_vertex_element *ve) +{ + unsigned ndw, i; + u32 *bytecode; + unsigned fetch_resource_start = 0, format, num_format, format_comp; + struct pipe_vertex_element *elements = ve->elements; + const struct util_format_description *desc; + + /* 2 dwords for cf aligned to 4 + 4 dwords per input */ + ndw = 8 + ve->count * 4; + ve->fs_size = ndw * 4; + + /* use PIPE_BIND_VERTEX_BUFFER so we use the cache buffer manager */ + ve->fetch_shader = r600_bo(rctx->radeon, ndw*4, 256, PIPE_BIND_VERTEX_BUFFER, 0); + if (ve->fetch_shader == NULL) { + return -ENOMEM; + } + + bytecode = r600_bo_map(rctx->radeon, ve->fetch_shader, 0, NULL); + if (bytecode == NULL) { + r600_bo_reference(rctx->radeon, &ve->fetch_shader, NULL); + return -ENOMEM; + } + + if (rctx->family >= CHIP_CEDAR) { + eg_cf_vtx(ve, &bytecode[0], (ndw - 8) / 4); + } else { + r600_cf_vtx(ve, &bytecode[0], (ndw - 8) / 4); + fetch_resource_start = 160; + } + + /* vertex elements offset need special handling, if offset is bigger + * than what we can put in fetch instruction then we need to alterate + * the vertex resource offset. In such case in order to simplify code + * we will bound one resource per elements. It's a worst case scenario. + */ + for (i = 0; i < ve->count; i++) { + ve->vbuffer_offset[i] = C_SQ_VTX_WORD2_OFFSET & elements[i].src_offset; + if (ve->vbuffer_offset[i]) { + ve->vbuffer_need_offset = 1; + } + } + + for (i = 0; i < ve->count; i++) { + unsigned vbuffer_index; + r600_vertex_data_type(ve->hw_format[i], &format, &num_format, &format_comp); + desc = util_format_description(ve->hw_format[i]); + if (desc == NULL) { + R600_ERR("unknown format %d\n", ve->hw_format[i]); + r600_bo_reference(rctx->radeon, &ve->fetch_shader, NULL); + return -EINVAL; + } + + /* see above for vbuffer_need_offset explanation */ + vbuffer_index = elements[i].vertex_buffer_index; + if (ve->vbuffer_need_offset) { + bytecode[8 + i * 4 + 0] = S_SQ_VTX_WORD0_BUFFER_ID(i + fetch_resource_start); + } else { + bytecode[8 + i * 4 + 0] = S_SQ_VTX_WORD0_BUFFER_ID(vbuffer_index + fetch_resource_start); + } + bytecode[8 + i * 4 + 0] |= S_SQ_VTX_WORD0_SRC_GPR(0) | + S_SQ_VTX_WORD0_SRC_SEL_X(0) | + S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(0x1F); + bytecode[8 + i * 4 + 1] = S_SQ_VTX_WORD1_DST_SEL_X(desc->swizzle[0]) | + S_SQ_VTX_WORD1_DST_SEL_Y(desc->swizzle[1]) | + S_SQ_VTX_WORD1_DST_SEL_Z(desc->swizzle[2]) | + S_SQ_VTX_WORD1_DST_SEL_W(desc->swizzle[3]) | + S_SQ_VTX_WORD1_USE_CONST_FIELDS(0) | + S_SQ_VTX_WORD1_DATA_FORMAT(format) | + S_SQ_VTX_WORD1_NUM_FORMAT_ALL(num_format) | + S_SQ_VTX_WORD1_FORMAT_COMP_ALL(format_comp) | + S_SQ_VTX_WORD1_SRF_MODE_ALL(1) | + S_SQ_VTX_WORD1_GPR_DST_GPR(i + 1); + bytecode[8 + i * 4 + 2] = S_SQ_VTX_WORD2_OFFSET(elements[i].src_offset) | + S_SQ_VTX_WORD2_MEGA_FETCH(1); + bytecode[8 + i * 4 + 3] = 0; + } + r600_bo_unmap(rctx->radeon, ve->fetch_shader); + return 0; +} diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h index 25cda16837d..b147f0f5c88 100644 --- a/src/gallium/drivers/r600/r600_asm.h +++ b/src/gallium/drivers/r600/r600_asm.h @@ -28,6 +28,9 @@ #define NUM_OF_CYCLES 3 #define NUM_OF_COMPONENTS 4 +struct r600_vertex_element; +struct r600_pipe_context; + struct r600_bc_alu_src { unsigned sel; unsigned chan; @@ -145,12 +148,12 @@ struct r600_bc_cf { struct r600_bc_alu *curr_bs_head; }; -#define FC_NONE 0 -#define FC_IF 1 -#define FC_LOOP 2 -#define FC_REP 3 -#define FC_PUSH_VPM 4 -#define FC_PUSH_WQM 5 +#define FC_NONE 0 +#define FC_IF 1 +#define FC_LOOP 2 +#define FC_REP 3 +#define FC_PUSH_VPM 4 +#define FC_PUSH_WQM 5 struct r600_cf_stack_entry { int type; @@ -166,10 +169,11 @@ struct r600_cf_callstack { int current; int max; }; - + struct r600_bc { enum radeon_family family; int chiprev; /* 0 - r600, 1 - r700, 2 - evergreen */ + int type; struct list_head cf; struct r600_bc_cf *cf_last; unsigned ndw; @@ -187,6 +191,7 @@ struct r600_bc { /* eg_asm.c */ int eg_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf); +void eg_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); /* r600_asm.c */ int r600_bc_init(struct r600_bc *bc, enum radeon_family family); @@ -199,6 +204,11 @@ int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output); int r600_bc_build(struct r600_bc *bc); int r600_bc_add_cfinst(struct r600_bc *bc, int inst); int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int type); +void r600_bc_dump(struct r600_bc *bc); +void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); +void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned count); + +int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, struct r600_vertex_element *ve); /* r700_asm.c */ int r700_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id); diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 50d47060c1a..0f04136fb2a 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -27,9 +27,9 @@ enum r600_blitter_op /* bitmask */ { - R600_CLEAR = 1, - R600_CLEAR_SURFACE = 2, - R600_COPY = 4 + R600_CLEAR = 1, + R600_CLEAR_SURFACE = 2, + R600_COPY = 4 }; static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op) @@ -81,16 +81,21 @@ static void r600_blitter_end(struct pipe_context *ctx) int r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - struct pipe_surface *zsurf, *cbsurf; + struct pipe_surface *zsurf, *cbsurf, surf_tmpl; int level = 0; float depth = 1.0f; + surf_tmpl.format = texture->resource.base.b.format; + surf_tmpl.u.tex.level = level; + surf_tmpl.u.tex.first_layer = 0; + surf_tmpl.u.tex.last_layer = 0; + surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; - zsurf = ctx->screen->get_tex_surface(ctx->screen, &texture->resource.base.b, 0, level, 0, - PIPE_BIND_DEPTH_STENCIL); + zsurf = ctx->create_surface(ctx, &texture->resource.base.b, &surf_tmpl); - cbsurf = ctx->screen->get_tex_surface(ctx->screen, - (struct pipe_resource*)texture->flushed_depth_texture, - 0, level, 0, PIPE_BIND_RENDER_TARGET); + surf_tmpl.format = ((struct pipe_resource*)texture->flushed_depth_texture)->format; + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + cbsurf = ctx->create_surface(ctx, + (struct pipe_resource*)texture->flushed_depth_texture, &surf_tmpl); if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) @@ -154,42 +159,38 @@ static void r600_clear_depth_stencil(struct pipe_context *ctx, /* Copy a block of pixels from one surface to another using HW. */ static void r600_hw_copy_region(struct pipe_context *ctx, - struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource *src, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + struct pipe_resource *dst, + unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; r600_blitter_begin(ctx, R600_COPY); - util_blitter_copy_region(rctx->blitter, dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height, - TRUE); + util_blitter_copy_region(rctx->blitter, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box, TRUE); r600_blitter_end(ctx); } static void r600_resource_copy_region(struct pipe_context *ctx, struct pipe_resource *dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { boolean is_depth; /* there is something wrong with depth resource copies at the moment so avoid them for now */ is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; if (is_depth) - util_resource_copy_region(ctx, dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height); + util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); else - r600_hw_copy_region(ctx, dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height); - + r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); } void r600_init_blit_functions(struct r600_pipe_context *rctx) diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c index ed97b6e69a3..a17c54d6eeb 100644 --- a/src/gallium/drivers/r600/r600_buffer.c +++ b/src/gallium/drivers/r600/r600_buffer.c @@ -29,7 +29,6 @@ #include <util/u_math.h> #include <util/u_inlines.h> #include <util/u_memory.h> -#include <util/u_upload_mgr.h> #include "state_tracker/drm_driver.h" #include <xf86drm.h> #include "radeon_drm.h" @@ -53,12 +52,13 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen, rbuffer->magic = R600_BUFFER_MAGIC; rbuffer->user_buffer = NULL; - rbuffer->num_ranges = 0; rbuffer->r.base.b = *templ; pipe_reference_init(&rbuffer->r.base.b.reference, 1); rbuffer->r.base.b.screen = screen; rbuffer->r.base.vtbl = &r600_buffer_vtbl; rbuffer->r.size = rbuffer->r.base.b.width0; + rbuffer->r.bo_size = rbuffer->r.size; + rbuffer->uploaded = FALSE; bo = r600_bo((struct radeon*)screen->winsys, rbuffer->r.base.b.width0, alignment, rbuffer->r.base.b.bind, rbuffer->r.base.b.usage); if (bo == NULL) { FREE(rbuffer); @@ -89,10 +89,12 @@ struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen, rbuffer->r.base.b.width0 = bytes; rbuffer->r.base.b.height0 = 1; rbuffer->r.base.b.depth0 = 1; + rbuffer->r.base.b.array_size = 1; rbuffer->r.base.b.flags = 0; - rbuffer->num_ranges = 0; rbuffer->r.bo = NULL; + rbuffer->r.bo_size = 0; rbuffer->user_buffer = ptr; + rbuffer->uploaded = FALSE; return &rbuffer->r.base.b; } @@ -104,6 +106,7 @@ static void r600_buffer_destroy(struct pipe_screen *screen, if (rbuffer->r.bo) { r600_bo_reference((struct radeon*)screen->winsys, &rbuffer->r.bo, NULL); } + rbuffer->r.bo = NULL; FREE(rbuffer); } @@ -113,29 +116,10 @@ static void *r600_buffer_transfer_map(struct pipe_context *pipe, struct r600_resource_buffer *rbuffer = r600_buffer(transfer->resource); int write = 0; uint8_t *data; - int i; - boolean flush = FALSE; if (rbuffer->user_buffer) return (uint8_t*)rbuffer->user_buffer + transfer->box.x; - if (transfer->usage & PIPE_TRANSFER_DISCARD) { - for (i = 0; i < rbuffer->num_ranges; i++) { - if ((transfer->box.x >= rbuffer->ranges[i].start) && - (transfer->box.x < rbuffer->ranges[i].end)) - flush = TRUE; - - if (flush) { - r600_bo_reference((struct radeon*)pipe->winsys, &rbuffer->r.bo, NULL); - rbuffer->num_ranges = 0; - rbuffer->r.bo = r600_bo((struct radeon*)pipe->winsys, - rbuffer->r.base.b.width0, 0, - rbuffer->r.base.b.bind, - rbuffer->r.base.b.usage); - break; - } - } - } if (transfer->usage & PIPE_TRANSFER_DONTBLOCK) { /* FIXME */ } @@ -154,41 +138,22 @@ static void r600_buffer_transfer_unmap(struct pipe_context *pipe, { struct r600_resource_buffer *rbuffer = r600_buffer(transfer->resource); + if (rbuffer->user_buffer) + return; + if (rbuffer->r.bo) r600_bo_unmap((struct radeon*)pipe->winsys, rbuffer->r.bo); } static void r600_buffer_transfer_flush_region(struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) + struct pipe_transfer *transfer, + const struct pipe_box *box) { - struct r600_resource_buffer *rbuffer = r600_buffer(transfer->resource); - unsigned i; - unsigned offset = transfer->box.x + box->x; - unsigned length = box->width; - - assert(box->x + box->width <= transfer->box.width); - - if (rbuffer->user_buffer) - return; - - /* mark the range as used */ - for(i = 0; i < rbuffer->num_ranges; ++i) { - if(offset <= rbuffer->ranges[i].end && rbuffer->ranges[i].start <= (offset+box->width)) { - rbuffer->ranges[i].start = MIN2(rbuffer->ranges[i].start, offset); - rbuffer->ranges[i].end = MAX2(rbuffer->ranges[i].end, (offset+length)); - return; - } - } - - rbuffer->ranges[rbuffer->num_ranges].start = offset; - rbuffer->ranges[rbuffer->num_ranges].end = offset+length; - rbuffer->num_ranges++; } unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context, struct pipe_resource *buf, - unsigned face, unsigned level) + unsigned level, int layer) { /* FIXME */ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; @@ -235,29 +200,25 @@ struct u_resource_vtbl r600_buffer_vtbl = int r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw) { - struct pipe_resource *upload_buffer = NULL; - unsigned index_offset = draw->index_buffer_offset; - int ret = 0; - if (r600_buffer_is_user_buffer(draw->index_buffer)) { - ret = u_upload_buffer(rctx->upload_ib, - index_offset, - draw->count * draw->index_size, - draw->index_buffer, - &index_offset, - &upload_buffer); - if (ret) { - goto done; - } - draw->index_buffer_offset = index_offset; - - /* Transfer ownership. */ - pipe_resource_reference(&draw->index_buffer, upload_buffer); - pipe_resource_reference(&upload_buffer, NULL); + struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer); + unsigned upload_offset; + int ret = 0; + + ret = r600_upload_buffer(rctx->rupload_vb, + draw->index_buffer_offset, + draw->count * draw->index_size, + rbuffer, + &upload_offset, + &rbuffer->r.bo_size, + &rbuffer->r.bo); + if (ret) + return ret; + rbuffer->uploaded = TRUE; + draw->index_buffer_offset = upload_offset; } -done: - return ret; + return 0; } int r600_upload_user_buffers(struct r600_pipe_context *rctx) @@ -266,25 +227,24 @@ int r600_upload_user_buffers(struct r600_pipe_context *rctx) int i, nr; nr = rctx->vertex_elements->count; + nr = rctx->nvertex_buffer; for (i = 0; i < nr; i++) { - struct pipe_vertex_buffer *vb = - &rctx->vertex_buffer[rctx->vertex_elements->elements[i].vertex_buffer_index]; + struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i]; if (r600_buffer_is_user_buffer(vb->buffer)) { - struct pipe_resource *upload_buffer = NULL; - unsigned offset = 0; /*vb->buffer_offset * 4;*/ - unsigned size = vb->buffer->width0; + struct r600_resource_buffer *rbuffer = r600_buffer(vb->buffer); unsigned upload_offset; - ret = u_upload_buffer(rctx->upload_vb, - offset, size, - vb->buffer, - &upload_offset, &upload_buffer); + + ret = r600_upload_buffer(rctx->rupload_vb, + 0, vb->buffer->width0, + rbuffer, + &upload_offset, + &rbuffer->r.bo_size, + &rbuffer->r.bo); if (ret) return ret; - - pipe_resource_reference(&vb->buffer, NULL); - vb->buffer = upload_buffer; + rbuffer->uploaded = TRUE; vb->buffer_offset = upload_offset; } } diff --git a/src/gallium/drivers/r600/r600_opcodes.h b/src/gallium/drivers/r600/r600_opcodes.h index 4f9b39a7fdc..2ee0c83e5d3 100644 --- a/src/gallium/drivers/r600/r600_opcodes.h +++ b/src/gallium/drivers/r600/r600_opcodes.h @@ -385,8 +385,13 @@ #define EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_MEM_EXPORT_COMBINED 0x0000005B #define EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_MEM_RAT_COMBINED_CACHELESS 0x0000005C -#define BC_INST(bc, x) ((bc)->chiprev == 2 ? EG_##x : x) -#define CTX_INST(x) (ctx->bc->chiprev == 2 ? EG_##x : x) +#define CHIPREV_R600 0 +#define CHIPREV_R700 1 +#define CHIPREV_EVERGREEN 2 + +#define BC_INST(bc, x) ((bc)->chiprev == CHIPREV_EVERGREEN ? EG_##x : x) + +#define CTX_INST(x) (ctx->bc->chiprev == CHIPREV_EVERGREEN ? EG_##x : x) #endif diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 2a113f0ea8d..72988b946e5 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -35,7 +35,6 @@ #include <util/u_pack_color.h> #include <util/u_memory.h> #include <util/u_inlines.h> -#include <util/u_upload_mgr.h> #include <pipebuffer/pb_buffer.h> #include "r600.h" #include "r600d.h" @@ -59,9 +58,6 @@ static void r600_flush(struct pipe_context *ctx, unsigned flags, if (!rctx->ctx.pm4_cdwords) return; - u_upload_flush(rctx->upload_vb); - u_upload_flush(rctx->upload_ib); - #if 0 sprintf(dname, "gallium-%08d.bof", dc); if (dc < 20) { @@ -71,6 +67,8 @@ static void r600_flush(struct pipe_context *ctx, unsigned flags, dc++; #endif r600_context_flush(&rctx->ctx); + + r600_upload_flush(rctx->rupload_vb); } static void r600_destroy_context(struct pipe_context *context) @@ -79,6 +77,8 @@ static void r600_destroy_context(struct pipe_context *context) rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush); + r600_end_vertex_translate(rctx); + r600_context_fini(&rctx->ctx); util_blitter_destroy(rctx->blitter); @@ -87,8 +87,7 @@ static void r600_destroy_context(struct pipe_context *context) free(rctx->states[i]); } - u_upload_destroy(rctx->upload_vb); - u_upload_destroy(rctx->upload_ib); + r600_upload_destroy(rctx->rupload_vb); if (rctx->tran.translate_cache) translate_cache_destroy(rctx->tran.translate_cache); @@ -120,6 +119,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void r600_init_blit_functions(rctx); r600_init_query_functions(rctx); r600_init_context_resource_functions(rctx); + r600_init_surface_functions(rctx); switch (r600_get_family(rctx->radeon)) { case CHIP_R600: @@ -147,6 +147,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void case CHIP_JUNIPER: case CHIP_CYPRESS: case CHIP_HEMLOCK: + case CHIP_PALM: rctx->context.draw_vbo = evergreen_draw; evergreen_init_state_functions(rctx); if (evergreen_context_init(&rctx->ctx, rctx->radeon)) { @@ -161,16 +162,8 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void return NULL; } - rctx->upload_ib = u_upload_create(&rctx->context, 32 * 1024, 16, - PIPE_BIND_INDEX_BUFFER); - if (rctx->upload_ib == NULL) { - r600_destroy_context(&rctx->context); - return NULL; - } - - rctx->upload_vb = u_upload_create(&rctx->context, 128 * 1024, 16, - PIPE_BIND_VERTEX_BUFFER); - if (rctx->upload_vb == NULL) { + rctx->rupload_vb = r600_upload_create(rctx, 128 * 1024, 16); + if (rctx->rupload_vb == NULL) { r600_destroy_context(&rctx->context); return NULL; } @@ -186,7 +179,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void FREE(rctx); return NULL; } - + rctx->vs_resource = CALLOC(R600_RESOURCE_ARRAY_SIZE, sizeof(struct r600_pipe_state)); if (!rctx->vs_resource) { FREE(rctx); @@ -238,6 +231,7 @@ static const char *r600_get_family_name(enum radeon_family family) case CHIP_JUNIPER: return "AMD JUNIPER"; case CHIP_CYPRESS: return "AMD CYPRESS"; case CHIP_HEMLOCK: return "AMD HEMLOCK"; + case CHIP_PALM: return "AMD PALM"; default: return "AMD unknown"; } } @@ -252,6 +246,9 @@ static const char* r600_get_name(struct pipe_screen* pscreen) static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) { + struct r600_screen *rscreen = (struct r600_screen *)pscreen; + enum radeon_family family = r600_get_family(rscreen->radeon); + switch (param) { /* Supported features (boolean caps). */ case PIPE_CAP_NPOT_TEXTURES: @@ -284,7 +281,10 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 14; + if (family >= CHIP_CEDAR) + return 15; + else + return 14; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: /* FIXME allow this once infrastructure is there */ return 16; @@ -313,12 +313,18 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) static float r600_get_paramf(struct pipe_screen* pscreen, enum pipe_cap param) { + struct r600_screen *rscreen = (struct r600_screen *)pscreen; + enum radeon_family family = r600_get_family(rscreen->radeon); + switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: case PIPE_CAP_MAX_LINE_WIDTH_AA: case PIPE_CAP_MAX_POINT_WIDTH: case PIPE_CAP_MAX_POINT_WIDTH_AA: - return 8192.0f; + if (family >= CHIP_CEDAR) + return 16384.0f; + else + return 8192.0f; case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: return 16.0f; case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: @@ -375,6 +381,8 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; default: return 0; } @@ -403,10 +411,10 @@ static boolean r600_is_format_supported(struct pipe_screen* screen, } if ((usage & (PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SCANOUT | - PIPE_BIND_SHARED)) && - r600_is_colorbuffer_format_supported(format)) { + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT | + PIPE_BIND_SHARED)) && + r600_is_colorbuffer_format_supported(format)) { retval |= usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | @@ -463,7 +471,6 @@ struct pipe_screen *r600_screen_create(struct radeon *radeon) rscreen->screen.get_paramf = r600_get_paramf; rscreen->screen.is_format_supported = r600_is_format_supported; rscreen->screen.context_create = r600_create_context; - r600_init_screen_texture_functions(&rscreen->screen); r600_init_screen_resource_functions(&rscreen->screen); rscreen->tiling_info = r600_get_tiling_info(radeon); diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 1c691f6b764..43dbee99b0f 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -53,6 +53,8 @@ enum r600_pipe_state_id { R600_PIPE_STATE_CONSTANT, R600_PIPE_STATE_SAMPLER, R600_PIPE_STATE_RESOURCE, + R600_PIPE_STATE_POLYGON_OFFSET, + R600_PIPE_STATE_FETCH_SHADER, R600_PIPE_NSTATES }; @@ -86,13 +88,22 @@ struct r600_vertex_element struct pipe_vertex_element elements[PIPE_MAX_ATTRIBS]; enum pipe_format hw_format[PIPE_MAX_ATTRIBS]; unsigned hw_format_size[PIPE_MAX_ATTRIBS]; - boolean incompatible_layout; + boolean incompatible_layout; + struct r600_bo *fetch_shader; + unsigned fs_size; + struct r600_pipe_state rstate; + /* if offset is to big for fetch instructio we need to alterate + * offset of vertex buffer, record here the offset need to add + */ + unsigned vbuffer_need_offset; + unsigned vbuffer_offset[PIPE_MAX_ATTRIBS]; }; struct r600_pipe_shader { struct r600_shader shader; struct r600_pipe_state rstate; struct r600_bo *bo; + struct r600_bo *bo_fetch; struct r600_vertex_element vertex_elements; }; @@ -100,25 +111,28 @@ struct r600_pipe_shader { #define NUM_TEX_UNITS 16 struct r600_textures_info { - struct r600_pipe_sampler_view *views[NUM_TEX_UNITS]; - unsigned n_views; + struct r600_pipe_sampler_view *views[NUM_TEX_UNITS]; + unsigned n_views; void *samplers[NUM_TEX_UNITS]; - unsigned n_samplers; + unsigned n_samplers; }; +/* vertex buffer translation context, used to translate vertex input that + * hw doesn't natively support, so far only FLOAT64 is unsupported. + */ struct r600_translate_context { /* Translate cache for incompatible vertex offset/stride/format fallback. */ - struct translate_cache *translate_cache; - + struct translate_cache *translate_cache; /* The vertex buffer slot containing the translated buffer. */ - unsigned vb_slot; - /* Saved and new vertex element state. */ - void *saved_velems, *new_velems; + unsigned vb_slot; + void *new_velems; }; #define R600_CONSTANT_ARRAY_SIZE 256 #define R600_RESOURCE_ARRAY_SIZE 160 +struct r600_upload; + struct r600_pipe_context { struct pipe_context context; struct blitter_context *blitter; @@ -139,6 +153,7 @@ struct r600_pipe_context { struct pipe_stencil_ref stencil_ref; struct pipe_viewport_state viewport; struct pipe_clip_state clip; + unsigned nvs_resource; struct r600_pipe_state *vs_resource; struct r600_pipe_state *ps_resource; struct r600_pipe_state config; @@ -150,14 +165,11 @@ struct r600_pipe_context { /* shader information */ unsigned sprite_coord_enable; bool flatshade; - struct u_upload_mgr *upload_vb; - struct u_upload_mgr *upload_ib; + struct r600_upload *rupload_vb; unsigned any_user_vbs; - struct r600_textures_info ps_samplers; - - unsigned vb_max_index; - struct r600_translate_context tran; - + struct r600_textures_info ps_samplers; + unsigned vb_max_index; + struct r600_translate_context tran; }; struct r600_drawl { @@ -180,6 +192,8 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info) void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader); void evergreen_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *shader); void *evergreen_create_db_flush_dsa(struct r600_pipe_context *rctx); +void evergreen_polygon_offset_update(struct r600_pipe_context *rctx); +void evergreen_vertex_buffer_update(struct r600_pipe_context *rctx); /* r600_blit.c */ void r600_init_blit_functions(struct r600_pipe_context *rctx); @@ -193,7 +207,7 @@ struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen, unsigned bind); unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context, struct pipe_resource *buf, - unsigned face, unsigned level); + unsigned level, int layer); struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen, struct winsys_handle *whandle); int r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw); @@ -206,7 +220,7 @@ void r600_init_query_functions(struct r600_pipe_context *rctx); void r600_init_context_resource_functions(struct r600_pipe_context *r600); /* r600_shader.c */ -int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *shader); +int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader); int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens); void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader); int r600_find_vs_semantic_index(struct r600_shader *vs, @@ -217,14 +231,20 @@ void r600_init_state_functions(struct r600_pipe_context *rctx); void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info); void r600_init_config(struct r600_pipe_context *rctx); void *r600_create_db_flush_dsa(struct r600_pipe_context *rctx); +void r600_polygon_offset_update(struct r600_pipe_context *rctx); +void r600_vertex_buffer_update(struct r600_pipe_context *rctx); + /* r600_helper.h */ int r600_conv_pipe_prim(unsigned pprim, unsigned *prim); /* r600_texture.c */ void r600_init_screen_texture_functions(struct pipe_screen *screen); +void r600_init_surface_functions(struct r600_pipe_context *r600); uint32_t r600_translate_texformat(enum pipe_format format, const unsigned char *swizzle_view, uint32_t *word4_p, uint32_t *yuv_format_p); +unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, + unsigned level, unsigned layer); /* r600_translate.c */ void r600_begin_vertex_translate(struct r600_pipe_context *rctx); @@ -251,13 +271,13 @@ void r600_sampler_view_destroy(struct pipe_context *ctx, void r600_bind_state(struct pipe_context *ctx, void *state); void r600_delete_state(struct pipe_context *ctx, void *state); void r600_bind_vertex_elements(struct pipe_context *ctx, void *state); - void *r600_create_shader_state(struct pipe_context *ctx, const struct pipe_shader_state *state); void r600_bind_ps_shader(struct pipe_context *ctx, void *state); void r600_bind_vs_shader(struct pipe_context *ctx, void *state); void r600_delete_ps_shader(struct pipe_context *ctx, void *state); void r600_delete_vs_shader(struct pipe_context *ctx, void *state); + /* * common helpers */ diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h index 7a2d1f44122..8ca27699206 100644 --- a/src/gallium/drivers/r600/r600_resource.h +++ b/src/gallium/drivers/r600/r600_resource.h @@ -46,6 +46,7 @@ struct r600_resource { struct u_resource base; struct r600_bo *bo; u32 size; + unsigned bo_size; }; struct r600_resource_texture { @@ -61,7 +62,21 @@ struct r600_resource_texture { unsigned tile_type; unsigned depth; unsigned dirty; - struct r600_resource_texture *flushed_depth_texture; + struct r600_resource_texture *flushed_depth_texture; +}; + +#define R600_BUFFER_MAGIC 0xabcd1600 + +struct r600_resource_buffer { + struct r600_resource r; + uint32_t magic; + void *user_buffer; + bool uploaded; +}; + +struct r600_surface { + struct pipe_surface base; + unsigned aligned_height; }; void r600_init_screen_resource_functions(struct pipe_screen *screen); @@ -73,46 +88,30 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, const struct pipe_resource *base, struct winsys_handle *whandle); -#define R600_BUFFER_MAGIC 0xabcd1600 -#define R600_BUFFER_MAX_RANGES 32 - -struct r600_buffer_range { - uint32_t start; - uint32_t end; -}; - -struct r600_resource_buffer { - struct r600_resource r; - uint32_t magic; - void *user_buffer; - struct r600_buffer_range ranges[R600_BUFFER_MAX_RANGES]; - unsigned num_ranges; -}; - /* r600_buffer */ static INLINE struct r600_resource_buffer *r600_buffer(struct pipe_resource *buffer) { if (buffer) { assert(((struct r600_resource_buffer *)buffer)->magic == R600_BUFFER_MAGIC); return (struct r600_resource_buffer *)buffer; - } - return NULL; + } + return NULL; } static INLINE boolean r600_buffer_is_user_buffer(struct pipe_resource *buffer) { - return r600_buffer(buffer)->user_buffer ? TRUE : FALSE; + if (r600_buffer(buffer)->uploaded) + return FALSE; + return r600_buffer(buffer)->user_buffer ? TRUE : FALSE; } -int r600_texture_depth_flush(struct pipe_context *ctx, - struct pipe_resource *texture); - -extern int (*r600_blit_uncompress_depth_ptr)(struct pipe_context *ctx, struct r600_resource_texture *texture); +int r600_texture_depth_flush(struct pipe_context *ctx, struct pipe_resource *texture); +int (*r600_blit_uncompress_depth_ptr)(struct pipe_context *ctx, struct r600_resource_texture *texture); /* r600_texture.c texture transfer functions. */ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, struct pipe_resource *texture, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box); void r600_texture_transfer_destroy(struct pipe_context *ctx, @@ -122,9 +121,15 @@ void* r600_texture_transfer_map(struct pipe_context *ctx, void r600_texture_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer* transfer); -struct r600_surface { - struct pipe_surface base; - unsigned aligned_height; -}; +struct r600_pipe_context; +struct r600_upload *r600_upload_create(struct r600_pipe_context *rctx, + unsigned default_size, + unsigned alignment); +void r600_upload_flush(struct r600_upload *upload); +void r600_upload_destroy(struct r600_upload *upload); +int r600_upload_buffer(struct r600_upload *upload, unsigned offset, + unsigned size, struct r600_resource_buffer *in_buffer, + unsigned *out_offset, unsigned *out_size, + struct r600_bo **out_buffer); #endif diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index f6153c0e80f..9c7b7f0a578 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -44,6 +44,9 @@ static void r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shade rstate->nregs = 0; /* so far never got proper semantic id from tgsi */ + /* FIXME better to move this in config things so they get emited + * only one time per cs + */ for (i = 0; i < 10; i++) { spi_vs_out_id[i] = 0; } @@ -67,20 +70,11 @@ static void r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shade S_028868_STACK_SIZE(rshader->bc.nstack), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_0288A4_SQ_PGM_RESOURCES_FS, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_0288D0_SQ_PGM_CF_OFFSET_VS, 0x00000000, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_0288DC_SQ_PGM_CF_OFFSET_FS, - 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_028858_SQ_PGM_START_VS, r600_bo_offset(shader->bo) >> 8, 0xFFFFFFFF, shader->bo); - r600_pipe_state_add_reg(rstate, - R_028894_SQ_PGM_START_FS, - r600_bo_offset(shader->bo) >> 8, 0xFFFFFFFF, shader->bo); r600_pipe_state_add_reg(rstate, R_03E200_SQ_LOOP_CONST_0 + (32 * 4), 0x01000FFF, @@ -104,37 +98,20 @@ int r600_find_vs_semantic_index(struct r600_shader *vs, static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader) { - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_pipe_state *rstate = &shader->rstate; struct r600_shader *rshader = &shader->shader; - unsigned i, tmp, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1; + unsigned i, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1; int pos_index = -1, face_index = -1; - /* clear previous register */ rstate->nregs = 0; for (i = 0; i < rshader->ninput; i++) { - tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i)); - if (rshader->input[i].centroid) - tmp |= S_028644_SEL_CENTROID(1); - if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR) - tmp |= S_028644_SEL_LINEAR(1); - if (rshader->input[i].name == TGSI_SEMANTIC_POSITION) pos_index = i; - if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || - rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || - rshader->input[i].name == TGSI_SEMANTIC_POSITION) { - tmp |= S_028644_FLAT_SHADE(rshader->flat_shade); - } if (rshader->input[i].name == TGSI_SEMANTIC_FACE) face_index = i; - if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && - rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { - tmp |= S_028644_PT_SPRITE_TEX(1); - } - r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL); } + for (i = 0; i < rshader->noutput; i++) { if (rshader->output[i].name == TGSI_SEMANTIC_POSITION) r600_pipe_state_add_reg(rstate, @@ -210,7 +187,7 @@ static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shade 0xFFFFFFFF, NULL); } -static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader) +int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_shader *rshader = &shader->shader; @@ -227,7 +204,6 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s r600_bo_unmap(rctx->radeon, shader->bo); } /* build state */ - rshader->flat_shade = rctx->flatshade; switch (rshader->processor_type) { case TGSI_PROCESSOR_VERTEX: if (rshader->family >= CHIP_CEDAR) { @@ -246,75 +222,9 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s default: return -EINVAL; } - r600_context_pipe_state_set(&rctx->ctx, &shader->rstate); return 0; } -static int r600_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rshader) -{ - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - struct r600_shader *shader = &rshader->shader; - const struct util_format_description *desc; - enum pipe_format resource_format[160]; - unsigned i, nresources = 0; - struct r600_bc *bc = &shader->bc; - struct r600_bc_cf *cf; - struct r600_bc_vtx *vtx; - - if (shader->processor_type != TGSI_PROCESSOR_VERTEX) - return 0; - /* doing a full memcmp fell over the refcount */ - if ((rshader->vertex_elements.count == rctx->vertex_elements->count) && - (!memcmp(&rshader->vertex_elements.elements, &rctx->vertex_elements->elements, 32 * sizeof(struct pipe_vertex_element)))) { - return 0; - } - rshader->vertex_elements = *rctx->vertex_elements; - for (i = 0; i < rctx->vertex_elements->count; i++) { - resource_format[nresources++] = rctx->vertex_elements->hw_format[i]; - } - r600_bo_reference(rctx->radeon, &rshader->bo, NULL); - LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) { - switch (cf->inst) { - case V_SQ_CF_WORD1_SQ_CF_INST_VTX: - case V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC: - LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) { - desc = util_format_description(resource_format[vtx->buffer_id]); - if (desc == NULL) { - R600_ERR("unknown format %d\n", resource_format[vtx->buffer_id]); - return -EINVAL; - } - vtx->dst_sel_x = desc->swizzle[0]; - vtx->dst_sel_y = desc->swizzle[1]; - vtx->dst_sel_z = desc->swizzle[2]; - vtx->dst_sel_w = desc->swizzle[3]; - } - break; - default: - break; - } - } - return r600_bc_build(&shader->bc); -} - -int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *shader) -{ - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; - int r; - - if (shader == NULL) - return -EINVAL; - /* there should be enough input */ - if (rctx->vertex_elements->count < shader->shader.bc.nresource) { - R600_ERR("%d resources provided, expecting %d\n", - rctx->vertex_elements->count, shader->shader.bc.nresource); - return -EINVAL; - } - r = r600_shader_update(ctx, shader); - if (r) - return r; - return r600_pipe_shader(ctx, shader); -} - int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader); int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens) { @@ -334,20 +244,17 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s R600_ERR("building bytecode failed !\n"); return r; } +//r600_bc_dump(&shader->shader.bc); //fprintf(stderr, "______________________________________________________________\n"); - return 0; + return r600_pipe_shader(ctx, shader); } -void -r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader) +void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; r600_bo_reference(rctx->radeon, &shader->bo, NULL); - r600_bc_clear(&shader->shader.bc); - - /* FIXME: is there more stuff to free? */ } /* @@ -444,7 +351,7 @@ static int evergreen_interp_alu(struct r600_shader_ctx *ctx, int input) if (ctx->shader->input[input].centroid) ij_index++; } - + /* work out gpr and base_chan from index */ gpr = ij_index / 2; base_chan = (2 * (ij_index % 2)) + 1; @@ -477,15 +384,13 @@ static int evergreen_interp_alu(struct r600_shader_ctx *ctx, int input) return r; } return 0; -} - - +} + + static int tgsi_declaration(struct r600_shader_ctx *ctx) { struct tgsi_full_declaration *d = &ctx->parse.FullToken.FullDeclaration; - struct r600_bc_vtx vtx; unsigned i; - int r; switch (d->Declaration.File) { case TGSI_FILE_INPUT: @@ -495,27 +400,7 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx) ctx->shader->input[i].interpolate = d->Declaration.Interpolate; ctx->shader->input[i].centroid = d->Declaration.Centroid; ctx->shader->input[i].gpr = ctx->file_offset[TGSI_FILE_INPUT] + i; - if (ctx->type == TGSI_PROCESSOR_VERTEX) { - /* turn input into fetch */ - memset(&vtx, 0, sizeof(struct r600_bc_vtx)); - vtx.inst = 0; - vtx.fetch_type = 0; - vtx.buffer_id = i; - /* register containing the index into the buffer */ - vtx.src_gpr = 0; - vtx.src_sel_x = 0; - vtx.mega_fetch_count = 0x1F; - vtx.dst_gpr = ctx->shader->input[i].gpr; - vtx.dst_sel_x = 0; - vtx.dst_sel_y = 1; - vtx.dst_sel_z = 2; - vtx.dst_sel_w = 3; - vtx.use_const_fields = 1; - r = r600_bc_add_vtx(ctx->bc, &vtx); - if (r) - return r; - } - if (ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->bc->chiprev == 2) { + if (ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->bc->chiprev == CHIPREV_EVERGREEN) { /* turn input into interpolate on EG */ if (ctx->shader->input[i].name != TGSI_SEMANTIC_POSITION) { if (ctx->shader->input[i].interpolate > 0) { @@ -549,7 +434,7 @@ static int r600_get_temp(struct r600_shader_ctx *ctx) return ctx->temp_reg + ctx->max_driver_temp_used++; } -/* +/* * for evergreen we need to scan the shader to find the number of GPRs we need to * reserve for interpolation. * @@ -615,6 +500,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s tgsi_parse_init(&ctx.parse, tokens); ctx.type = ctx.parse.FullHeader.Processor.Processor; shader->processor_type = ctx.type; + ctx.bc->type = shader->processor_type; /* register allocations */ /* Values [0,127] correspond to GPR[0..127]. @@ -640,8 +526,13 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s } if (ctx.type == TGSI_PROCESSOR_VERTEX) { ctx.file_offset[TGSI_FILE_INPUT] = 1; + if (ctx.bc->chiprev == CHIPREV_EVERGREEN) { + r600_bc_add_cfinst(ctx.bc, EG_V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS); + } else { + r600_bc_add_cfinst(ctx.bc, V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS); + } } - if (ctx.type == TGSI_PROCESSOR_FRAGMENT && ctx.bc->chiprev == 2) { + if (ctx.type == TGSI_PROCESSOR_FRAGMENT && ctx.bc->chiprev == CHIPREV_EVERGREEN) { ctx.file_offset[TGSI_FILE_INPUT] = evergreen_gpr_count(&ctx); } ctx.file_offset[TGSI_FILE_OUTPUT] = ctx.file_offset[TGSI_FILE_INPUT] + @@ -687,7 +578,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s /* reserve first tmp for everyone */ r600_get_temp(&ctx); opcode = ctx.parse.FullToken.FullInstruction.Instruction.Opcode; - if (ctx.bc->chiprev == 2) + if (ctx.bc->chiprev == CHIPREV_EVERGREEN) ctx.inst_info = &eg_shader_tgsi_instruction[opcode]; else ctx.inst_info = &r600_shader_tgsi_instruction[opcode]; @@ -1001,7 +892,7 @@ static int tgsi_op2_s(struct r600_shader_ctx *ctx, int swap) r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); if (r) return r; - + alu.inst = ctx->inst_info->r600_opcode; if (!swap) { for (j = 0; j < inst->Instruction.NumSrcRegs; j++) { @@ -1046,7 +937,7 @@ static int tgsi_op2_swap(struct r600_shader_ctx *ctx) return tgsi_op2_s(ctx, 1); } -/* +/* * r600 - trunc to -PI..PI range * r700 - normalize by dividing by 2PI * see fdo bug 27901 @@ -1058,7 +949,7 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, int r; uint32_t lit_vals[4]; struct r600_bc_alu alu; - + memset(lit_vals, 0, 4*4); r = tgsi_split_constant(ctx, r600_src); if (r) @@ -1067,10 +958,6 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, if (r) return r; - r = tgsi_split_literal_constant(ctx, r600_src); - if (r) - return r; - lit_vals[0] = fui(1.0 /(3.1415926535 * 2)); lit_vals[1] = fui(0.5f); @@ -1084,7 +971,7 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, alu.src[0] = r600_src[0]; alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); - + alu.src[1].sel = V_SQ_ALU_SRC_LITERAL; alu.src[1].chan = 0; alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; @@ -1099,7 +986,7 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT); - + alu.dst.chan = 0; alu.dst.sel = ctx->temp_reg; alu.dst.write = 1; @@ -1111,7 +998,7 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, if (r) return r; - if (ctx->bc->chiprev == 0) { + if (ctx->bc->chiprev == CHIPREV_R600) { lit_vals[0] = fui(3.1415926535897f * 2.0f); lit_vals[1] = fui(-3.1415926535897f); } else { @@ -1129,7 +1016,7 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx, alu.src[0].sel = ctx->temp_reg; alu.src[0].chan = 0; - + alu.src[1].sel = V_SQ_ALU_SRC_LITERAL; alu.src[1].chan = 0; alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; @@ -1564,7 +1451,7 @@ static int tgsi_pow(struct r600_shader_ctx *ctx) return r; /* b * LOG2(a) */ memset(&alu, 0, sizeof(struct r600_bc_alu)); - alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL_IEEE); + alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL); r = tgsi_src(ctx, &inst->Src[1], &alu.src[0]); if (r) return r; @@ -1908,10 +1795,10 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - + /* MULADD R0.x, R0.x, PS1, (0x3FC00000, 1.5f).x * MULADD R0.y, R0.y, PS1, (0x3FC00000, 1.5f).x - * muladd has no writemask, have to use another temp + * muladd has no writemask, have to use another temp */ memset(&alu, 0, sizeof(struct r600_bc_alu)); alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD); @@ -1921,7 +1808,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) alu.src[0].chan = 0; alu.src[1].sel = ctx->temp_reg; alu.src[1].chan = 2; - + alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; alu.src[2].chan = 0; @@ -1941,7 +1828,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) alu.src[0].chan = 1; alu.src[1].sel = ctx->temp_reg; alu.src[1].chan = 2; - + alu.src[2].sel = V_SQ_ALU_SRC_LITERAL; alu.src[2].chan = 0; @@ -1980,7 +1867,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) } src_gpr = ctx->temp_reg; } - + opcode = ctx->inst_info->r600_opcode; if (opcode == SQ_TEX_INST_SAMPLE && (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D || inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D)) @@ -1990,8 +1877,6 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) tex.inst = opcode; tex.sampler_id = ctx->file_offset[inst->Src[1].Register.File] + inst->Src[1].Register.Index; tex.resource_id = tex.sampler_id; - if (ctx->shader->processor_type == TGSI_PROCESSOR_VERTEX) - tex.resource_id += PIPE_MAX_ATTRIBS; tex.src_gpr = src_gpr; tex.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index; tex.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 0 : 7; @@ -2026,7 +1911,6 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) /* add shadow ambient support - gallium doesn't do it yet */ return 0; - } static int tgsi_lrp(struct r600_shader_ctx *ctx) @@ -2156,7 +2040,7 @@ static int tgsi_cmp(struct r600_shader_ctx *ctx) r = r600_bc_add_alu(ctx->bc, &alu); if (r) return r; - } + } if (use_temp) return tgsi_helper_copy(ctx, inst); return 0; @@ -2342,7 +2226,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx) if (r) return r; } - + /* result.y = tmp - floor(tmp); */ if ((inst->Dst[0].Register.WriteMask >> 1) & 1) { memset(&alu, 0, sizeof(struct r600_bc_alu)); @@ -2621,16 +2505,25 @@ static int tgsi_log(struct r600_shader_ctx *ctx) return tgsi_helper_copy(ctx, inst); } -/* r6/7 only for now */ static int tgsi_eg_arl(struct r600_shader_ctx *ctx) { struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; struct r600_bc_alu alu; int r; - memset(&alu, 0, sizeof(struct r600_bc_alu)); - alu.inst = EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT_FLOOR; + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_ARL: + alu.inst = EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT_FLOOR; + break; + case TGSI_OPCODE_ARR: + alu.inst = EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT; + break; + default: + assert(0); + return -1; + } + r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); if (r) return r; @@ -2663,18 +2556,18 @@ static int tgsi_r600_arl(struct r600_shader_ctx *ctx) int r; memset(&alu, 0, sizeof(struct r600_bc_alu)); - switch (inst->Instruction.Opcode) { - case TGSI_OPCODE_ARL: - alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR; - break; - case TGSI_OPCODE_ARR: - alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA; - break; - default: - assert(0); - return -1; - } - + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_ARL: + alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR; + break; + case TGSI_OPCODE_ARR: + alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA; + break; + default: + assert(0); + return -1; + } + r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); if (r) @@ -2703,8 +2596,8 @@ static int tgsi_opdst(struct r600_shader_ctx *ctx) r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); if (r) return r; - - if (i == 0 || i == 3) { + + if (i == 0 || i == 3) { alu.src[0].sel = V_SQ_ALU_SRC_1; } else { r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]); @@ -2750,7 +2643,7 @@ static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode) alu.src[0].chan = tgsi_chan(&inst->Src[0], 0); alu.src[1].sel = V_SQ_ALU_SRC_0; alu.src[1].chan = 0; - + alu.last = 1; r = r600_bc_add_alu_type(ctx->bc, &alu, CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE)); @@ -2763,6 +2656,7 @@ static int pops(struct r600_shader_ctx *ctx, int pops) { r600_bc_add_cfinst(ctx->bc, CTX_INST(V_SQ_CF_WORD1_SQ_CF_INST_POP)); ctx->bc->cf_last->pop_count = pops; + ctx->bc->cf_last->cf_addr = ctx->bc->cf_last->id + 2; return 0; } @@ -2804,7 +2698,7 @@ static inline void callstack_check_depth(struct r600_shader_ctx *ctx, unsigned r ctx->bc->callstack[ctx->bc->call_sp].current + diff; } return; - } + } switch (reason) { case FC_PUSH_VPM: ctx->bc->callstack[ctx->bc->call_sp].current++; @@ -2878,7 +2772,7 @@ static int emit_setret_in_loop_flag(struct r600_shader_ctx *ctx, unsigned flag_v static void emit_testflag(struct r600_shader_ctx *ctx) { - + } static void emit_return_on_flag(struct r600_shader_ctx *ctx, unsigned ifidx) @@ -3239,7 +3133,7 @@ static struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] = { {TGSI_OPCODE_UP4UB, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, {TGSI_OPCODE_X2D, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, {TGSI_OPCODE_ARA, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, - {TGSI_OPCODE_ARR, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, + {TGSI_OPCODE_ARR, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_eg_arl}, {TGSI_OPCODE_BRA, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, {TGSI_OPCODE_CAL, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, {TGSI_OPCODE_RET, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported}, diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index f8bc5951395..35b0331525a 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -38,7 +38,6 @@ struct r600_shader_io { struct r600_shader { unsigned processor_type; struct r600_bc bc; - boolean flat_shade; unsigned ninput; unsigned noutput; unsigned nlds; diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 54cc79b1549..cd5f0792d5e 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -36,7 +36,6 @@ #include <util/u_pack_color.h> #include <util/u_memory.h> #include <util/u_inlines.h> -#include <util/u_upload_mgr.h> #include <util/u_framebuffer.h> #include <pipebuffer/pb_buffer.h> #include "r600.h" @@ -46,14 +45,164 @@ #include "r600_pipe.h" #include "r600_state_inlines.h" +void r600_polygon_offset_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_state state; + + state.id = R600_PIPE_STATE_POLYGON_OFFSET; + state.nregs = 0; + if (rctx->rasterizer && rctx->framebuffer.zsbuf) { + float offset_units = rctx->rasterizer->offset_units; + unsigned offset_db_fmt_cntl = 0, depth; + + switch (rctx->framebuffer.zsbuf->texture->format) { + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + depth = -24; + offset_units *= 2.0f; + break; + case PIPE_FORMAT_Z32_FLOAT: + depth = -23; + offset_units *= 1.0f; + offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT(1); + break; + case PIPE_FORMAT_Z16_UNORM: + depth = -16; + offset_units *= 4.0f; + break; + default: + return; + } + /* FIXME some of those reg can be computed with cso */ + offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS(depth); + r600_pipe_state_add_reg(&state, + R_028E00_PA_SU_POLY_OFFSET_FRONT_SCALE, + fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028E04_PA_SU_POLY_OFFSET_FRONT_OFFSET, + fui(offset_units), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028E08_PA_SU_POLY_OFFSET_BACK_SCALE, + fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028E0C_PA_SU_POLY_OFFSET_BACK_OFFSET, + fui(offset_units), 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(&state, + R_028DF8_PA_SU_POLY_OFFSET_DB_FMT_CNTL, + offset_db_fmt_cntl, 0xFFFFFFFF, NULL); + r600_context_pipe_state_set(&rctx->ctx, &state); + } +} + +/* FIXME optimize away spi update when it's not needed */ +static void r600_spi_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_shader *shader = rctx->ps_shader; + struct r600_pipe_state rstate; + struct r600_shader *rshader = &shader->shader; + unsigned i, tmp; + + rstate.nregs = 0; + for (i = 0; i < rshader->ninput; i++) { + tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i)); + if (rshader->input[i].centroid) + tmp |= S_028644_SEL_CENTROID(1); + if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR) + tmp |= S_028644_SEL_LINEAR(1); + + if (rshader->input[i].name == TGSI_SEMANTIC_COLOR || + rshader->input[i].name == TGSI_SEMANTIC_BCOLOR || + rshader->input[i].name == TGSI_SEMANTIC_POSITION) { + tmp |= S_028644_FLAT_SHADE(rctx->flatshade); + } + if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC && + rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) { + tmp |= S_028644_PT_SPRITE_TEX(1); + } + r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL); + } + r600_context_pipe_state_set(&rctx->ctx, &rstate); +} + +void r600_vertex_buffer_update(struct r600_pipe_context *rctx) +{ + struct r600_pipe_state *rstate; + struct r600_resource *rbuffer; + struct pipe_vertex_buffer *vertex_buffer; + unsigned i, offset; + + /* we don't update until we know vertex elements */ + if (rctx->vertex_elements == NULL || !rctx->nvertex_buffer) + return; + + if (rctx->vertex_elements->incompatible_layout) { + /* translate rebind new vertex elements so + * return once translated + */ + r600_begin_vertex_translate(rctx); + return; + } + + if (rctx->any_user_vbs) { + r600_upload_user_buffers(rctx); + rctx->any_user_vbs = FALSE; + } + + if (rctx->vertex_elements->vbuffer_need_offset) { + /* one resource per vertex elements */ + rctx->nvs_resource = rctx->vertex_elements->count; + } else { + /* bind vertex buffer once */ + rctx->nvs_resource = rctx->nvertex_buffer; + } + + for (i = 0 ; i < rctx->nvs_resource; i++) { + rstate = &rctx->vs_resource[i]; + rstate->id = R600_PIPE_STATE_RESOURCE; + rstate->nregs = 0; + + if (rctx->vertex_elements->vbuffer_need_offset) { + /* one resource per vertex elements */ + unsigned vbuffer_index; + vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index; + vertex_buffer = &rctx->vertex_buffer[vbuffer_index]; + rbuffer = (struct r600_resource*)vertex_buffer->buffer; + offset = rctx->vertex_elements->vbuffer_offset[i] + + vertex_buffer->buffer_offset + + r600_bo_offset(rbuffer->bo); + } else { + /* bind vertex buffer once */ + vertex_buffer = &rctx->vertex_buffer[i]; + rbuffer = (struct r600_resource*)vertex_buffer->buffer; + offset = vertex_buffer->buffer_offset + + r600_bo_offset(rbuffer->bo); + } + + r600_pipe_state_add_reg(rstate, R_038000_RESOURCE0_WORD0, + offset, 0xFFFFFFFF, rbuffer->bo); + r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1, + rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2, + S_038008_STRIDE(vertex_buffer->stride), + 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5, + 0x00000000, 0xFFFFFFFF, NULL); + r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6, + 0xC0000000, 0xFFFFFFFF, NULL); + r600_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i); + } +} + static void r600_draw_common(struct r600_drawl *draw) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)draw->ctx; - struct r600_pipe_state *rstate; struct r600_resource *rbuffer; - unsigned i, j, offset, prim; + unsigned prim; u32 vgt_dma_index_type, vgt_draw_initiator, mask; - struct pipe_vertex_buffer *vertex_buffer; struct r600_draw rdraw; struct r600_pipe_state vgt; @@ -76,42 +225,23 @@ static void r600_draw_common(struct r600_drawl *draw) } if (r600_conv_pipe_prim(draw->mode, &prim)) return; - - - /* rebuild vertex shader if input format changed */ - if (r600_pipe_shader_update(&rctx->context, rctx->vs_shader)) + if (unlikely(rctx->ps_shader == NULL)) { + R600_ERR("missing vertex shader\n"); return; - if (r600_pipe_shader_update(&rctx->context, rctx->ps_shader)) + } + if (unlikely(rctx->vs_shader == NULL)) { + R600_ERR("missing vertex shader\n"); + return; + } + /* there should be enough input */ + if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) { + R600_ERR("%d resources provided, expecting %d\n", + rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource); return; - - for (i = 0 ; i < rctx->vertex_elements->count; i++) { - uint32_t word2, format; - - rstate = &rctx->vs_resource[i]; - rstate->id = R600_PIPE_STATE_RESOURCE; - rstate->nregs = 0; - - j = rctx->vertex_elements->elements[i].vertex_buffer_index; - vertex_buffer = &rctx->vertex_buffer[j]; - rbuffer = (struct r600_resource*)vertex_buffer->buffer; - offset = rctx->vertex_elements->elements[i].src_offset + - vertex_buffer->buffer_offset + - r600_bo_offset(rbuffer->bo); - - format = r600_translate_vertex_data_type(rctx->vertex_elements->hw_format[i]); - - word2 = format | S_038008_STRIDE(vertex_buffer->stride); - - r600_pipe_state_add_reg(rstate, R_038000_RESOURCE0_WORD0, offset, 0xFFFFFFFF, rbuffer->bo); - r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1, rbuffer->size - offset - 1, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2, word2, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3, 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4, 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5, 0x00000000, 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6, 0xC0000000, 0xFFFFFFFF, NULL); - r600_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, i); } + r600_spi_update(rctx); + mask = 0; for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) { mask |= (0xF << (i * 4)); @@ -126,46 +256,6 @@ static void r600_draw_common(struct r600_drawl *draw) r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL); - /* build late state */ - if (rctx->rasterizer && rctx->framebuffer.zsbuf) { - float offset_units = rctx->rasterizer->offset_units; - unsigned offset_db_fmt_cntl = 0, depth; - - switch (rctx->framebuffer.zsbuf->texture->format) { - case PIPE_FORMAT_Z24X8_UNORM: - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - depth = -24; - offset_units *= 2.0f; - break; - case PIPE_FORMAT_Z32_FLOAT: - depth = -23; - offset_units *= 1.0f; - offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_DB_IS_FLOAT_FMT(1); - break; - case PIPE_FORMAT_Z16_UNORM: - depth = -16; - offset_units *= 4.0f; - break; - default: - return; - } - offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS(depth); - r600_pipe_state_add_reg(&vgt, - R_028E00_PA_SU_POLY_OFFSET_FRONT_SCALE, - fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028E04_PA_SU_POLY_OFFSET_FRONT_OFFSET, - fui(offset_units), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028E08_PA_SU_POLY_OFFSET_BACK_SCALE, - fui(rctx->rasterizer->offset_scale), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028E0C_PA_SU_POLY_OFFSET_BACK_OFFSET, - fui(offset_units), 0xFFFFFFFF, NULL); - r600_pipe_state_add_reg(&vgt, - R_028DF8_PA_SU_POLY_OFFSET_DB_FMT_CNTL, - offset_db_fmt_cntl, 0xFFFFFFFF, NULL); - } r600_context_pipe_state_set(&rctx->ctx, &vgt); rdraw.vgt_num_indices = draw->count; @@ -185,17 +275,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_drawl draw; - boolean translate = FALSE; - if (rctx->vertex_elements->incompatible_layout) { - r600_begin_vertex_translate(rctx); - translate = TRUE; - } - - if (rctx->any_user_vbs) { - r600_upload_user_buffers(rctx); - rctx->any_user_vbs = FALSE; - } memset(&draw, 0, sizeof(struct r600_drawl)); draw.ctx = ctx; draw.mode = info->mode; @@ -226,9 +306,6 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) } r600_draw_common(&draw); - if (translate) - r600_end_vertex_translate(rctx); - pipe_resource_reference(&draw.index_buffer, NULL); } @@ -296,7 +373,7 @@ static void *r600_create_blend_state(struct pipe_context *ctx, unsigned eqRGB = state->rt[i].rgb_func; unsigned srcRGB = state->rt[i].rgb_src_factor; unsigned dstRGB = state->rt[i].rgb_dst_factor; - + unsigned eqA = state->rt[i].alpha_func; unsigned srcA = state->rt[i].alpha_src_factor; unsigned dstA = state->rt[i].alpha_dst_factor; @@ -475,7 +552,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx, r600_pipe_state_add_reg(rstate, R_028A0C_PA_SC_LINE_STIPPLE, 0x00000005, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_028A48_PA_SC_MPASS_PS_CNTL, 0x00000000, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_028C00_PA_SC_LINE_CNTL, 0x00000400, 0xFFFFFFFF, NULL); - + r600_pipe_state_add_reg(rstate, R_028C08_PA_SU_VTX_CNTL, S_028C08_PIX_CENTER_HALF(state->gl_rasterization_rules), 0xFFFFFFFF, NULL); @@ -603,9 +680,9 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c word4 | S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_NORM) | S_038010_SRF_MODE_ALL(V_038010_SFR_MODE_NO_ZERO) | S_038010_REQUEST_SIZE(1) | - S_038010_BASE_LEVEL(state->first_level), 0xFFFFFFFF, NULL); + S_038010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5, - S_038014_LAST_LEVEL(state->last_level) | + S_038014_LAST_LEVEL(state->u.tex.last_level) | S_038014_BASE_ARRAY(0) | S_038014_LAST_ARRAY(0), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6, @@ -622,7 +699,7 @@ static void r600_set_vs_sampler_view(struct pipe_context *ctx, unsigned count, for (int i = 0; i < count; i++) { if (resource[i]) { - r600_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state, i + PIPE_MAX_ATTRIBS); + r600_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state, i); } } } @@ -692,16 +769,16 @@ static void r600_set_clip_state(struct pipe_context *ctx, rstate->id = R600_PIPE_STATE_CLIP; for (int i = 0; i < state->nr; i++) { r600_pipe_state_add_reg(rstate, - R_028E20_PA_CL_UCP0_X + i * 4, + R_028E20_PA_CL_UCP0_X + i * 16, fui(state->ucp[i][0]), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_028E24_PA_CL_UCP0_Y + i * 4, + R_028E24_PA_CL_UCP0_Y + i * 16, fui(state->ucp[i][1]) , 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_028E28_PA_CL_UCP0_Z + i * 4, + R_028E28_PA_CL_UCP0_Z + i * 16, fui(state->ucp[i][2]), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, - R_028E2C_PA_CL_UCP0_W + i * 4, + R_028E2C_PA_CL_UCP0_W + i * 16, fui(state->ucp[i][3]), 0xFFFFFFFF, NULL); } r600_pipe_state_add_reg(rstate, R_028810_PA_CL_CLIP_CNTL, @@ -824,10 +901,11 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta struct r600_resource_texture *rtex; struct r600_resource *rbuffer; struct r600_surface *surf; - unsigned level = state->cbufs[cb]->level; + unsigned level = state->cbufs[cb]->u.tex.level; unsigned pitch, slice; unsigned color_info; unsigned format, swap, ntype; + unsigned offset; const struct util_format_description *desc; struct r600_bo *bo[3]; @@ -838,6 +916,9 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta bo[1] = rbuffer->bo; bo[2] = rbuffer->bo; + /* XXX quite sure for dx10+ hw don't need any offset hacks */ + offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture, + level, state->cbufs[cb]->u.tex.first_layer); pitch = rtex->pitch_in_pixels[level] / 8 - 1; slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; ntype = 0; @@ -852,12 +933,12 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta S_0280A0_ARRAY_MODE(rtex->array_mode[level]) | S_0280A0_BLEND_CLAMP(1) | S_0280A0_NUMBER_TYPE(ntype); - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) + if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) color_info |= S_0280A0_SOURCE_FORMAT(1); r600_pipe_state_add_reg(rstate, R_028040_CB_COLOR0_BASE + cb * 4, - (state->cbufs[cb]->offset + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]); + (offset + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]); r600_pipe_state_add_reg(rstate, R_0280A0_CB_COLOR0_INFO + cb * 4, color_info, 0xFFFFFFFF, bo[0]); @@ -888,11 +969,12 @@ static void r600_db(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta struct r600_surface *surf; unsigned level; unsigned pitch, slice, format; + unsigned offset; if (state->zsbuf == NULL) return; - level = state->zsbuf->level; + level = state->zsbuf->u.tex.level; surf = (struct r600_surface *)state->zsbuf; rtex = (struct r600_resource_texture*)state->zsbuf->texture; @@ -902,12 +984,15 @@ static void r600_db(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta rtex->depth = 1; rbuffer = &rtex->resource; + /* XXX quite sure for dx10+ hw don't need any offset hacks */ + offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, + level, state->zsbuf->u.tex.first_layer); pitch = rtex->pitch_in_pixels[level] / 8 - 1; slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1; format = r600_translate_dbformat(state->zsbuf->texture->format); r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE, - (state->zsbuf->offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); + (offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); r600_pipe_state_add_reg(rstate, R_028000_DB_DEPTH_SIZE, S_028000_PITCH_TILE_MAX(pitch) | S_028000_SLICE_TILE_MAX(slice), 0xFFFFFFFF, NULL); @@ -933,7 +1018,7 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, rstate->id = R600_PIPE_STATE_FRAMEBUFFER; util_copy_framebuffer_state(&rctx->framebuffer, state); - + rctx->pframebuffer = &rctx->framebuffer; /* build states */ @@ -1015,6 +1100,10 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, free(rctx->states[R600_PIPE_STATE_FRAMEBUFFER]); rctx->states[R600_PIPE_STATE_FRAMEBUFFER] = rstate; r600_context_pipe_state_set(&rctx->ctx, rstate); + + if (state->zsbuf) { + r600_polygon_offset_update(rctx); + } } static void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 210420e823b..99b372caace 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -58,6 +58,12 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state) rctx->states[rs->rstate.id] = &rs->rstate; r600_context_pipe_state_set(&rctx->ctx, &rs->rstate); + + if (rctx->family >= CHIP_CEDAR) { + evergreen_polygon_offset_update(rctx); + } else { + r600_polygon_offset_update(rctx); + } } void r600_delete_rs_state(struct pipe_context *ctx, void *state) @@ -113,8 +119,23 @@ void r600_bind_vertex_elements(struct pipe_context *ctx, void *state) struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_vertex_element *v = (struct r600_vertex_element*)state; + /* delete previous translated vertex elements */ + if (rctx->tran.new_velems) { + r600_end_vertex_translate(rctx); + } + rctx->vertex_elements = v; if (v) { + rctx->states[v->rstate.id] = &v->rstate; + r600_context_pipe_state_set(&rctx->ctx, &v->rstate); + if (rctx->family >= CHIP_CEDAR) { + evergreen_vertex_buffer_update(rctx); + } else { + r600_vertex_buffer_update(rctx); + } + } + + if (v) { // rctx->vs_rebuild = TRUE; } } @@ -122,11 +143,16 @@ void r600_bind_vertex_elements(struct pipe_context *ctx, void *state) void r600_delete_vertex_element(struct pipe_context *ctx, void *state) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + struct r600_vertex_element *v = (struct r600_vertex_element*)state; - FREE(state); - + if (rctx->states[v->rstate.id] == &v->rstate) { + rctx->states[v->rstate.id] = NULL; + } if (rctx->vertex_elements == state) rctx->vertex_elements = NULL; + + r600_bo_reference(rctx->radeon, &v->fetch_shader, NULL); + FREE(state); } @@ -166,16 +192,23 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count, rctx->any_user_vbs = TRUE; pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer); + /* The stride of zero means we will be fetching only the first + * vertex, so don't care about max_index. */ + if (!vbo->stride) + continue; + if (vbo->max_index == ~0) { - if (!vbo->stride) - vbo->max_index = 1; - else - vbo->max_index = (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; + vbo->max_index = (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; } max_index = MIN2(vbo->max_index, max_index); } rctx->nvertex_buffer = count; rctx->vb_max_index = max_index; + if (rctx->family >= CHIP_CEDAR) { + evergreen_vertex_buffer_update(rctx); + } else { + r600_vertex_buffer_update(rctx); + } } @@ -186,9 +219,10 @@ void *r600_create_vertex_elements(struct pipe_context *ctx, unsigned count, const struct pipe_vertex_element *elements) { + struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; struct r600_vertex_element *v = CALLOC_STRUCT(r600_vertex_element); - int i; enum pipe_format *format; + int i; assert(count < 32); if (!v) @@ -202,19 +236,22 @@ void *r600_create_vertex_elements(struct pipe_context *ctx, format = &v->hw_format[i]; switch (*format) { - FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); - FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); - FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); - FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); + FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); + FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); + FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); + FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); default:; } v->incompatible_layout = v->incompatible_layout || - v->elements[i].src_format != v->hw_format[i] || - v->elements[i].src_offset % 4 != 0; + v->elements[i].src_format != v->hw_format[i]; + + v->hw_format_size[i] = align(util_format_get_blocksize(v->hw_format[i]), 4); + } - v->hw_format_size[i] = - align(util_format_get_blocksize(v->hw_format[i]), 4); + if (r600_vertex_elements_build_fetch_shader(rctx, v)) { + FREE(v); + return NULL; } return v; @@ -239,6 +276,9 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state) /* TODO delete old shader */ rctx->ps_shader = (struct r600_pipe_shader *)state; + if (state) { + r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate); + } } void r600_bind_vs_shader(struct pipe_context *ctx, void *state) @@ -247,6 +287,9 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state) /* TODO delete old shader */ rctx->vs_shader = (struct r600_pipe_shader *)state; + if (state) { + r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate); + } } void r600_delete_ps_shader(struct pipe_context *ctx, void *state) diff --git a/src/gallium/drivers/r600/r600_state_inlines.h b/src/gallium/drivers/r600/r600_state_inlines.h index 1be5b156d35..d994196e19d 100644 --- a/src/gallium/drivers/r600/r600_state_inlines.h +++ b/src/gallium/drivers/r600/r600_state_inlines.h @@ -282,6 +282,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) switch (format) { /* 8-bit buffers. */ case PIPE_FORMAT_A8_UNORM: + return V_0280A0_SWAP_ALT_REV; case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: case PIPE_FORMAT_R8_UNORM: @@ -304,6 +305,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format) return V_0280A0_SWAP_STD; case PIPE_FORMAT_L8A8_UNORM: + return V_0280A0_SWAP_ALT; case PIPE_FORMAT_R8G8_UNORM: return V_0280A0_SWAP_STD; diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index e719f7fb983..d4d9b07c0e8 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -45,14 +45,10 @@ static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_t { struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer; struct pipe_resource *texture = transfer->resource; - struct pipe_subresource subdst; - subdst.face = 0; - subdst.level = 0; ctx->resource_copy_region(ctx, rtransfer->staging_texture, - subdst, 0, 0, 0, texture, transfer->sr, - transfer->box.x, transfer->box.y, transfer->box.z, - transfer->box.width, transfer->box.height); + 0, 0, 0, 0, texture, transfer->level, + &transfer->box); } @@ -61,34 +57,32 @@ static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600 { struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer; struct pipe_resource *texture = transfer->resource; - struct pipe_subresource subsrc; - - subsrc.face = 0; - subsrc.level = 0; - ctx->resource_copy_region(ctx, texture, transfer->sr, + struct pipe_box sbox; + + sbox.x = sbox.y = sbox.z = 0; + sbox.width = transfer->box.width; + sbox.height = transfer->box.height; + /* XXX that might be wrong */ + sbox.depth = 1; + ctx->resource_copy_region(ctx, texture, transfer->level, transfer->box.x, transfer->box.y, transfer->box.z, - rtransfer->staging_texture, subsrc, - 0, 0, 0, - transfer->box.width, transfer->box.height); + rtransfer->staging_texture, + 0, &sbox); ctx->flush(ctx, 0, NULL); } -static unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, - unsigned level, unsigned zslice, - unsigned face) +unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, + unsigned level, unsigned layer) { unsigned offset = rtex->offset[level]; switch (rtex->resource.base.b.target) { case PIPE_TEXTURE_3D: - assert(face == 0); - return offset + zslice * rtex->layer_size[level]; case PIPE_TEXTURE_CUBE: - assert(zslice == 0); - return offset + face * rtex->layer_size[level]; + return offset + layer * rtex->layer_size[level]; default: - assert(zslice == 0 && face == 0); + assert(layer == 0); return offset; } } @@ -109,11 +103,11 @@ static unsigned r600_get_pixel_alignment(struct pipe_screen *screen, case V_038000_ARRAY_2D_TILED_THIN1: p_align = MAX2(rscreen->tiling_info->num_banks, (((rscreen->tiling_info->group_bytes / 8 / pixsize)) * - rscreen->tiling_info->num_banks)); + rscreen->tiling_info->num_banks)) * 8; break; - case 0: + case V_038000_ARRAY_LINEAR_GENERAL: default: - p_align = 64; + p_align = rscreen->tiling_info->group_bytes / pixsize; break; } return p_align; @@ -139,6 +133,29 @@ static unsigned r600_get_height_alignment(struct pipe_screen *screen, return h_align; } +static unsigned r600_get_base_alignment(struct pipe_screen *screen, + enum pipe_format format, + unsigned array_mode) +{ + struct r600_screen* rscreen = (struct r600_screen *)screen; + unsigned pixsize = util_format_get_blocksize(format); + int p_align = r600_get_pixel_alignment(screen, format, array_mode); + int h_align = r600_get_height_alignment(screen, array_mode); + int b_align; + + switch (array_mode) { + case V_038000_ARRAY_2D_TILED_THIN1: + b_align = MAX2(rscreen->tiling_info->num_banks * rscreen->tiling_info->num_channels * 8 * 8 * pixsize, + p_align * pixsize * h_align); + break; + case V_038000_ARRAY_1D_TILED_THIN1: + default: + b_align = rscreen->tiling_info->group_bytes; + break; + } + return b_align; +} + static unsigned mip_minify(unsigned size, unsigned level) { unsigned val; @@ -153,10 +170,8 @@ static unsigned r600_texture_get_stride(struct pipe_screen *screen, unsigned level) { struct pipe_resource *ptex = &rtex->resource.base.b; - struct radeon *radeon = (struct radeon *)screen->winsys; - enum chip_class chipc = r600_get_family_class(radeon); unsigned width, stride, tile_width; - + if (rtex->pitch_override) return rtex->pitch_override; @@ -167,11 +182,6 @@ static unsigned r600_texture_get_stride(struct pipe_screen *screen, width = align(width, tile_width); } stride = util_format_get_stride(ptex->format, width); - if (chipc == EVERGREEN) - stride = align(stride, 512); - - if (ptex->bind & PIPE_BIND_RENDER_TARGET) - stride = align(stride, 512); return stride; } @@ -193,11 +203,10 @@ static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen, } /* Get a width in pixels from a stride in bytes. */ -static unsigned pitch_to_width(enum pipe_format format, - unsigned pitch_in_bytes) +static unsigned pitch_to_width(enum pipe_format format, unsigned pitch_in_bytes) { - return (pitch_in_bytes / util_format_get_blocksize(format)) * - util_format_get_blockwidth(format); + return (pitch_in_bytes / util_format_get_blocksize(format)) * + util_format_get_blockwidth(format); } static void r600_texture_set_array_mode(struct pipe_screen *screen, @@ -257,6 +266,9 @@ static void r600_setup_miptree(struct pipe_screen *screen, } else size = layer_size * u_minify(ptex->depth0, i); + /* align base image and start of miptree */ + if ((i == 0) || (i == 1)) + offset = align(offset, r600_get_base_alignment(screen, ptex->format, array_mode)); rtex->offset[i] = offset; rtex->layer_size[i] = layer_size; rtex->pitch_in_bytes[i] = pitch; @@ -297,7 +309,10 @@ r600_texture_create_object(struct pipe_screen *screen, resource->size = rtex->size; if (!resource->bo) { - resource->bo = r600_bo(radeon, rtex->size, 4096, base->bind, base->usage); + struct pipe_resource *ptex = &rtex->resource.base.b; + int base_align = r600_get_base_alignment(screen, ptex->format, array_mode); + + resource->bo = r600_bo(radeon, rtex->size, base_align, base->bind, base->usage); if (!resource->bo) { FREE(rtex); return NULL; @@ -310,12 +325,12 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen, const struct pipe_resource *templ) { unsigned array_mode = 0; - static int force_tiling = -1; + static int force_tiling = -1; - /* Would like some magic "get_bool_option_once" routine. + /* Would like some magic "get_bool_option_once" routine. */ if (force_tiling == -1) - force_tiling = debug_get_bool_option("R600_FORCE_TILING", FALSE); + force_tiling = debug_get_bool_option("R600_FORCE_TILING", FALSE); if (force_tiling) { if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) && @@ -346,8 +361,8 @@ static void r600_texture_destroy(struct pipe_screen *screen, } static boolean r600_texture_get_handle(struct pipe_screen* screen, - struct pipe_resource *ptex, - struct winsys_handle *whandle) + struct pipe_resource *ptex, + struct winsys_handle *whandle) { struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex; struct r600_resource *resource = &rtex->resource; @@ -357,36 +372,39 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen, rtex->pitch_in_bytes[0], whandle); } -static struct pipe_surface *r600_get_tex_surface(struct pipe_screen *screen, +static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, struct pipe_resource *texture, - unsigned face, unsigned level, - unsigned zslice, unsigned flags) + const struct pipe_surface *surf_tmpl) { struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; struct r600_surface *surface = CALLOC_STRUCT(r600_surface); - unsigned offset, tile_height; + unsigned tile_height; + unsigned level = surf_tmpl->u.tex.level; + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); if (surface == NULL) return NULL; - offset = r600_texture_get_offset(rtex, level, zslice, face); + /* XXX no offset */ +/* offset = r600_texture_get_offset(rtex, level, surf_tmpl->u.tex.first_layer);*/ pipe_reference_init(&surface->base.reference, 1); pipe_resource_reference(&surface->base.texture, texture); - surface->base.format = texture->format; + surface->base.context = pipe; + surface->base.format = surf_tmpl->format; surface->base.width = mip_minify(texture->width0, level); surface->base.height = mip_minify(texture->height0, level); - surface->base.offset = offset; - surface->base.usage = flags; - surface->base.zslice = zslice; + surface->base.usage = surf_tmpl->usage; surface->base.texture = texture; - surface->base.face = face; - surface->base.level = level; + surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; + surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; + surface->base.u.tex.level = level; - tile_height = r600_get_height_alignment(screen, rtex->array_mode[level]); + tile_height = r600_get_height_alignment(pipe->screen, rtex->array_mode[level]); surface->aligned_height = align(surface->base.height, tile_height); return &surface->base; } -static void r600_tex_surface_destroy(struct pipe_surface *surface) +static void r600_surface_destroy(struct pipe_context *pipe, + struct pipe_surface *surface) { pipe_resource_reference(&surface->texture, NULL); FREE(surface); @@ -419,7 +437,7 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, static unsigned int r600_texture_is_referenced(struct pipe_context *context, struct pipe_resource *texture, - unsigned face, unsigned level) + unsigned level, int layer) { /* FIXME */ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; @@ -466,7 +484,7 @@ out: */ static INLINE unsigned u_box_volume( const struct pipe_box *box ) { - return box->width * box->depth * box->height; + return box->width * box->depth * box->height; }; @@ -474,44 +492,44 @@ static INLINE unsigned u_box_volume( const struct pipe_box *box ) * If so, don't use a staging resource. */ static boolean permit_hardware_blit(struct pipe_screen *screen, - struct pipe_resource *res) + struct pipe_resource *res) { - unsigned bind; + unsigned bind; - if (util_format_is_depth_or_stencil(res->format)) - bind = PIPE_BIND_DEPTH_STENCIL; - else - bind = PIPE_BIND_RENDER_TARGET; + if (util_format_is_depth_or_stencil(res->format)) + bind = PIPE_BIND_DEPTH_STENCIL; + else + bind = PIPE_BIND_RENDER_TARGET; /* See r600_resource_copy_region: there is something wrong - * with depth resource copies at the moment so avoid them for - * now. - */ + * with depth resource copies at the moment so avoid them for + * now. + */ if (util_format_get_component_bits(res->format, - UTIL_FORMAT_COLORSPACE_ZS, - 0) != 0) - return FALSE; - - if (!screen->is_format_supported(screen, - res->format, - res->target, - res->nr_samples, - bind, 0)) - return FALSE; - - if (!screen->is_format_supported(screen, - res->format, - res->target, - res->nr_samples, - PIPE_BIND_SAMPLER_VIEW, 0)) - return FALSE; - - return TRUE; + UTIL_FORMAT_COLORSPACE_ZS, + 0) != 0) + return FALSE; + + if (!screen->is_format_supported(screen, + res->format, + res->target, + res->nr_samples, + bind, 0)) + return FALSE; + + if (!screen->is_format_supported(screen, + res->format, + res->target, + res->nr_samples, + PIPE_BIND_SAMPLER_VIEW, 0)) + return FALSE; + + return TRUE; } struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, struct pipe_resource *texture, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box) { @@ -531,37 +549,36 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, if (rtex->tiled) use_staging_texture = TRUE; - if ((usage & PIPE_TRANSFER_READ) && - u_box_volume(box) > 1024) - use_staging_texture = TRUE; - - /* XXX: Use a staging texture for uploads if the underlying BO - * is busy. No interface for checking that currently? so do - * it eagerly whenever the transfer doesn't require a readback - * and might block. - */ - if ((usage & PIPE_TRANSFER_WRITE) && - !(usage & (PIPE_TRANSFER_READ | - PIPE_TRANSFER_DONTBLOCK | - PIPE_TRANSFER_UNSYNCHRONIZED))) - use_staging_texture = TRUE; - - if (!permit_hardware_blit(ctx->screen, texture) || - (texture->flags & R600_RESOURCE_FLAG_TRANSFER)) - use_staging_texture = FALSE; + if ((usage & PIPE_TRANSFER_READ) && u_box_volume(box) > 1024) + use_staging_texture = TRUE; + + /* XXX: Use a staging texture for uploads if the underlying BO + * is busy. No interface for checking that currently? so do + * it eagerly whenever the transfer doesn't require a readback + * and might block. + */ + if ((usage & PIPE_TRANSFER_WRITE) && + !(usage & (PIPE_TRANSFER_READ | + PIPE_TRANSFER_DONTBLOCK | + PIPE_TRANSFER_UNSYNCHRONIZED))) + use_staging_texture = TRUE; + + if (!permit_hardware_blit(ctx->screen, texture) || + (texture->flags & R600_RESOURCE_FLAG_TRANSFER)) + use_staging_texture = FALSE; trans = CALLOC_STRUCT(r600_transfer); if (trans == NULL) return NULL; pipe_resource_reference(&trans->transfer.resource, texture); - trans->transfer.sr = sr; + trans->transfer.level = level; trans->transfer.usage = usage; trans->transfer.box = *box; if (rtex->depth) { - /* XXX: only readback the rectangle which is being mapped? - */ - /* XXX: when discard is true, no need to read back from depth texture - */ + /* XXX: only readback the rectangle which is being mapped? + */ + /* XXX: when discard is true, no need to read back from depth texture + */ r = r600_texture_depth_flush(ctx, texture); if (r < 0) { R600_ERR("failed to create temporary texture to hold untiled copy\n"); @@ -575,6 +592,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, resource.width0 = box->width; resource.height0 = box->height; resource.depth0 = 1; + resource.array_size = 1; resource.last_level = 0; resource.nr_samples = 0; resource.usage = PIPE_USAGE_STAGING; @@ -600,7 +618,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, } trans->transfer.stride = - ((struct r600_resource_texture *)trans->staging_texture)->pitch_in_bytes[0]; + ((struct r600_resource_texture *)trans->staging_texture)->pitch_in_bytes[0]; if (usage & PIPE_TRANSFER_READ) { r600_copy_to_staging_texture(ctx, trans); /* Always referenced in the blit. */ @@ -608,8 +626,8 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, } return &trans->transfer; } - trans->transfer.stride = rtex->pitch_in_bytes[sr.level]; - trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face); + trans->transfer.stride = rtex->pitch_in_bytes[level]; + trans->offset = r600_texture_get_offset(rtex, level, box->z); return &trans->transfer; } @@ -722,10 +740,10 @@ struct u_resource_vtbl r600_texture_vtbl = u_default_transfer_inline_write /* transfer_inline_write */ }; -void r600_init_screen_texture_functions(struct pipe_screen *screen) +void r600_init_surface_functions(struct r600_pipe_context *r600) { - screen->get_tex_surface = r600_get_tex_surface; - screen->tex_surface_destroy = r600_tex_surface_destroy; + r600->context.create_surface = r600_create_surface; + r600->context.surface_destroy = r600_surface_destroy; } static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format, @@ -826,8 +844,8 @@ uint32_t r600_translate_texformat(enum pipe_format format, case UTIL_FORMAT_COLORSPACE_YUV: yuv_format |= (1 << 30); switch (format) { - case PIPE_FORMAT_UYVY: - case PIPE_FORMAT_YUYV: + case PIPE_FORMAT_UYVY: + case PIPE_FORMAT_YUYV: default: break; } @@ -845,29 +863,29 @@ uint32_t r600_translate_texformat(enum pipe_format format, /* S3TC formats. TODO */ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { - static int r600_enable_s3tc = -1; + static int r600_enable_s3tc = -1; - if (r600_enable_s3tc == -1) - r600_enable_s3tc = - debug_get_bool_option("R600_ENABLE_S3TC", FALSE); + if (r600_enable_s3tc == -1) + r600_enable_s3tc = + debug_get_bool_option("R600_ENABLE_S3TC", FALSE); - if (!r600_enable_s3tc) - goto out_unknown; + if (!r600_enable_s3tc) + goto out_unknown; switch (format) { case PIPE_FORMAT_DXT1_RGB: case PIPE_FORMAT_DXT1_RGBA: - result = FMT_BC1; - goto out_word4; + result = FMT_BC1; + goto out_word4; case PIPE_FORMAT_DXT3_RGBA: - result = FMT_BC2; - goto out_word4; + result = FMT_BC2; + goto out_word4; case PIPE_FORMAT_DXT5_RGBA: - result = FMT_BC3; - goto out_word4; - default: - goto out_unknown; - } + result = FMT_BC3; + goto out_word4; + default: + goto out_unknown; + } } diff --git a/src/gallium/drivers/r600/r600_translate.c b/src/gallium/drivers/r600/r600_translate.c index 9a07cf2073f..ba12eee2b56 100644 --- a/src/gallium/drivers/r600/r600_translate.c +++ b/src/gallium/drivers/r600/r600_translate.c @@ -41,6 +41,8 @@ void r600_begin_vertex_translate(struct r600_pipe_context *rctx) struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; struct pipe_resource *out_buffer; unsigned i, num_verts; + struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; + void *tmp; /* Initialize the translate key, i.e. the recipe how vertices should be * translated. */ @@ -51,9 +53,7 @@ void r600_begin_vertex_translate(struct r600_pipe_context *rctx) unsigned output_format_size = ve->hw_format_size[i]; /* Check for support. */ - if (ve->elements[i].src_format == ve->hw_format[i] && - (vb->buffer_offset + ve->elements[i].src_offset) % 4 == 0 && - vb->stride % 4 == 0) { + if (ve->elements[i].src_format == ve->hw_format[i]) { continue; } @@ -147,29 +147,23 @@ void r600_begin_vertex_translate(struct r600_pipe_context *rctx) } /* Save and replace vertex elements. */ - { - struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; - - rctx->tran.saved_velems = rctx->vertex_elements; - - for (i = 0; i < ve->count; i++) { - if (vb_translated[ve->elements[i].vertex_buffer_index]) { - te = &key.element[tr_elem_index[i]]; - new_velems[i].instance_divisor = ve->elements[i].instance_divisor; - new_velems[i].src_format = te->output_format; - new_velems[i].src_offset = te->output_offset; - new_velems[i].vertex_buffer_index = rctx->tran.vb_slot; - } else { - memcpy(&new_velems[i], &ve->elements[i], - sizeof(struct pipe_vertex_element)); - } + for (i = 0; i < ve->count; i++) { + if (vb_translated[ve->elements[i].vertex_buffer_index]) { + te = &key.element[tr_elem_index[i]]; + new_velems[i].instance_divisor = ve->elements[i].instance_divisor; + new_velems[i].src_format = te->output_format; + new_velems[i].src_offset = te->output_offset; + new_velems[i].vertex_buffer_index = rctx->tran.vb_slot; + } else { + memcpy(&new_velems[i], &ve->elements[i], + sizeof(struct pipe_vertex_element)); } - - rctx->tran.new_velems = - pipe->create_vertex_elements_state(pipe, ve->count, new_velems); - pipe->bind_vertex_elements_state(pipe, rctx->tran.new_velems); } + tmp = pipe->create_vertex_elements_state(pipe, ve->count, new_velems); + pipe->bind_vertex_elements_state(pipe, tmp); + rctx->tran.new_velems = tmp; + pipe_resource_reference(&out_buffer, NULL); } @@ -177,13 +171,15 @@ void r600_end_vertex_translate(struct r600_pipe_context *rctx) { struct pipe_context *pipe = &rctx->context; + if (rctx->tran.new_velems == NULL) { + return; + } /* Restore vertex elements. */ - pipe->bind_vertex_elements_state(pipe, rctx->tran.saved_velems); pipe->delete_vertex_elements_state(pipe, rctx->tran.new_velems); + rctx->tran.new_velems = NULL; /* Delete the now-unused VBO. */ - pipe_resource_reference(&rctx->vertex_buffer[rctx->tran.vb_slot].buffer, - NULL); + pipe_resource_reference(&rctx->vertex_buffer[rctx->tran.vb_slot].buffer, NULL); } void r600_translate_index_buffer(struct r600_pipe_context *r600, @@ -197,14 +193,7 @@ void r600_translate_index_buffer(struct r600_pipe_context *r600, *index_size = 2; *start = 0; break; - case 2: - if (*start % 2 != 0) { - util_rebuild_ushort_elts(&r600->context, index_buffer, 0, *start, count); - *start = 0; - } - break; - case 4: break; } diff --git a/src/gallium/drivers/r600/r600_upload.c b/src/gallium/drivers/r600/r600_upload.c new file mode 100644 index 00000000000..44102ff55b6 --- /dev/null +++ b/src/gallium/drivers/r600/r600_upload.c @@ -0,0 +1,114 @@ +/* + * Copyright 2010 Jerome Glisse <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jerome Glisse <[email protected]> + */ +#include <errno.h> +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "r600.h" +#include "r600_pipe.h" +#include "r600_resource.h" + +struct r600_upload { + struct r600_pipe_context *rctx; + struct r600_bo *buffer; + char *ptr; + unsigned size; + unsigned default_size; + unsigned total_alloc_size; + unsigned offset; + unsigned alignment; +}; + +struct r600_upload *r600_upload_create(struct r600_pipe_context *rctx, + unsigned default_size, + unsigned alignment) +{ + struct r600_upload *upload = CALLOC_STRUCT(r600_upload); + + if (upload == NULL) + return NULL; + + upload->rctx = rctx; + upload->size = 0; + upload->default_size = default_size; + upload->alignment = alignment; + upload->ptr = NULL; + upload->buffer = NULL; + upload->total_alloc_size = 0; + + return upload; +} + +void r600_upload_flush(struct r600_upload *upload) +{ + if (upload->buffer) { + r600_bo_reference(upload->rctx->radeon, &upload->buffer, NULL); + } + upload->default_size = MAX2(upload->total_alloc_size, upload->default_size); + upload->total_alloc_size = 0; + upload->size = 0; + upload->offset = 0; + upload->ptr = NULL; + upload->buffer = NULL; +} + +void r600_upload_destroy(struct r600_upload *upload) +{ + r600_upload_flush(upload); + FREE(upload); +} + +int r600_upload_buffer(struct r600_upload *upload, unsigned offset, + unsigned size, struct r600_resource_buffer *in_buffer, + unsigned *out_offset, unsigned *out_size, + struct r600_bo **out_buffer) +{ + unsigned alloc_size = align(size, upload->alignment); + const void *in_ptr = NULL; + + if (upload->offset + alloc_size > upload->size) { + if (upload->size) { + r600_bo_reference(upload->rctx->radeon, &upload->buffer, NULL); + } + upload->size = align(MAX2(upload->default_size, alloc_size), 4096); + upload->total_alloc_size += upload->size; + upload->offset = 0; + upload->buffer = r600_bo(upload->rctx->radeon, upload->size, 4096, PIPE_BIND_VERTEX_BUFFER, 0); + if (upload->buffer == NULL) { + return -ENOMEM; + } + upload->ptr = r600_bo_map(upload->rctx->radeon, upload->buffer, 0, NULL); + } + + in_ptr = in_buffer->user_buffer; + memcpy(upload->ptr + upload->offset, (uint8_t *) in_ptr + offset, size); + *out_offset = upload->offset; + *out_size = upload->size; + *out_buffer = NULL; + r600_bo_reference(upload->rctx->radeon, out_buffer, upload->buffer); + upload->offset += alloc_size; + + return 0; +} diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c index 413da59e559..94e57e40f86 100644 --- a/src/gallium/drivers/rbug/rbug_context.c +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -707,17 +707,13 @@ rbug_set_sample_mask(struct pipe_context *_pipe, static void rbug_resource_copy_region(struct pipe_context *_pipe, struct pipe_resource *_dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *_src, - struct pipe_subresource subsrc, - unsigned srcx, - unsigned srcy, - unsigned srcz, - unsigned width, - unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { struct rbug_context *rb_pipe = rbug_context(_pipe); struct rbug_resource *rb_resource_dst = rbug_resource(_dst); @@ -728,17 +724,13 @@ rbug_resource_copy_region(struct pipe_context *_pipe, pipe->resource_copy_region(pipe, dst, - subdst, + dst_level, dstx, dsty, dstz, src, - subsrc, - srcx, - srcy, - srcz, - width, - height); + src_level, + src_box); } static void @@ -820,8 +812,8 @@ rbug_flush(struct pipe_context *_pipe, static unsigned int rbug_is_resource_referenced(struct pipe_context *_pipe, struct pipe_resource *_resource, - unsigned face, - unsigned level) + unsigned level, + int layer) { struct rbug_context *rb_pipe = rbug_context(_pipe); struct rbug_resource *rb_resource = rbug_resource(_resource); @@ -830,8 +822,8 @@ rbug_is_resource_referenced(struct pipe_context *_pipe, return pipe->is_resource_referenced(pipe, resource, - face, - level); + level, + layer); } static struct pipe_sampler_view * @@ -862,10 +854,40 @@ rbug_context_sampler_view_destroy(struct pipe_context *_pipe, rbug_sampler_view(_view)); } +static struct pipe_surface * +rbug_context_create_surface(struct pipe_context *_pipe, + struct pipe_resource *_resource, + const struct pipe_surface *surf_tmpl) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + struct pipe_surface *result; + + result = pipe->create_surface(pipe, + resource, + surf_tmpl); + + if (result) + return rbug_surface_create(rb_pipe, rb_resource, result); + return NULL; +} + +static void +rbug_context_surface_destroy(struct pipe_context *_pipe, + struct pipe_surface *_surface) +{ + rbug_surface_destroy(rbug_context(_pipe), + rbug_surface(_surface)); +} + + + static struct pipe_transfer * rbug_context_get_transfer(struct pipe_context *_context, struct pipe_resource *_resource, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box) { @@ -877,7 +899,7 @@ rbug_context_get_transfer(struct pipe_context *_context, result = context->get_transfer(context, resource, - sr, + level, usage, box); @@ -942,12 +964,12 @@ rbug_context_transfer_unmap(struct pipe_context *_context, static void rbug_context_transfer_inline_write(struct pipe_context *_context, struct pipe_resource *_resource, - struct pipe_subresource sr, + unsigned level, unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, - unsigned slice_stride) + unsigned layer_stride) { struct rbug_context *rb_pipe = rbug_context(_context); struct rbug_resource *rb_resource = rbug_resource(_resource); @@ -956,12 +978,12 @@ rbug_context_transfer_inline_write(struct pipe_context *_context, context->transfer_inline_write(context, resource, - sr, + level, usage, box, data, stride, - slice_stride); + layer_stride); } @@ -1042,6 +1064,8 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) rb_pipe->base.is_resource_referenced = rbug_is_resource_referenced; rb_pipe->base.create_sampler_view = rbug_context_create_sampler_view; rb_pipe->base.sampler_view_destroy = rbug_context_sampler_view_destroy; + rb_pipe->base.create_surface = rbug_context_create_surface; + rb_pipe->base.surface_destroy = rbug_context_surface_destroy; rb_pipe->base.get_transfer = rbug_context_get_transfer; rb_pipe->base.transfer_destroy = rbug_context_transfer_destroy; rb_pipe->base.transfer_map = rbug_context_transfer_map; diff --git a/src/gallium/drivers/rbug/rbug_core.c b/src/gallium/drivers/rbug/rbug_core.c index 9dc663b079a..eb772d19d05 100644 --- a/src/gallium/drivers/rbug/rbug_core.c +++ b/src/gallium/drivers/rbug/rbug_core.c @@ -266,9 +266,9 @@ rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_ tex = tr_tex->resource; t = pipe_get_transfer(context, tex, - gptr->face, gptr->level, gptr->zslice, - PIPE_TRANSFER_READ, - gptr->x, gptr->y, gptr->w, gptr->h); + gptr->level, gptr->face + gptr->zslice, + PIPE_TRANSFER_READ, + gptr->x, gptr->y, gptr->w, gptr->h); map = context->transfer_map(context, t); @@ -279,7 +279,7 @@ rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_ util_format_get_blocksize(t->resource->format), (uint8_t*)map, t->stride * util_format_get_nblocksy(t->resource->format, - t->box.height), + t->box.height), t->stride, NULL); diff --git a/src/gallium/drivers/rbug/rbug_objects.c b/src/gallium/drivers/rbug/rbug_objects.c index 0979fcff957..7d7cc482ae6 100644 --- a/src/gallium/drivers/rbug/rbug_objects.c +++ b/src/gallium/drivers/rbug/rbug_objects.c @@ -79,7 +79,8 @@ rbug_resource_destroy(struct rbug_resource *rb_resource) struct pipe_surface * -rbug_surface_create(struct rbug_resource *rb_resource, +rbug_surface_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, struct pipe_surface *surface) { struct rbug_surface *rb_surface; @@ -108,10 +109,12 @@ error: } void -rbug_surface_destroy(struct rbug_surface *rb_surface) +rbug_surface_destroy(struct rbug_context *rb_context, + struct rbug_surface *rb_surface) { pipe_resource_reference(&rb_surface->base.texture, NULL); - pipe_surface_reference(&rb_surface->surface, NULL); + rb_context->pipe->surface_destroy(rb_context->pipe, + rb_surface->surface); FREE(rb_surface); } diff --git a/src/gallium/drivers/rbug/rbug_objects.h b/src/gallium/drivers/rbug/rbug_objects.h index 49c128d3d1a..3fba3334228 100644 --- a/src/gallium/drivers/rbug/rbug_objects.h +++ b/src/gallium/drivers/rbug/rbug_objects.h @@ -189,11 +189,13 @@ void rbug_resource_destroy(struct rbug_resource *rb_resource); struct pipe_surface * -rbug_surface_create(struct rbug_resource *rb_resource, +rbug_surface_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, struct pipe_surface *surface); void -rbug_surface_destroy(struct rbug_surface *rb_surface); +rbug_surface_destroy(struct rbug_context *rb_context, + struct rbug_surface *rb_surface); struct pipe_sampler_view * rbug_sampler_view_create(struct rbug_context *rb_context, diff --git a/src/gallium/drivers/rbug/rbug_screen.c b/src/gallium/drivers/rbug/rbug_screen.c index 961df482c29..d635ce575c0 100644 --- a/src/gallium/drivers/rbug/rbug_screen.c +++ b/src/gallium/drivers/rbug/rbug_screen.c @@ -188,40 +188,6 @@ rbug_screen_resource_destroy(struct pipe_screen *screen, rbug_resource_destroy(rbug_resource(_resource)); } -static struct pipe_surface * -rbug_screen_get_tex_surface(struct pipe_screen *_screen, - struct pipe_resource *_resource, - unsigned face, - unsigned level, - unsigned zslice, - unsigned usage) -{ - struct rbug_screen *rb_screen = rbug_screen(_screen); - struct rbug_resource *rb_resource = rbug_resource(_resource); - struct pipe_screen *screen = rb_screen->screen; - struct pipe_resource *resource = rb_resource->resource; - struct pipe_surface *result; - - result = screen->get_tex_surface(screen, - resource, - face, - level, - zslice, - usage); - - if (result) - return rbug_surface_create(rb_resource, result); - return NULL; -} - -static void -rbug_screen_tex_surface_destroy(struct pipe_surface *_surface) -{ - rbug_surface_destroy(rbug_surface(_surface)); -} - - - static struct pipe_resource * rbug_screen_user_buffer_create(struct pipe_screen *_screen, void *ptr, @@ -246,16 +212,18 @@ rbug_screen_user_buffer_create(struct pipe_screen *_screen, static void rbug_screen_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_surface *_surface, + struct pipe_resource *_resource, + unsigned level, unsigned layer, void *context_private) { struct rbug_screen *rb_screen = rbug_screen(_screen); - struct rbug_surface *rb_surface = rbug_surface(_surface); + struct rbug_resource *rb_resource = rbug_resource(_resource); struct pipe_screen *screen = rb_screen->screen; - struct pipe_surface *surface = rb_surface->surface; + struct pipe_resource *resource = rb_resource->resource; screen->flush_frontbuffer(screen, - surface, + resource, + level, layer, context_private); } @@ -336,8 +304,6 @@ rbug_screen_create(struct pipe_screen *screen) rb_screen->base.resource_from_handle = rbug_screen_resource_from_handle; rb_screen->base.resource_get_handle = rbug_screen_resource_get_handle; rb_screen->base.resource_destroy = rbug_screen_resource_destroy; - rb_screen->base.get_tex_surface = rbug_screen_get_tex_surface; - rb_screen->base.tex_surface_destroy = rbug_screen_tex_surface_destroy; rb_screen->base.user_buffer_create = rbug_screen_user_buffer_create; rb_screen->base.flush_frontbuffer = rbug_screen_flush_frontbuffer; rb_screen->base.fence_reference = rbug_screen_fence_reference; diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index b5d30bc6fc9..e935ce6d21b 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -145,15 +145,15 @@ softpipe_destroy( struct pipe_context *pipe ) */ static unsigned int softpipe_is_resource_referenced( struct pipe_context *pipe, - struct pipe_resource *texture, - unsigned face, unsigned level) + struct pipe_resource *texture, + unsigned level, int layer) { struct softpipe_context *softpipe = softpipe_context( pipe ); unsigned i; if (texture->target == PIPE_BUFFER) return PIPE_UNREFERENCED; - + /* check if any of the bound drawing surfaces are this texture */ if (softpipe->dirty_render_cache) { for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) { diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 9361a3df09e..903574b7e19 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -154,9 +154,9 @@ struct softpipe_context { /** TGSI exec things */ struct { - struct sp_sampler_varient *geom_samplers_list[PIPE_MAX_GEOMETRY_SAMPLERS]; - struct sp_sampler_varient *vert_samplers_list[PIPE_MAX_VERTEX_SAMPLERS]; - struct sp_sampler_varient *frag_samplers_list[PIPE_MAX_SAMPLERS]; + struct sp_sampler_variant *geom_samplers_list[PIPE_MAX_GEOMETRY_SAMPLERS]; + struct sp_sampler_variant *vert_samplers_list[PIPE_MAX_VERTEX_SAMPLERS]; + struct sp_sampler_variant *frag_samplers_list[PIPE_MAX_SAMPLERS]; } tgsi; struct tgsi_exec_machine *fs_machine; @@ -192,7 +192,7 @@ softpipe_context( struct pipe_context *pipe ) } void -softpipe_reset_sampler_varients(struct softpipe_context *softpipe); +softpipe_reset_sampler_variants(struct softpipe_context *softpipe); struct pipe_context * softpipe_create_context( struct pipe_screen *, void *priv ); diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index 1071011db0e..4258395063b 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -120,8 +120,8 @@ softpipe_flush( struct pipe_context *pipe, boolean softpipe_flush_resource(struct pipe_context *pipe, struct pipe_resource *texture, - unsigned face, unsigned level, + int layer, unsigned flush_flags, boolean read_only, boolean cpu_access, @@ -129,7 +129,7 @@ softpipe_flush_resource(struct pipe_context *pipe, { unsigned referenced; - referenced = pipe->is_resource_referenced(pipe, texture, face, level); + referenced = pipe->is_resource_referenced(pipe, texture, level, layer); if ((referenced & PIPE_REFERENCED_FOR_WRITE) || ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) { diff --git a/src/gallium/drivers/softpipe/sp_flush.h b/src/gallium/drivers/softpipe/sp_flush.h index cb97482a71b..22a5ceeb9ec 100644 --- a/src/gallium/drivers/softpipe/sp_flush.h +++ b/src/gallium/drivers/softpipe/sp_flush.h @@ -40,8 +40,8 @@ softpipe_flush(struct pipe_context *pipe, unsigned flags, boolean softpipe_flush_resource(struct pipe_context *pipe, struct pipe_resource *texture, - unsigned face, unsigned level, + int layer, unsigned flush_flags, boolean read_only, boolean cpu_access, diff --git a/src/gallium/drivers/softpipe/sp_limits.h b/src/gallium/drivers/softpipe/sp_limits.h new file mode 100644 index 00000000000..a7a24c98d57 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_limits.h @@ -0,0 +1,42 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SP_LIMITS_H +#define SP_LIMITS_H + + + +#define SP_MAX_TEXTURE_2D_LEVELS 15 /* 16K x 16K */ +#define SP_MAX_TEXTURE_3D_LEVELS 9 /* 512 x 512 x 512 */ + + +/** Max surface size */ +#define MAX_WIDTH (1 << (SP_MAX_TEXTURE_2D_LEVELS - 1)) +#define MAX_HEIGHT (1 << (SP_MAX_TEXTURE_2D_LEVELS - 1)) + + +#endif /* SP_LIMITS_H */ diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 5f171d314a3..cbdea19af43 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -266,12 +266,13 @@ softpipe_destroy_screen( struct pipe_screen *screen ) */ static void softpipe_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_surface *surface, + struct pipe_resource *resource, + unsigned level, unsigned layer, void *context_private) { struct softpipe_screen *screen = softpipe_screen(_screen); struct sw_winsys *winsys = screen->winsys; - struct softpipe_resource *texture = softpipe_resource(surface->texture); + struct softpipe_resource *texture = softpipe_resource(resource); assert(texture->dt); if (texture->dt) diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c index 3ba4d934fd2..bf4c12701af 100644 --- a/src/gallium/drivers/softpipe/sp_state_derived.c +++ b/src/gallium/drivers/softpipe/sp_state_derived.c @@ -197,7 +197,7 @@ update_tgsi_samplers( struct softpipe_context *softpipe ) { unsigned i; - softpipe_reset_sampler_varients( softpipe ); + softpipe_reset_sampler_variants( softpipe ); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[i]; diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index b59fbc33ed6..cfa211b60a0 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -43,8 +43,8 @@ struct sp_sampler { struct pipe_sampler_state base; - struct sp_sampler_varient *varients; - struct sp_sampler_varient *current; + struct sp_sampler_variant *variants; + struct sp_sampler_variant *current; }; static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler ) @@ -60,7 +60,7 @@ softpipe_create_sampler_state(struct pipe_context *pipe, struct sp_sampler *sp_sampler = CALLOC_STRUCT(sp_sampler); sp_sampler->base = *sampler; - sp_sampler->varients = NULL; + sp_sampler->variants = NULL; return (void *)sp_sampler; } @@ -277,23 +277,24 @@ softpipe_set_geometry_sampler_views(struct pipe_context *pipe, /** - * Find/create an sp_sampler_varient object for sampling the given texture, + * Find/create an sp_sampler_variant object for sampling the given texture, * sampler and tex unit. * * Note that the tex unit is significant. We can't re-use a sampler - * varient for multiple texture units because the sampler varient contains + * variant for multiple texture units because the sampler variant contains * the texture object pointer. If the texture object pointer were stored - * somewhere outside the sampler varient, we could re-use samplers for + * somewhere outside the sampler variant, we could re-use samplers for * multiple texture units. */ -static struct sp_sampler_varient * -get_sampler_varient( unsigned unit, +static struct sp_sampler_variant * +get_sampler_variant( unsigned unit, struct sp_sampler *sampler, + struct pipe_sampler_view *view, struct pipe_resource *resource, unsigned processor ) { struct softpipe_resource *sp_texture = softpipe_resource(resource); - struct sp_sampler_varient *v = NULL; + struct sp_sampler_variant *v = NULL; union sp_sampler_key key; /* if this fails, widen the key.unit field and update this assertion */ @@ -303,6 +304,10 @@ get_sampler_varient( unsigned unit, key.bits.is_pot = sp_texture->pot; key.bits.processor = processor; key.bits.unit = unit; + key.bits.swizzle_r = view->swizzle_r; + key.bits.swizzle_g = view->swizzle_g; + key.bits.swizzle_b = view->swizzle_b; + key.bits.swizzle_a = view->swizzle_a; key.bits.pad = 0; if (sampler->current && @@ -311,14 +316,14 @@ get_sampler_varient( unsigned unit, } if (v == NULL) { - for (v = sampler->varients; v; v = v->next) + for (v = sampler->variants; v; v = v->next) if (v->key.value == key.value) break; if (v == NULL) { - v = sp_create_sampler_varient( &sampler->base, key ); - v->next = sampler->varients; - sampler->varients = v; + v = sp_create_sampler_variant( &sampler->base, key ); + v->next = sampler->variants; + sampler->variants = v; } } @@ -328,7 +333,7 @@ get_sampler_varient( unsigned unit, void -softpipe_reset_sampler_varients(struct softpipe_context *softpipe) +softpipe_reset_sampler_variants(struct softpipe_context *softpipe) { int i; @@ -345,12 +350,13 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) } softpipe->tgsi.vert_samplers_list[i] = - get_sampler_varient( i, + get_sampler_variant( i, sp_sampler(softpipe->vertex_samplers[i]), + softpipe->vertex_sampler_views[i], texture, TGSI_PROCESSOR_VERTEX ); - sp_sampler_varient_bind_texture( softpipe->tgsi.vert_samplers_list[i], + sp_sampler_variant_bind_texture( softpipe->tgsi.vert_samplers_list[i], softpipe->vertex_tex_cache[i], texture ); } @@ -366,13 +372,14 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) } softpipe->tgsi.geom_samplers_list[i] = - get_sampler_varient( + get_sampler_variant( i, sp_sampler(softpipe->geometry_samplers[i]), + softpipe->geometry_sampler_views[i], texture, TGSI_PROCESSOR_GEOMETRY ); - sp_sampler_varient_bind_texture( + sp_sampler_variant_bind_texture( softpipe->tgsi.geom_samplers_list[i], softpipe->geometry_tex_cache[i], texture ); @@ -389,12 +396,13 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) } softpipe->tgsi.frag_samplers_list[i] = - get_sampler_varient( i, + get_sampler_variant( i, sp_sampler(softpipe->sampler[i]), + softpipe->sampler_views[i], texture, TGSI_PROCESSOR_FRAGMENT ); - sp_sampler_varient_bind_texture( softpipe->tgsi.frag_samplers_list[i], + sp_sampler_variant_bind_texture( softpipe->tgsi.frag_samplers_list[i], softpipe->tex_cache[i], texture ); } @@ -406,11 +414,11 @@ softpipe_delete_sampler_state(struct pipe_context *pipe, void *sampler) { struct sp_sampler *sp_sampler = (struct sp_sampler *)sampler; - struct sp_sampler_varient *v, *tmp; + struct sp_sampler_variant *v, *tmp; - for (v = sp_sampler->varients; v; v = tmp) { + for (v = sp_sampler->variants; v; v = tmp) { tmp = v->next; - sp_sampler_varient_destroy(v); + sp_sampler_variant_destroy(v); } FREE( sampler ); diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 2eac4c7a82b..cbc40d4b446 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -545,7 +545,7 @@ wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size, * derivatives w.r.t X and Y, then compute lambda (level of detail). */ static float -compute_lambda_1d(const struct sp_sampler_varient *samp, +compute_lambda_1d(const struct sp_sampler_variant *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE]) @@ -560,7 +560,7 @@ compute_lambda_1d(const struct sp_sampler_varient *samp, static float -compute_lambda_2d(const struct sp_sampler_varient *samp, +compute_lambda_2d(const struct sp_sampler_variant *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE]) @@ -579,7 +579,7 @@ compute_lambda_2d(const struct sp_sampler_varient *samp, static float -compute_lambda_3d(const struct sp_sampler_varient *samp, +compute_lambda_3d(const struct sp_sampler_variant *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE]) @@ -608,7 +608,7 @@ compute_lambda_3d(const struct sp_sampler_varient *samp, * Since there aren't derivatives to use, just return 0. */ static float -compute_lambda_vert(const struct sp_sampler_varient *samp, +compute_lambda_vert(const struct sp_sampler_variant *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE]) @@ -634,7 +634,7 @@ compute_lambda_vert(const struct sp_sampler_varient *samp, static INLINE const float * -get_texel_2d_no_border(const struct sp_sampler_varient *samp, +get_texel_2d_no_border(const struct sp_sampler_variant *samp, union tex_tile_address addr, int x, int y) { const struct softpipe_tex_cached_tile *tile; @@ -651,7 +651,7 @@ get_texel_2d_no_border(const struct sp_sampler_varient *samp, static INLINE const float * -get_texel_2d(const struct sp_sampler_varient *samp, +get_texel_2d(const struct sp_sampler_variant *samp, union tex_tile_address addr, int x, int y) { const struct pipe_resource *texture = samp->texture; @@ -659,8 +659,7 @@ get_texel_2d(const struct sp_sampler_varient *samp, if (x < 0 || x >= (int) u_minify(texture->width0, level) || y < 0 || y >= (int) u_minify(texture->height0, level)) { - return sp_tex_tile_cache_border_color(samp->cache, - samp->sampler->border_color); + return samp->sampler->border_color; } else { return get_texel_2d_no_border( samp, addr, x, y ); @@ -671,7 +670,7 @@ get_texel_2d(const struct sp_sampler_varient *samp, /* Gather a quad of adjacent texels within a tile: */ static INLINE void -get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_varient *samp, +get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_variant *samp, union tex_tile_address addr, unsigned x, unsigned y, const float *out[4]) @@ -695,7 +694,7 @@ get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_varient *samp, /* Gather a quad of potentially non-adjacent texels: */ static INLINE void -get_texel_quad_2d_no_border(const struct sp_sampler_varient *samp, +get_texel_quad_2d_no_border(const struct sp_sampler_variant *samp, union tex_tile_address addr, int x0, int y0, int x1, int y1, @@ -710,7 +709,7 @@ get_texel_quad_2d_no_border(const struct sp_sampler_varient *samp, /* Can involve a lot of unnecessary checks for border color: */ static INLINE void -get_texel_quad_2d(const struct sp_sampler_varient *samp, +get_texel_quad_2d(const struct sp_sampler_variant *samp, union tex_tile_address addr, int x0, int y0, int x1, int y1, @@ -724,10 +723,10 @@ get_texel_quad_2d(const struct sp_sampler_varient *samp, -/* 3d varients: +/* 3d variants: */ static INLINE const float * -get_texel_3d_no_border(const struct sp_sampler_varient *samp, +get_texel_3d_no_border(const struct sp_sampler_variant *samp, union tex_tile_address addr, int x, int y, int z) { const struct softpipe_tex_cached_tile *tile; @@ -745,7 +744,7 @@ get_texel_3d_no_border(const struct sp_sampler_varient *samp, static INLINE const float * -get_texel_3d(const struct sp_sampler_varient *samp, +get_texel_3d(const struct sp_sampler_variant *samp, union tex_tile_address addr, int x, int y, int z) { const struct pipe_resource *texture = samp->texture; @@ -754,8 +753,7 @@ get_texel_3d(const struct sp_sampler_varient *samp, if (x < 0 || x >= (int) u_minify(texture->width0, level) || y < 0 || y >= (int) u_minify(texture->height0, level) || z < 0 || z >= (int) u_minify(texture->depth0, level)) { - return sp_tex_tile_cache_border_color(samp->cache, - samp->sampler->border_color); + return samp->sampler->border_color; } else { return get_texel_3d_no_border( samp, addr, x, y, z ); @@ -800,7 +798,7 @@ img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); unsigned j; unsigned level = samp->level; unsigned xpot = pot_level_size(samp->xpot, level); @@ -863,7 +861,7 @@ img_filter_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); unsigned j; unsigned level = samp->level; unsigned xpot = pot_level_size(samp->xpot, level); @@ -907,7 +905,7 @@ img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); unsigned j; unsigned level = samp->level; unsigned xpot = pot_level_size(samp->xpot, level); @@ -960,7 +958,7 @@ img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; unsigned level0, j; int width; @@ -1000,7 +998,7 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; unsigned level0, j; int width, height; @@ -1052,7 +1050,7 @@ img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; const unsigned *faces = samp->faces; /* zero when not cube-mapping */ unsigned level0, j; @@ -1096,7 +1094,7 @@ img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; unsigned level0, j; int width, height, depth; @@ -1138,7 +1136,7 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; unsigned level0, j; int width; @@ -1178,7 +1176,7 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; unsigned level0, j; int width, height; @@ -1225,7 +1223,7 @@ img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; const unsigned *faces = samp->faces; /* zero when not cube-mapping */ unsigned level0, j; @@ -1274,7 +1272,7 @@ img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; unsigned level0, j; int width, height, depth; @@ -1350,7 +1348,7 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; int level0; float lambda; @@ -1417,7 +1415,7 @@ mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; float lambda; float lod[QUAD_SIZE]; @@ -1460,7 +1458,7 @@ mip_filter_none(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); float lambda; float lod[QUAD_SIZE]; @@ -1501,7 +1499,7 @@ mip_filter_linear_2d_linear_repeat_POT( enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_resource *texture = samp->texture; int level0; float lambda; @@ -1569,7 +1567,7 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); const struct pipe_sampler_state *sampler = samp->sampler; int j, k0, k1, k2, k3; float val; @@ -1656,7 +1654,7 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { - struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); + struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); unsigned j; float ssss[4], tttt[4]; @@ -1731,6 +1729,86 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, } +static void +sample_swizzle(struct tgsi_sampler *tgsi_sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ + struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); + float rgba_temp[NUM_CHANNELS][QUAD_SIZE]; + const unsigned swizzle_r = samp->key.bits.swizzle_r; + const unsigned swizzle_g = samp->key.bits.swizzle_g; + const unsigned swizzle_b = samp->key.bits.swizzle_b; + const unsigned swizzle_a = samp->key.bits.swizzle_a; + unsigned j; + + samp->sample_target(tgsi_sampler, s, t, p, c0, control, rgba_temp); + + switch (swizzle_r) { + case PIPE_SWIZZLE_ZERO: + for (j = 0; j < 4; j++) + rgba[0][j] = 0.0f; + break; + case PIPE_SWIZZLE_ONE: + for (j = 0; j < 4; j++) + rgba[0][j] = 1.0f; + break; + default: + assert(swizzle_r < 4); + for (j = 0; j < 4; j++) + rgba[0][j] = rgba_temp[swizzle_r][j]; + } + + switch (swizzle_g) { + case PIPE_SWIZZLE_ZERO: + for (j = 0; j < 4; j++) + rgba[1][j] = 0.0f; + break; + case PIPE_SWIZZLE_ONE: + for (j = 0; j < 4; j++) + rgba[1][j] = 1.0f; + break; + default: + assert(swizzle_g < 4); + for (j = 0; j < 4; j++) + rgba[1][j] = rgba_temp[swizzle_g][j]; + } + + switch (swizzle_b) { + case PIPE_SWIZZLE_ZERO: + for (j = 0; j < 4; j++) + rgba[2][j] = 0.0f; + break; + case PIPE_SWIZZLE_ONE: + for (j = 0; j < 4; j++) + rgba[2][j] = 1.0f; + break; + default: + assert(swizzle_b < 4); + for (j = 0; j < 4; j++) + rgba[2][j] = rgba_temp[swizzle_b][j]; + } + + switch (swizzle_a) { + case PIPE_SWIZZLE_ZERO: + for (j = 0; j < 4; j++) + rgba[3][j] = 0.0f; + break; + case PIPE_SWIZZLE_ONE: + for (j = 0; j < 4; j++) + rgba[3][j] = 1.0f; + break; + default: + assert(swizzle_a < 4); + for (j = 0; j < 4; j++) + rgba[3][j] = rgba_temp[swizzle_a][j]; + } +} + static wrap_nearest_func get_nearest_unorm_wrap(unsigned mode) @@ -1909,10 +1987,10 @@ get_img_filter(const union sp_sampler_key key, /** - * Bind the given texture object and texture cache to the sampler varient. + * Bind the given texture object and texture cache to the sampler variant. */ void -sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp, +sp_sampler_variant_bind_texture( struct sp_sampler_variant *samp, struct softpipe_tex_tile_cache *tex_cache, const struct pipe_resource *texture ) { @@ -1927,20 +2005,20 @@ sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp, void -sp_sampler_varient_destroy( struct sp_sampler_varient *samp ) +sp_sampler_variant_destroy( struct sp_sampler_variant *samp ) { FREE(samp); } /** - * Create a sampler varient for a given set of non-orthogonal state. + * Create a sampler variant for a given set of non-orthogonal state. */ -struct sp_sampler_varient * -sp_create_sampler_varient( const struct pipe_sampler_state *sampler, +struct sp_sampler_variant * +sp_create_sampler_variant( const struct pipe_sampler_state *sampler, const union sp_sampler_key key ) { - struct sp_sampler_varient *samp = CALLOC_STRUCT(sp_sampler_varient); + struct sp_sampler_variant *samp = CALLOC_STRUCT(sp_sampler_variant); if (!samp) return NULL; @@ -2015,7 +2093,7 @@ sp_create_sampler_varient( const struct pipe_sampler_state *sampler, } if (key.bits.target == PIPE_TEXTURE_CUBE) { - samp->base.get_samples = sample_cube; + samp->sample_target = sample_cube; } else { samp->faces[0] = 0; @@ -2026,7 +2104,17 @@ sp_create_sampler_varient( const struct pipe_sampler_state *sampler, /* Skip cube face determination by promoting the compare * function pointer: */ - samp->base.get_samples = samp->compare; + samp->sample_target = samp->compare; + } + + if (key.bits.swizzle_r != PIPE_SWIZZLE_RED || + key.bits.swizzle_g != PIPE_SWIZZLE_GREEN || + key.bits.swizzle_b != PIPE_SWIZZLE_BLUE || + key.bits.swizzle_a != PIPE_SWIZZLE_ALPHA) { + samp->base.get_samples = sample_swizzle; + } + else { + samp->base.get_samples = samp->sample_target; } return samp; diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.h b/src/gallium/drivers/softpipe/sp_tex_sample.h index 6114acf7371..ed99006ab02 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.h +++ b/src/gallium/drivers/softpipe/sp_tex_sample.h @@ -32,7 +32,7 @@ #include "tgsi/tgsi_exec.h" -struct sp_sampler_varient; +struct sp_sampler_variant; typedef void (*wrap_nearest_func)(const float s[4], unsigned size, @@ -44,7 +44,7 @@ typedef void (*wrap_linear_func)(const float s[4], int icoord1[4], float w[4]); -typedef float (*compute_lambda_func)(const struct sp_sampler_varient *sampler, +typedef float (*compute_lambda_func)(const struct sp_sampler_variant *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE]); @@ -64,7 +64,11 @@ union sp_sampler_key { unsigned is_pot:1; unsigned processor:2; unsigned unit:4; - unsigned pad:22; + unsigned swizzle_r:3; + unsigned swizzle_g:3; + unsigned swizzle_b:3; + unsigned swizzle_a:3; + unsigned pad:10; } bits; unsigned value; }; @@ -72,7 +76,7 @@ union sp_sampler_key { /** * Subclass of tgsi_sampler */ -struct sp_sampler_varient +struct sp_sampler_variant { struct tgsi_sampler base; /**< base class */ @@ -113,32 +117,33 @@ struct sp_sampler_varient filter_func mip_filter; filter_func compare; + filter_func sample_target; /* Linked list: */ - struct sp_sampler_varient *next; + struct sp_sampler_variant *next; }; struct sp_sampler; -/* Create a sampler varient for a given set of non-orthogonal state. Currently the +/* Create a sampler variant for a given set of non-orthogonal state. Currently the */ -struct sp_sampler_varient * -sp_create_sampler_varient( const struct pipe_sampler_state *sampler, +struct sp_sampler_variant * +sp_create_sampler_variant( const struct pipe_sampler_state *sampler, const union sp_sampler_key key ); -void sp_sampler_varient_bind_texture( struct sp_sampler_varient *varient, +void sp_sampler_variant_bind_texture( struct sp_sampler_variant *variant, struct softpipe_tex_tile_cache *tex_cache, const struct pipe_resource *tex ); -void sp_sampler_varient_destroy( struct sp_sampler_varient * ); +void sp_sampler_variant_destroy( struct sp_sampler_variant * ); -static INLINE struct sp_sampler_varient * -sp_sampler_varient(const struct tgsi_sampler *sampler) +static INLINE struct sp_sampler_variant * +sp_sampler_variant(const struct tgsi_sampler *sampler) { - return (struct sp_sampler_varient *) sampler; + return (struct sp_sampler_variant *) sampler; } extern void diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index e817c0c8cf5..e42015ad498 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -48,6 +48,9 @@ sp_create_tex_tile_cache( struct pipe_context *pipe ) struct softpipe_tex_tile_cache *tc; uint pos; + /* make sure max texture size works */ + assert((TILE_SIZE << TEX_ADDR_BITS) >= (1 << (SP_MAX_TEXTURE_2D_LEVELS-1))); + tc = CALLOC_STRUCT( softpipe_tex_tile_cache ); if (tc) { tc->pipe = pipe; @@ -260,15 +263,14 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, } tc->tex_trans = - pipe_get_transfer(tc->pipe, tc->texture, - addr.bits.face, - addr.bits.level, - addr.bits.z, - PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED, - 0, 0, - u_minify(tc->texture->width0, addr.bits.level), - u_minify(tc->texture->height0, addr.bits.level)); - + pipe_get_transfer(tc->pipe, tc->texture, + addr.bits.level, + addr.bits.face + addr.bits.z, + PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED, + 0, 0, + u_minify(tc->texture->width0, addr.bits.level), + u_minify(tc->texture->height0, addr.bits.level)); + tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans); tc->tex_face = addr.bits.face; @@ -276,45 +278,26 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, tc->tex_z = addr.bits.z; } - /* get tile from the transfer (view into texture) */ + /* get tile from the transfer (view into texture) + * Note we're using the swizzle version of this fuction only because + * we need to pass the texture cache's format explicitly. + */ pipe_get_tile_swizzle(tc->pipe, tc->tex_trans, addr.bits.x * TILE_SIZE, addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, - tc->swizzle_r, - tc->swizzle_g, - tc->swizzle_b, - tc->swizzle_a, + PIPE_SWIZZLE_RED, + PIPE_SWIZZLE_GREEN, + PIPE_SWIZZLE_BLUE, + PIPE_SWIZZLE_ALPHA, tc->format, (float *) tile->data.color); + tile->addr = addr; } tc->last_tile = tile; return tile; } - - - -/** - * Return the swizzled border color. - */ -const float * -sp_tex_tile_cache_border_color(struct softpipe_tex_tile_cache *tc, - const float border_color[4]) -{ - float rgba01[6]; - - COPY_4V(rgba01, border_color); - rgba01[PIPE_SWIZZLE_ZERO] = 0.0f; - rgba01[PIPE_SWIZZLE_ONE] = 1.0f; - - tc->swz_border_color[0] = rgba01[tc->swizzle_r]; - tc->swz_border_color[1] = rgba01[tc->swizzle_g]; - tc->swz_border_color[2] = rgba01[tc->swizzle_b]; - tc->swz_border_color[3] = rgba01[tc->swizzle_a]; - - return tc->swz_border_color; -} diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h index 05f25133daa..2220955b715 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h @@ -30,6 +30,7 @@ #include "pipe/p_compiler.h" +#include "sp_limits.h" struct softpipe_context; @@ -39,22 +40,26 @@ struct softpipe_tex_tile_cache; /** * Cache tile size (width and height). This needs to be a power of two. */ -#define TILE_SIZE 64 +#define TILE_SIZE_LOG2 6 +#define TILE_SIZE (1 << TILE_SIZE_LOG2) -/* If we need to support > 4096, just expand this to be a 64 bit - * union, or consider tiling in Z as well. +#define TEX_ADDR_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1 - TILE_SIZE_LOG2) +#define TEX_Z_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1) + +/** + * Texture tile address as a union for fast compares. */ union tex_tile_address { struct { - unsigned x:6; /* 4096 / TILE_SIZE */ - unsigned y:6; /* 4096 / TILE_SIZE */ - unsigned z:12; /* 4096 -- z not tiled */ + unsigned x:TEX_ADDR_BITS; /* 16K / TILE_SIZE */ + unsigned y:TEX_ADDR_BITS; /* 16K / TILE_SIZE */ + unsigned z:TEX_Z_BITS; /* 16K -- z not tiled */ unsigned face:3; unsigned level:4; unsigned invalid:1; } bits; - unsigned value; + uint64_t value; }; @@ -90,8 +95,6 @@ struct softpipe_tex_tile_cache unsigned format; struct softpipe_tex_cached_tile *last_tile; /**< most recently retrieved tile */ - - float swz_border_color[4]; /**< swizzled border color */ }; @@ -126,10 +129,10 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, static INLINE union tex_tile_address tex_tile_address( unsigned x, - unsigned y, - unsigned z, - unsigned face, - unsigned level ) + unsigned y, + unsigned z, + unsigned face, + unsigned level ) { union tex_tile_address addr; @@ -139,7 +142,7 @@ tex_tile_address( unsigned x, addr.bits.z = z; addr.bits.face = face; addr.bits.level = level; - + return addr; } @@ -156,10 +159,5 @@ sp_get_cached_tile_tex(struct softpipe_tex_tile_cache *tc, } -const float * -sp_tex_tile_cache_border_color(struct softpipe_tex_tile_cache *tc, - const float border_color[4]); - - #endif /* SP_TEX_TILE_CACHE_H */ diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 4e6123fbd07..509d9982b17 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -220,23 +220,18 @@ softpipe_resource_get_handle(struct pipe_screen *screen, */ static unsigned sp_get_tex_image_offset(const struct softpipe_resource *spr, - unsigned level, unsigned face, unsigned zslice) + unsigned level, unsigned layer) { const unsigned hgt = u_minify(spr->base.height0, level); const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt); unsigned offset = spr->level_offset[level]; - if (spr->base.target == PIPE_TEXTURE_CUBE) { - assert(zslice == 0); - offset += face * nblocksy * spr->stride[level]; - } - else if (spr->base.target == PIPE_TEXTURE_3D) { - assert(face == 0); - offset += zslice * nblocksy * spr->stride[level]; + if (spr->base.target == PIPE_TEXTURE_CUBE || + spr->base.target == PIPE_TEXTURE_3D) { + offset += layer * nblocksy * spr->stride[level]; } else { - assert(face == 0); - assert(zslice == 0); + assert(layer == 0); } return offset; @@ -247,39 +242,40 @@ sp_get_tex_image_offset(const struct softpipe_resource *spr, * Get a pipe_surface "view" into a texture resource. */ static struct pipe_surface * -softpipe_get_tex_surface(struct pipe_screen *screen, - struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned usage) +softpipe_create_surface(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { - struct softpipe_resource *spr = softpipe_resource(pt); struct pipe_surface *ps; + unsigned level = surf_tmpl->u.tex.level; assert(level <= pt->last_level); + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); ps = CALLOC_STRUCT(pipe_surface); if (ps) { pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); - ps->format = pt->format; + ps->context = pipe; + ps->format = surf_tmpl->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); - ps->offset = sp_get_tex_image_offset(spr, level, face, zslice); - ps->usage = usage; + ps->usage = surf_tmpl->usage; - ps->face = face; - ps->level = level; - ps->zslice = zslice; + ps->u.tex.level = level; + ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; + ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; } return ps; } /** - * Free a pipe_surface which was created with softpipe_get_tex_surface(). + * Free a pipe_surface which was created with softpipe_create_surface(). */ static void -softpipe_tex_surface_destroy(struct pipe_surface *surf) +softpipe_surface_destroy(struct pipe_context *pipe, + struct pipe_surface *surf) { /* Effectively do the texture_update work here - if texture images * needed post-processing to put them into hardware layout, this is @@ -302,21 +298,21 @@ softpipe_tex_surface_destroy(struct pipe_surface *surf) */ static struct pipe_transfer * softpipe_get_transfer(struct pipe_context *pipe, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct softpipe_resource *spr = softpipe_resource(resource); struct softpipe_transfer *spt; assert(resource); - assert(sr.level <= resource->last_level); + assert(level <= resource->last_level); /* make sure the requested region is in the image bounds */ - assert(box->x + box->width <= u_minify(resource->width0, sr.level)); - assert(box->y + box->height <= u_minify(resource->height0, sr.level)); - assert(box->z + box->depth <= u_minify(resource->depth0, sr.level)); + assert(box->x + box->width <= u_minify(resource->width0, level)); + assert(box->y + box->height <= u_minify(resource->height0, level)); + assert(box->z + box->depth <= (u_minify(resource->depth0, level) + resource->array_size - 1)); /* * Transfers, like other pipe operations, must happen in order, so flush the @@ -326,7 +322,7 @@ softpipe_get_transfer(struct pipe_context *pipe, boolean read_only = !(usage & PIPE_TRANSFER_WRITE); boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); if (!softpipe_flush_resource(pipe, resource, - sr.face, sr.level, + level, box->depth > 1 ? -1 : box->z, 0, /* flush_flags */ read_only, TRUE, /* cpu_access */ @@ -343,21 +339,21 @@ softpipe_get_transfer(struct pipe_context *pipe, if (spt) { struct pipe_transfer *pt = &spt->base; enum pipe_format format = resource->format; - const unsigned hgt = u_minify(spr->base.height0, sr.level); + const unsigned hgt = u_minify(spr->base.height0, level); const unsigned nblocksy = util_format_get_nblocksy(format, hgt); pipe_resource_reference(&pt->resource, resource); - pt->sr = sr; + pt->level = level; pt->usage = usage; pt->box = *box; - pt->stride = spr->stride[sr.level]; - pt->slice_stride = pt->stride * nblocksy; + pt->stride = spr->stride[level]; + pt->layer_stride = pt->stride * nblocksy; - spt->offset = sp_get_tex_image_offset(spr, sr.level, sr.face, box->z); + spt->offset = sp_get_tex_image_offset(spr, level, box->z); spt->offset += - box->y / util_format_get_blockheight(format) * spt->base.stride + - box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + box->y / util_format_get_blockheight(format) * spt->base.stride + + box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); return pt; } @@ -454,6 +450,7 @@ softpipe_user_buffer_create(struct pipe_screen *screen, spr->base.width0 = bytes; spr->base.height0 = 1; spr->base.depth0 = 1; + spr->base.array_size = 1; spr->userBuffer = TRUE; spr->data = ptr; @@ -471,6 +468,9 @@ softpipe_init_texture_funcs(struct pipe_context *pipe) pipe->transfer_flush_region = u_default_transfer_flush_region; pipe->transfer_inline_write = u_default_transfer_inline_write; + + pipe->create_surface = softpipe_create_surface; + pipe->surface_destroy = softpipe_surface_destroy; } @@ -483,6 +483,4 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen) screen->resource_get_handle = softpipe_resource_get_handle; screen->user_buffer_create = softpipe_user_buffer_create; - screen->get_tex_surface = softpipe_get_tex_surface; - screen->tex_surface_destroy = softpipe_tex_surface_destroy; } diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 6b205dc5329..5603110eeb3 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -30,10 +30,7 @@ #include "pipe/p_state.h" - - -#define SP_MAX_TEXTURE_2D_LEVELS 13 /* 4K x 4K */ -#define SP_MAX_TEXTURE_3D_LEVELS 9 /* 512 x 512 x 512 */ +#include "sp_limits.h" struct pipe_context; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index aa76b8aa1ec..480860af63b 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -92,6 +92,10 @@ sp_create_tile_cache( struct pipe_context *pipe ) maxTexSize = 1 << (maxLevels - 1); assert(MAX_WIDTH >= maxTexSize); + assert(sizeof(union tile_address) == 4); + + assert((TILE_SIZE << TILE_ADDR_BITS) >= MAX_WIDTH); + tc = CALLOC_STRUCT( softpipe_tile_cache ); if (tc) { tc->pipe = pipe; @@ -170,11 +174,11 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, tc->surface = ps; if (ps) { - tc->transfer = pipe_get_transfer(pipe, ps->texture, ps->face, - ps->level, ps->zslice, - PIPE_TRANSFER_READ_WRITE | - PIPE_TRANSFER_UNSYNCHRONIZED, - 0, 0, ps->width, ps->height); + tc->transfer = pipe_get_transfer(pipe, ps->texture, + ps->u.tex.level, ps->u.tex.first_layer, + PIPE_TRANSFER_READ_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED, + 0, 0, ps->width, ps->height); tc->depth_stencil = (ps->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || ps->format == PIPE_FORMAT_Z24X8_UNORM || diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index 4151a47c323..68140b1d2f9 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -30,6 +30,7 @@ #include "pipe/p_compiler.h" +#include "sp_texture.h" struct softpipe_tile_cache; @@ -38,18 +39,22 @@ struct softpipe_tile_cache; /** * Cache tile size (width and height). This needs to be a power of two. */ -#define TILE_SIZE 64 +#define TILE_SIZE_LOG2 6 +#define TILE_SIZE (1 << TILE_SIZE_LOG2) -/* If we need to support > 4096, just expand this to be a 64 bit - * union, or consider tiling in Z as well. +#define TILE_ADDR_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1 - TILE_SIZE_LOG2) + + +/** + * Surface tile address as a union for fast compares. */ union tile_address { struct { - unsigned x:6; /* 4096 / TILE_SIZE */ - unsigned y:6; /* 4096 / TILE_SIZE */ + unsigned x:TILE_ADDR_BITS; /* 16K / TILE_SIZE */ + unsigned y:TILE_ADDR_BITS; /* 16K / TILE_SIZE */ unsigned invalid:1; - unsigned pad:19; + unsigned pad:15; } bits; unsigned value; }; @@ -70,11 +75,6 @@ struct softpipe_cached_tile #define NUM_ENTRIES 50 -/** XXX move these */ -#define MAX_WIDTH 4096 -#define MAX_HEIGHT 4096 - - struct softpipe_tile_cache { struct pipe_context *pipe; diff --git a/src/gallium/drivers/svga/SConscript b/src/gallium/drivers/svga/SConscript index 12ce4732d15..5455ed07573 100644 --- a/src/gallium/drivers/svga/SConscript +++ b/src/gallium/drivers/svga/SConscript @@ -73,4 +73,6 @@ svga = env.ConvenienceLibrary( source = sources, ) +env.Alias('svga', svga) + Export('svga') diff --git a/src/gallium/drivers/svga/svga_cmd.c b/src/gallium/drivers/svga/svga_cmd.c index e975f3b02fa..05eab8a517d 100644 --- a/src/gallium/drivers/svga/svga_cmd.c +++ b/src/gallium/drivers/svga/svga_cmd.c @@ -455,8 +455,8 @@ SVGA3D_SurfaceDMA(struct svga_winsys_context *swc, cmd->guest.pitch = st->base.stride; swc->surface_relocation(swc, &cmd->host.sid, texture->handle, surface_flags); - cmd->host.face = st->base.sr.face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */ - cmd->host.mipmap = st->base.sr.level; + cmd->host.face = st->face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */ + cmd->host.mipmap = st->base.level; cmd->transfer = transfer; diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index cd3f6b89825..1e513f1039f 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -109,6 +109,7 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen, svga_init_vertex_functions(svga); svga_init_constbuffer_functions(svga); svga_init_query_functions(svga); + svga_init_surface_functions(svga); /* debug */ diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 1fb5a04887f..04e281a506d 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -422,6 +422,7 @@ void svga_init_vertex_functions( struct svga_context *svga ); void svga_init_constbuffer_functions( struct svga_context *svga ); void svga_init_draw_functions( struct svga_context *svga ); void svga_init_query_functions( struct svga_context *svga ); +void svga_init_surface_functions(struct svga_context *svga); void svga_cleanup_vertex_state( struct svga_context *svga ); void svga_cleanup_tss_binding( struct svga_context *svga ); diff --git a/src/gallium/drivers/svga/svga_pipe_blit.c b/src/gallium/drivers/svga/svga_pipe_blit.c index ca036a6463b..426698806c8 100644 --- a/src/gallium/drivers/svga/svga_pipe_blit.c +++ b/src/gallium/drivers/svga/svga_pipe_blit.c @@ -32,37 +32,40 @@ #define FILE_DEBUG_FLAG DEBUG_BLIT -/* XXX I got my doubts about this, should maybe use svga_texture_copy_handle directly? */ +/* XXX still have doubts about this... */ static void svga_surface_copy(struct pipe_context *pipe, struct pipe_resource* dst_tex, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource* src_tex, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) -{ + unsigned src_level, + const struct pipe_box *src_box) + { struct svga_context *svga = svga_context(pipe); - struct pipe_screen *screen = pipe->screen; + struct svga_texture *stex = svga_texture(src_tex); + struct svga_texture *dtex = svga_texture(dst_tex); +/* struct pipe_screen *screen = pipe->screen; SVGA3dCopyBox *box; enum pipe_error ret; - struct pipe_surface *srcsurf, *dstsurf; + struct pipe_surface *srcsurf, *dstsurf;*/ + unsigned dst_face, dst_z, src_face, src_z; svga_hwtnl_flush_retry( svga ); +#if 0 srcsurf = screen->get_tex_surface(screen, src_tex, - subsrc.face, subsrc.level, srcz, + src_level, src_box->z, src_box->z, PIPE_BIND_SAMPLER_VIEW); dstsurf = screen->get_tex_surface(screen, dst_tex, - subdst.face, subdst.level, dstz, + dst_level, dst_box->z, dst_box->z, PIPE_BIND_RENDER_TARGET); SVGA_DBG(DEBUG_DMA, "blit to sid %p (%d,%d), from sid %p (%d,%d) sz %dx%d\n", svga_surface(dstsurf)->handle, dstx, dsty, svga_surface(srcsurf)->handle, - srcx, srcy, + src_box->x, src_box->y, width, height); ret = SVGA3D_BeginSurfaceCopy(svga->swc, @@ -88,8 +91,8 @@ static void svga_surface_copy(struct pipe_context *pipe, box->w = width; box->h = height; box->d = 1; - box->srcx = srcx; - box->srcy = srcy; + box->srcx = src_box->x; + box->srcy = src_box->y; box->srcz = 0; SVGA_FIFOCommitAll(svga->swc); @@ -100,6 +103,37 @@ static void svga_surface_copy(struct pipe_context *pipe, pipe_surface_reference(&srcsurf, NULL); pipe_surface_reference(&dstsurf, NULL); +#else + if (src_tex->target == PIPE_TEXTURE_CUBE) { + src_face = src_box->z; + src_z = 0; + assert(src_box->depth == 1); + } + else { + src_face = 0; + src_z = src_box->z; + } + /* different src/dst type???*/ + if (dst_tex->target == PIPE_TEXTURE_CUBE) { + dst_face = dstz; + dst_z = 0; + assert(src_box->depth == 1); + } + else { + dst_face = 0; + dst_z = dstz; + } + svga_texture_copy_handle(svga, + stex->handle, + src_box->x, src_box->y, src_z, + src_level, src_face, + dtex->handle, + dstx, dsty, dst_z, + dst_level, dst_face, + src_box->width, src_box->height, src_box->depth); + +#endif + } diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index 660eb0757a6..e97b4e57415 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -68,7 +68,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, /* need this for draw module. */ rast->templ = *templ; - /* light_twoside - XXX: need fragment shader varient */ + /* light_twoside - XXX: need fragment shader variant */ /* poly_smooth - XXX: no fallback available */ /* poly_stipple_enable - draw module */ /* sprite_coord_enable - ? */ diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c index 198d4013328..f12e2b68627 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.c +++ b/src/gallium/drivers/svga/svga_resource_buffer.c @@ -53,8 +53,8 @@ svga_buffer_needs_hw_storage(unsigned usage) static unsigned int svga_buffer_is_referenced( struct pipe_context *pipe, - struct pipe_resource *buf, - unsigned face, unsigned level) + struct pipe_resource *buf, + unsigned level, int layer) { struct svga_screen *ss = svga_screen(pipe->screen); struct svga_buffer *sbuf = svga_buffer(buf); @@ -337,6 +337,7 @@ svga_user_buffer_create(struct pipe_screen *screen, sbuf->b.b.width0 = bytes; sbuf->b.b.height0 = 1; sbuf->b.b.depth0 = 1; + sbuf->b.b.array_size = 1; sbuf->swbuf = ptr; sbuf->user = TRUE; diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 26eb03a895a..7c9e600b9f4 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -50,8 +50,8 @@ static unsigned int svga_texture_is_referenced( struct pipe_context *pipe, - struct pipe_resource *texture, - unsigned face, unsigned level) + struct pipe_resource *texture, + unsigned level, int layer) { struct svga_texture *tex = svga_texture(texture); struct svga_screen *ss = svga_screen(pipe->screen); @@ -171,20 +171,7 @@ svga_transfer_dma_band(struct svga_context *svga, struct svga_texture *texture = svga_texture(st->base.resource); SVGA3dCopyBox box; enum pipe_error ret; - - SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - (%u, %u, %u), %ubpp\n", - transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from", - texture->handle, - st->base.sr.face, - st->base.box.x, - y, - st->base.box.z, - st->base.box.x + st->base.box.width, - y + h, - st->base.box.z + 1, - util_format_get_blocksize(texture->b.b.format) * 8 / - (util_format_get_blockwidth(texture->b.b.format)*util_format_get_blockheight(texture->b.b.format))); - + box.x = st->base.box.x; box.y = y; box.z = st->base.box.z; @@ -195,6 +182,26 @@ svga_transfer_dma_band(struct svga_context *svga, box.srcy = srcy; box.srcz = 0; + if (st->base.resource->target == PIPE_TEXTURE_CUBE) { + st->face = st->base.box.z; + box.z = 0; + } + else + st->face = 0; + + SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - (%u, %u, %u), %ubpp\n", + transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from", + texture->handle, + st->face, + st->base.box.x, + y, + box.z, + st->base.box.x + st->base.box.width, + y + h, + box.z + 1, + util_format_get_blocksize(texture->b.b.format) * 8 / + (util_format_get_blockwidth(texture->b.b.format)*util_format_get_blockheight(texture->b.b.format))); + ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1); if(ret != PIPE_OK) { svga->swc->flush(svga->swc, NULL); @@ -213,7 +220,7 @@ svga_transfer_dma(struct svga_context *svga, struct svga_screen *screen = svga_screen(texture->b.b.screen); struct svga_winsys_screen *sws = screen->sws; struct pipe_fence_handle *fence = NULL; - + if (transfer == SVGA3D_READ_HOST_VRAM) { SVGA_DBG(DEBUG_PERF, "%s: readback transfer\n", __FUNCTION__); } @@ -221,7 +228,7 @@ svga_transfer_dma(struct svga_context *svga, if(!st->swbuf) { /* Do the DMA transfer in a single go */ - + svga_transfer_dma_band(svga, st, transfer, st->base.box.y, st->base.box.height, 0); if(transfer == SVGA3D_READ_HOST_VRAM) { @@ -245,12 +252,12 @@ svga_transfer_dma(struct svga_context *svga, /* Transfer band must be aligned to pixel block boundaries */ assert(y % blockheight == 0); assert(h % blockheight == 0); - + offset = y * st->base.stride / blockheight; length = h * st->base.stride / blockheight; sw = (uint8_t *)st->swbuf + offset; - + if(transfer == SVGA3D_WRITE_HOST_VRAM) { /* Wait for the previous DMAs to complete */ /* TODO: keep one DMA (at half the size) in the background */ @@ -267,9 +274,9 @@ svga_transfer_dma(struct svga_context *svga, sws->buffer_unmap(sws, st->hwbuf); } } - + svga_transfer_dma_band(svga, st, transfer, y, h, srcy); - + if(transfer == SVGA3D_READ_HOST_VRAM) { svga_context_flush(svga, &fence); sws->fence_finish(sws, fence, 0); @@ -336,10 +343,10 @@ svga_texture_destroy(struct pipe_screen *screen, */ static struct pipe_transfer * svga_texture_get_transfer(struct pipe_context *pipe, - struct pipe_resource *texture, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *texture, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); @@ -352,19 +359,20 @@ svga_texture_get_transfer(struct pipe_context *pipe, if (usage & PIPE_TRANSFER_MAP_DIRECTLY) return NULL; + assert(box->depth == 1); st = CALLOC_STRUCT(svga_transfer); if (!st) return NULL; - + pipe_resource_reference(&st->base.resource, texture); - st->base.sr = sr; + st->base.level = level; st->base.usage = usage; st->base.box = *box; st->base.stride = nblocksx*util_format_get_blocksize(texture->format); - st->base.slice_stride = 0; + st->base.layer_stride = 0; st->hw_nblocksy = nblocksy; - + st->hwbuf = svga_winsys_buffer_create(svga, 1, 0, @@ -391,7 +399,7 @@ svga_texture_get_transfer(struct pipe_context *pipe, if(!st->swbuf) goto no_swbuf; } - + if (usage & PIPE_TRANSFER_READ) svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM); @@ -454,8 +462,11 @@ svga_texture_transfer_destroy(struct pipe_context *pipe, if (st->base.usage & PIPE_TRANSFER_WRITE) { svga_transfer_dma(svga, st, SVGA3D_WRITE_HOST_VRAM); ss->texture_timestamp++; - tex->view_age[transfer->sr.level] = ++(tex->age); - tex->defined[transfer->sr.face][transfer->sr.level] = TRUE; + tex->view_age[transfer->level] = ++(tex->age); + if (transfer->resource->target == PIPE_TEXTURE_CUBE) + tex->defined[transfer->box.z][transfer->level] = TRUE; + else + tex->defined[0][transfer->level] = TRUE; } pipe_resource_reference(&st->base.resource, NULL); @@ -490,7 +501,7 @@ svga_texture_create(struct pipe_screen *screen, { struct svga_screen *svgascreen = svga_screen(screen); struct svga_texture *tex = CALLOC_STRUCT(svga_texture); - + if (!tex) goto error1; @@ -507,7 +518,7 @@ svga_texture_create(struct pipe_screen *screen, tex->key.size.width = template->width0; tex->key.size.height = template->height0; tex->key.size.depth = template->depth0; - + if(template->target == PIPE_TEXTURE_CUBE) { tex->key.flags |= SVGA3D_SURFACE_CUBEMAP; tex->key.numFaces = 6; diff --git a/src/gallium/drivers/svga/svga_resource_texture.h b/src/gallium/drivers/svga/svga_resource_texture.h index 631937f2eb0..9a2911c2a95 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.h +++ b/src/gallium/drivers/svga/svga_resource_texture.h @@ -85,6 +85,8 @@ struct svga_transfer { struct pipe_transfer base; + unsigned face; + struct svga_winsys_buffer *hwbuf; /* Height of the hardware buffer in pixel blocks */ diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index af99c419010..078190342a1 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -237,6 +237,8 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 0; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; } break; case PIPE_SHADER_VERTEX: @@ -276,6 +278,8 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en return 0; case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; default: break; } @@ -495,7 +499,6 @@ svga_screen_create(struct svga_winsys_screen *sws) screen->fence_finish = svga_fence_finish; svgascreen->sws = sws; - svga_screen_init_surface_functions(screen); svga_init_screen_resource_functions(svgascreen); svgascreen->use_ps30 = diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index ad6f2947137..9c04adec8ee 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -136,7 +136,7 @@ static int make_fs_key( const struct svga_context *svga, /* The blend workaround for simulating logicop xor behaviour * requires that the incoming fragment color be white. This change - * achieves that by creating a varient of the current fragment + * achieves that by creating a variant of the current fragment * shader that overrides all output colors with 1,1,1,1 * * This will work for most shaders, including those containing diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c index d34d68f5350..66fea02a4be 100644 --- a/src/gallium/drivers/svga/svga_state_need_swtnl.c +++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c @@ -114,7 +114,7 @@ static int update_need_pipeline( struct svga_context *svga, /* SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE */ if (svga->curr.rast->need_pipeline & (1 << svga->curr.reduced_prim)) { - SVGA_DBG(DEBUG_SWTNL, "%s: rast need_pipeline (%d) & prim (%x)\n", + SVGA_DBG(DEBUG_SWTNL, "%s: rast need_pipeline (0x%x) & prim (0x%x)\n", __FUNCTION__, svga->curr.rast->need_pipeline, (1 << svga->curr.reduced_prim) ); diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c index 4a50b19474c..f8b269a101e 100644 --- a/src/gallium/drivers/svga/svga_state_tss.c +++ b/src/gallium/drivers/svga/svga_state_tss.c @@ -238,7 +238,6 @@ update_tss(struct svga_context *svga, // TEXCOORDINDEX -- hopefully not needed if (svga->curr.tex_flags.flag_1d & (1 << i)) { - debug_printf("wrap 1d tex %d\n", i); EMIT_TS(svga, i, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV, fail); } else diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c index b21dc5fd9af..3e4bed76c05 100644 --- a/src/gallium/drivers/svga/svga_surface.c +++ b/src/gallium/drivers/svga/svga_surface.c @@ -179,36 +179,50 @@ svga_texture_view_surface(struct pipe_context *pipe, static struct pipe_surface * -svga_get_tex_surface(struct pipe_screen *screen, - struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) +svga_create_surface(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { struct svga_texture *tex = svga_texture(pt); + struct pipe_screen *screen = pipe->screen; struct svga_surface *s; - boolean render = (flags & (PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DEPTH_STENCIL)) ? TRUE : FALSE; + unsigned face, zslice; + /* XXX surfaces should only be used for rendering purposes nowadays */ + boolean render = (surf_tmpl->usage & (PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DEPTH_STENCIL)) ? TRUE : FALSE; boolean view = FALSE; SVGA3dSurfaceFormat format; + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); + s = CALLOC_STRUCT(svga_surface); if (!s) return NULL; + if (pt->target == PIPE_TEXTURE_CUBE) { + face = surf_tmpl->u.tex.first_layer; + zslice = 0; + } + else { + face = 0; + zslice = surf_tmpl->u.tex.first_layer; + } + pipe_reference_init(&s->base.reference, 1); pipe_resource_reference(&s->base.texture, pt); - s->base.format = pt->format; - s->base.width = u_minify(pt->width0, level); - s->base.height = u_minify(pt->height0, level); - s->base.usage = flags; - s->base.level = level; - s->base.face = face; - s->base.zslice = zslice; + s->base.context = pipe; + s->base.format = surf_tmpl->format; + s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level); + s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level); + s->base.usage = surf_tmpl->usage; + s->base.u.tex.level = surf_tmpl->u.tex.level; + s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; + s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; if (!render) - format = svga_translate_format(pt->format); + format = svga_translate_format(surf_tmpl->format); else - format = svga_translate_format_render(pt->format); + format = svga_translate_format_render(surf_tmpl->format); assert(format != SVGA3D_FORMAT_INVALID); @@ -217,11 +231,11 @@ svga_get_tex_surface(struct pipe_screen *screen, /* Currently only used for compressed textures */ if (render && - format != svga_translate_format(pt->format)) { + format != svga_translate_format(surf_tmpl->format)) { view = TRUE; } - if (level != 0 && + if (surf_tmpl->u.tex.level != 0 && svga_screen(screen)->debug.force_level_surface_view) view = TRUE; @@ -233,22 +247,22 @@ svga_get_tex_surface(struct pipe_screen *screen, if (view) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n", - pt, level, face, zslice, s); + pt, surf_tmpl->u.tex.level, face, zslice, s); - s->handle = svga_texture_view_surface(NULL, tex, format, level, 1, face, zslice, - &s->key); + s->handle = svga_texture_view_surface(NULL, tex, format, surf_tmpl->u.tex.level, + 1, face, zslice, &s->key); s->real_face = 0; s->real_level = 0; s->real_zslice = 0; } else { SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, face %u, z %u, %p\n", - pt, level, face, zslice, s); + pt, surf_tmpl->u.tex.level, face, zslice, s); memset(&s->key, 0, sizeof s->key); s->handle = tex->handle; s->real_face = face; - s->real_level = level; s->real_zslice = zslice; + s->real_level = surf_tmpl->u.tex.level; } return &s->base; @@ -256,7 +270,8 @@ svga_get_tex_surface(struct pipe_screen *screen, static void -svga_tex_surface_destroy(struct pipe_surface *surf) +svga_surface_destroy(struct pipe_context *pipe, + struct pipe_surface *surf) { struct svga_surface *s = svga_surface(surf); struct svga_texture *t = svga_texture(surf->texture); @@ -282,8 +297,13 @@ svga_mark_surface_dirty(struct pipe_surface *surf) s->dirty = TRUE; - if (s->handle == tex->handle) - tex->defined[surf->face][surf->level] = TRUE; + if (s->handle == tex->handle) { + /* hmm so 3d textures always have all their slices marked ? */ + if (surf->texture->target == PIPE_TEXTURE_CUBE) + tex->defined[surf->u.tex.first_layer][surf->u.tex.level] = TRUE; + else + tex->defined[0][surf->u.tex.level] = TRUE; + } else { /* this will happen later in svga_propagate_surface */ } @@ -314,22 +334,32 @@ svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf) struct svga_surface *s = svga_surface(surf); struct svga_texture *tex = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); + unsigned zslice, face; if (!s->dirty) return; + if (surf->texture->target == PIPE_TEXTURE_CUBE) { + zslice = 0; + face = surf->u.tex.first_layer; + } + else { + zslice = surf->u.tex.first_layer; + face = 0; + } + s->dirty = FALSE; ss->texture_timestamp++; - tex->view_age[surf->level] = ++(tex->age); + tex->view_age[surf->u.tex.level] = ++(tex->age); if (s->handle != tex->handle) { - SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->level, surf); + SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->u.tex.level, surf); svga_texture_copy_handle(svga_context(pipe), s->handle, 0, 0, 0, s->real_level, s->real_face, - tex->handle, 0, 0, surf->zslice, surf->level, surf->face, - u_minify(tex->b.b.width0, surf->level), - u_minify(tex->b.b.height0, surf->level), 1); - tex->defined[surf->face][surf->level] = TRUE; + tex->handle, 0, 0, zslice, surf->u.tex.level, face, + u_minify(tex->b.b.width0, surf->u.tex.level), + u_minify(tex->b.b.height0, surf->u.tex.level), 1); + tex->defined[face][surf->u.tex.level] = TRUE; } } @@ -351,9 +381,9 @@ svga_surface_needs_propagation(struct pipe_surface *surf) void -svga_screen_init_surface_functions(struct pipe_screen *screen) +svga_init_surface_functions(struct svga_context *svga) { - screen->get_tex_surface = svga_get_tex_surface; - screen->tex_surface_destroy = svga_tex_surface_destroy; + svga->pipe.create_surface = svga_create_surface; + svga->pipe.surface_destroy = svga_surface_destroy; } diff --git a/src/gallium/drivers/svga/svga_surface.h b/src/gallium/drivers/svga/svga_surface.h index 13bd5b19b61..afb8326e1f3 100644 --- a/src/gallium/drivers/svga/svga_surface.h +++ b/src/gallium/drivers/svga/svga_surface.h @@ -90,7 +90,4 @@ svga_surface(struct pipe_surface *surface) return (struct svga_surface *)surface; } -void -svga_screen_init_surface_functions(struct pipe_screen *screen); - #endif diff --git a/src/gallium/drivers/sw/SConscript b/src/gallium/drivers/sw/SConscript deleted file mode 100644 index 40d01db2f6d..00000000000 --- a/src/gallium/drivers/sw/SConscript +++ /dev/null @@ -1,37 +0,0 @@ -####################################################################### -# SConscript for swrast convenience library -# -# This is a meta-driver which consists of any and all of the software -# rasterizers into a single driver. A software rasterizer is defined -# as any driver which takes an sw_winsys pointer as the only argument -# to create_screen. - -Import('*') - -env = env.Clone() - -# To avoid targets having to check extensively or add drivers on a whim, append -# all referenced extra drivers to the exported symbol. -extra = [] -if True: - env.Append(CPPDEFINES = 'GALLIUM_SOFTPIPE') - env.Prepend(LIBS = [softpipe]) - extra.append(softpipe) - -if env['llvm']: - env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE') - env.Prepend(LIBS = [llvmpipe]) - extra.append(llvmpipe) - -if 'cell' in env['drivers']: - env.Append(CPPDEFINES = 'GALLIUM_CELL') - env.Prepend(LIBS = [cell]) - extra.append(cell) - -sw = env.ConvenienceLibrary( - target = 'sw', - source = [ - 'sw.c', - ] - ) + extra -Export('sw') diff --git a/src/gallium/drivers/sw/sw.c b/src/gallium/drivers/sw/sw.c deleted file mode 100644 index 6b873ecc1b0..00000000000 --- a/src/gallium/drivers/sw/sw.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "pipe/p_compiler.h" -#include "util/u_debug.h" -#include "target-helpers/wrap_screen.h" -#include "sw_public.h" - - -/* Helper function to choose and instantiate one of the software rasterizers: - * cell, llvmpipe, softpipe. - */ - -#ifdef GALLIUM_SOFTPIPE -#include "softpipe/sp_public.h" -#endif - -#ifdef GALLIUM_LLVMPIPE -#include "llvmpipe/lp_public.h" -#endif - -#ifdef GALLIUM_CELL -#include "cell/ppu/cell_public.h" -#endif - -struct pipe_screen * -swrast_create_screen(struct sw_winsys *winsys) -{ - const char *default_driver; - const char *driver; - struct pipe_screen *screen = NULL; - -#if defined(GALLIUM_CELL) - default_driver = "cell"; -#elif defined(GALLIUM_LLVMPIPE) - default_driver = "llvmpipe"; -#elif defined(GALLIUM_SOFTPIPE) - default_driver = "softpipe"; -#else - default_driver = ""; -#endif - - driver = debug_get_option("GALLIUM_DRIVER", default_driver); - -#if defined(GALLIUM_CELL) - if (screen == NULL && strcmp(driver, "cell") == 0) - screen = cell_create_screen( winsys ); -#endif - -#if defined(GALLIUM_LLVMPIPE) - if (screen == NULL && strcmp(driver, "llvmpipe") == 0) - screen = llvmpipe_create_screen( winsys ); -#endif - -#if defined(GALLIUM_SOFTPIPE) - if (screen == NULL) - screen = softpipe_create_screen( winsys ); -#endif - - return screen; -} diff --git a/src/gallium/drivers/sw/sw_public.h b/src/gallium/drivers/sw/sw_public.h deleted file mode 100644 index 7085c5c85a0..00000000000 --- a/src/gallium/drivers/sw/sw_public.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SW_PUBLIC_H -#define SW_PUBLIC_H - -/* A convenience library, primarily to isolate the logic required to - * figure out which if any software rasterizers have been built and - * select between them. - */ -struct sw_winsys; - -struct pipe_screen * -swrast_create_screen(struct sw_winsys *winsys); - -#endif diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 04f30f82c3d..eaabae8ce42 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -314,6 +314,9 @@ trace_context_bind_vertex_sampler_states(struct pipe_context *_pipe, struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; + if (!pipe->bind_vertex_sampler_states) + return; + trace_dump_call_begin("pipe_context", "bind_vertex_sampler_states"); trace_dump_arg(ptr, pipe); @@ -885,6 +888,60 @@ trace_sampler_view_destroy(struct pipe_context *_pipe, FREE(_view); } +/******************************************************************** + * surface + */ + + +static struct pipe_surface * +trace_create_surface(struct pipe_context *_pipe, + struct pipe_resource *_texture, + const struct pipe_surface *surf_tmpl) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_resource *tr_tex = trace_resource(_texture); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_resource *texture = tr_tex->resource; + struct pipe_surface *result = NULL; + + trace_dump_call_begin("pipe_context", "create_surface"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, texture); + /* hmm some values unitialized there */ + trace_dump_arg(surface, surf_tmpl); + + result = pipe->create_surface(pipe, texture, surf_tmpl); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_surf_create(tr_tex, result); + + return result; +} + + +static void +trace_surface_destroy(struct pipe_context *_pipe, + struct pipe_surface *_surface) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct trace_surface *tr_surf = trace_surface(_surface); + struct pipe_surface *surface = tr_surf->surface; + + trace_dump_call_begin("pipe_context", "surface_destroy"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, surface); + + trace_dump_call_end(); + + trace_surf_destroy(tr_surf); +} + static INLINE void trace_context_set_fragment_sampler_views(struct pipe_context *_pipe, @@ -926,6 +983,9 @@ trace_context_set_vertex_sampler_views(struct pipe_context *_pipe, struct pipe_sampler_view *unwrapped_views[PIPE_MAX_VERTEX_SAMPLERS]; unsigned i; + if (!pipe->set_vertex_sampler_views) + return; + for(i = 0; i < num; ++i) { tr_view = trace_sampler_view(views[i]); unwrapped_views[i] = tr_view ? tr_view->sampler_view : NULL; @@ -1004,12 +1064,11 @@ trace_context_set_index_buffer(struct pipe_context *_pipe, static INLINE void trace_context_resource_copy_region(struct pipe_context *_pipe, struct pipe_resource *dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; @@ -1021,21 +1080,17 @@ trace_context_resource_copy_region(struct pipe_context *_pipe, trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, dst); - trace_dump_arg_struct(subresource, subdst); + trace_dump_arg(uint, dst_level); trace_dump_arg(uint, dstx); trace_dump_arg(uint, dsty); trace_dump_arg(uint, dstz); trace_dump_arg(ptr, src); - trace_dump_arg_struct(subresource, subsrc); - trace_dump_arg(uint, srcx); - trace_dump_arg(uint, srcy); - trace_dump_arg(uint, srcz); - trace_dump_arg(uint, width); - trace_dump_arg(uint, height); + trace_dump_arg(uint, src_level); + trace_dump_arg(box, src_box); pipe->resource_copy_region(pipe, - dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height); + dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); trace_dump_call_end(); } @@ -1166,8 +1221,8 @@ trace_context_destroy(struct pipe_context *_pipe) static unsigned int trace_is_resource_referenced( struct pipe_context *_pipe, - struct pipe_resource *_resource, - unsigned face, unsigned level) + struct pipe_resource *_resource, + unsigned level, int layer) { struct trace_context *tr_ctx = trace_context(_pipe); struct trace_resource *tr_tex = trace_resource(_resource); @@ -1178,10 +1233,10 @@ trace_is_resource_referenced( struct pipe_context *_pipe, trace_dump_call_begin("pipe_context", "is_resource_referenced"); trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, texture); - trace_dump_arg(uint, face); trace_dump_arg(uint, level); + trace_dump_arg(int, layer); - referenced = pipe->is_resource_referenced(pipe, texture, face, level); + referenced = pipe->is_resource_referenced(pipe, texture, level, layer); trace_dump_ret(uint, referenced); trace_dump_call_end(); @@ -1197,10 +1252,10 @@ trace_is_resource_referenced( struct pipe_context *_pipe, static struct pipe_transfer * trace_context_get_transfer(struct pipe_context *_context, - struct pipe_resource *_resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *_resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct trace_context *tr_context = trace_context(_context); struct trace_resource *tr_tex = trace_resource(_resource); @@ -1215,7 +1270,7 @@ trace_context_get_transfer(struct pipe_context *_context, * to transfer_inline_write and ignore read transfers. */ - result = context->get_transfer(context, texture, sr, usage, box); + result = context->get_transfer(context, texture, level, usage, box); if (result) result = trace_transfer_create(tr_context, tr_tex, result); @@ -1226,7 +1281,7 @@ trace_context_get_transfer(struct pipe_context *_context, static void trace_context_transfer_destroy(struct pipe_context *_context, - struct pipe_transfer *_transfer) + struct pipe_transfer *_transfer) { struct trace_context *tr_context = trace_context(_context); struct trace_transfer *tr_trans = trace_transfer(_transfer); @@ -1274,7 +1329,7 @@ trace_context_transfer_flush_region( struct pipe_context *_context, static void trace_context_transfer_unmap(struct pipe_context *_context, - struct pipe_transfer *_transfer) + struct pipe_transfer *_transfer) { struct trace_context *tr_ctx = trace_context(_context); struct trace_transfer *tr_trans = trace_transfer(_transfer); @@ -1287,17 +1342,17 @@ trace_context_transfer_unmap(struct pipe_context *_context, */ struct pipe_resource *resource = transfer->resource; - struct pipe_subresource sr = transfer->sr; + unsigned level = transfer->level; unsigned usage = transfer->usage; const struct pipe_box *box = &transfer->box; unsigned stride = transfer->stride; - unsigned slice_stride = transfer->slice_stride; + unsigned layer_stride = transfer->layer_stride; trace_dump_call_begin("pipe_context", "transfer_inline_write"); trace_dump_arg(ptr, context); trace_dump_arg(ptr, resource); - trace_dump_arg_struct(subresource, sr); + trace_dump_arg(uint, level); trace_dump_arg(uint, usage); trace_dump_arg(box, box); @@ -1306,11 +1361,11 @@ trace_context_transfer_unmap(struct pipe_context *_context, resource->format, box, stride, - slice_stride); + layer_stride); trace_dump_arg_end(); trace_dump_arg(uint, stride); - trace_dump_arg(uint, slice_stride); + trace_dump_arg(uint, layer_stride); trace_dump_call_end(); @@ -1323,13 +1378,13 @@ trace_context_transfer_unmap(struct pipe_context *_context, static void trace_context_transfer_inline_write(struct pipe_context *_context, - struct pipe_resource *_resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box, - const void *data, - unsigned stride, - unsigned slice_stride) + struct pipe_resource *_resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) { struct trace_context *tr_context = trace_context(_context); struct trace_resource *tr_tex = trace_resource(_resource); @@ -1342,7 +1397,7 @@ trace_context_transfer_inline_write(struct pipe_context *_context, trace_dump_arg(ptr, context); trace_dump_arg(ptr, resource); - trace_dump_arg_struct(subresource, sr); + trace_dump_arg(uint, level); trace_dump_arg(uint, usage); trace_dump_arg(box, box); @@ -1351,16 +1406,16 @@ trace_context_transfer_inline_write(struct pipe_context *_context, resource->format, box, stride, - slice_stride); + layer_stride); trace_dump_arg_end(); trace_dump_arg(uint, stride); - trace_dump_arg(uint, slice_stride); + trace_dump_arg(uint, layer_stride); trace_dump_call_end(); context->transfer_inline_write(context, resource, - sr, usage, box, data, stride, slice_stride); + level, usage, box, data, stride, layer_stride); } @@ -1434,6 +1489,8 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.set_vertex_sampler_views = trace_context_set_vertex_sampler_views; tr_ctx->base.create_sampler_view = trace_create_sampler_view; tr_ctx->base.sampler_view_destroy = trace_sampler_view_destroy; + tr_ctx->base.create_surface = trace_create_surface; + tr_ctx->base.surface_destroy = trace_surface_destroy; tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers; tr_ctx->base.set_index_buffer = trace_context_set_index_buffer; tr_ctx->base.resource_copy_region = trace_context_resource_copy_region; diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index 8f816060324..155c869fbd9 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -71,6 +71,10 @@ void trace_dump_resource_template(const struct pipe_resource *templat) trace_dump_uint(templat->depth0); trace_dump_member_end(); + trace_dump_member_begin("array_size"); + trace_dump_uint(templat->array_size); + trace_dump_member_end(); + trace_dump_member(uint, templat, last_level); trace_dump_member(uint, templat, usage); trace_dump_member(uint, templat, bind); @@ -80,25 +84,6 @@ void trace_dump_resource_template(const struct pipe_resource *templat) } -void trace_dump_subresource(const struct pipe_subresource *subresource) -{ - if (!trace_dumping_enabled_locked()) - return; - - if(!subresource) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_subresource"); - - trace_dump_member(uint, subresource, face); - trace_dump_member(uint, subresource, level); - - trace_dump_struct_end(); -} - - void trace_dump_box(const struct pipe_box *box) { if (!trace_dumping_enabled_locked()) @@ -445,8 +430,13 @@ void trace_dump_sampler_view_template(const struct pipe_sampler_view *state) trace_dump_struct_begin("pipe_sampler_view"); trace_dump_member(format, state, format); - trace_dump_member(uint, state, first_level); - trace_dump_member(uint, state, last_level); + /* XXX */ + trace_dump_member(uint, state, u.tex.first_level); + trace_dump_member(uint, state, u.tex.last_level); + trace_dump_member(uint, state, u.tex.first_layer); + trace_dump_member(uint, state, u.tex.last_layer); + trace_dump_member(uint, state, u.buf.first_element); + trace_dump_member(uint, state, u.buf.last_element); trace_dump_member(uint, state, swizzle_r); trace_dump_member(uint, state, swizzle_g); trace_dump_member(uint, state, swizzle_b); @@ -472,14 +462,14 @@ void trace_dump_surface(const struct pipe_surface *state) trace_dump_member(uint, state, width); trace_dump_member(uint, state, height); - trace_dump_member(uint, state, layout); - trace_dump_member(uint, state, offset); trace_dump_member(uint, state, usage); trace_dump_member(ptr, state, texture); - trace_dump_member(uint, state, face); - trace_dump_member(uint, state, level); - trace_dump_member(uint, state, zslice); + trace_dump_member(uint, state, u.tex.level); + trace_dump_member(uint, state, u.tex.first_layer); + trace_dump_member(uint, state, u.tex.last_layer); + trace_dump_member(uint, state, u.buf.first_element); + trace_dump_member(uint, state, u.buf.last_element); trace_dump_struct_end(); } @@ -497,16 +487,18 @@ void trace_dump_transfer(const struct pipe_transfer *state) trace_dump_struct_begin("pipe_transfer"); + trace_dump_member(uint, state, box.x); + trace_dump_member(uint, state, box.y); + trace_dump_member(uint, state, box.z); trace_dump_member(uint, state, box.width); trace_dump_member(uint, state, box.height); + trace_dump_member(uint, state, box.depth); trace_dump_member(uint, state, stride); + trace_dump_member(uint, state, layer_stride); trace_dump_member(uint, state, usage); trace_dump_member(ptr, state, resource); - trace_dump_member(uint, state, sr.face); - trace_dump_member(uint, state, sr.level); - trace_dump_member(uint, state, box.z); trace_dump_struct_end(); } diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h index 078d2086109..fe8ece78d43 100644 --- a/src/gallium/drivers/trace/tr_dump_state.h +++ b/src/gallium/drivers/trace/tr_dump_state.h @@ -37,8 +37,6 @@ void trace_dump_format(enum pipe_format format); void trace_dump_resource_template(const struct pipe_resource *templat); -void trace_dump_subresource(const struct pipe_subresource *subresource); - void trace_dump_box(const struct pipe_box *box); void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state); diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index 935831071e6..c2de2daa883 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -210,23 +210,26 @@ trace_screen_context_create(struct pipe_screen *_screen, void *priv) static void trace_screen_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_surface *_surface, + struct pipe_resource *_resource, + unsigned level, unsigned layer, void *context_private) { struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_surface *tr_surf = trace_surface(_surface); + struct trace_resource *tr_res = trace_resource(_resource); struct pipe_screen *screen = tr_scr->screen; - struct pipe_surface *surface = tr_surf->surface; + struct pipe_resource *resource = tr_res->resource; trace_dump_call_begin("pipe_screen", "flush_frontbuffer"); trace_dump_arg(ptr, screen); - trace_dump_arg(ptr, surface); + trace_dump_arg(ptr, resource); + trace_dump_arg(uint, level); + trace_dump_arg(uint, layer); /* XXX: hide, as there is nothing we can do with this trace_dump_arg(ptr, context_private); */ - screen->flush_frontbuffer(screen, surface, context_private); + screen->flush_frontbuffer(screen, resource, level, layer, context_private); trace_dump_call_end(); } @@ -318,68 +321,6 @@ trace_screen_resource_destroy(struct pipe_screen *_screen, } -/******************************************************************** - * surface - */ - - -static struct pipe_surface * -trace_screen_get_tex_surface(struct pipe_screen *_screen, - struct pipe_resource *_texture, - unsigned face, unsigned level, - unsigned zslice, - unsigned usage) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_resource *tr_tex = trace_resource(_texture); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_resource *texture = tr_tex->resource; - struct pipe_surface *result = NULL; - - assert(texture->screen == screen); - - trace_dump_call_begin("pipe_screen", "get_tex_surface"); - - trace_dump_arg(ptr, screen); - trace_dump_arg(ptr, texture); - trace_dump_arg(uint, face); - trace_dump_arg(uint, level); - trace_dump_arg(uint, zslice); - trace_dump_arg(uint, usage); - - result = screen->get_tex_surface(screen, texture, face, level, zslice, usage); - - trace_dump_ret(ptr, result); - - trace_dump_call_end(); - - result = trace_surface_create(tr_tex, result); - - return result; -} - - -static void -trace_screen_tex_surface_destroy(struct pipe_surface *_surface) -{ - struct trace_screen *tr_scr = trace_screen(_surface->texture->screen); - struct trace_surface *tr_surf = trace_surface(_surface); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_surface *surface = tr_surf->surface; - - trace_dump_call_begin("pipe_screen", "tex_surface_destroy"); - - trace_dump_arg(ptr, screen); - trace_dump_arg(ptr, surface); - - trace_dump_call_end(); - - trace_surface_destroy(tr_surf); -} - - - - /******************************************************************** * buffer @@ -580,8 +521,6 @@ trace_screen_create(struct pipe_screen *screen) tr_scr->base.resource_from_handle = trace_screen_resource_from_handle; tr_scr->base.resource_get_handle = trace_screen_resource_get_handle; tr_scr->base.resource_destroy = trace_screen_resource_destroy; - tr_scr->base.get_tex_surface = trace_screen_get_tex_surface; - tr_scr->base.tex_surface_destroy = trace_screen_tex_surface_destroy; tr_scr->base.user_buffer_create = trace_screen_user_buffer_create; tr_scr->base.fence_reference = trace_screen_fence_reference; tr_scr->base.fence_signalled = trace_screen_fence_signalled; diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c index 9914b98b39c..27997346471 100644 --- a/src/gallium/drivers/trace/tr_texture.c +++ b/src/gallium/drivers/trace/tr_texture.c @@ -74,8 +74,8 @@ trace_resource_destroy(struct trace_screen *tr_scr, struct pipe_surface * -trace_surface_create(struct trace_resource *tr_tex, - struct pipe_surface *surface) +trace_surf_create(struct trace_resource *tr_tex, + struct pipe_surface *surface) { struct trace_surface *tr_surf; @@ -104,7 +104,7 @@ error: void -trace_surface_destroy(struct trace_surface *tr_surf) +trace_surf_destroy(struct trace_surface *tr_surf) { pipe_resource_reference(&tr_surf->base.texture, NULL); pipe_surface_reference(&tr_surf->surface, NULL); diff --git a/src/gallium/drivers/trace/tr_texture.h b/src/gallium/drivers/trace/tr_texture.h index 6513995d505..3352c96e59a 100644 --- a/src/gallium/drivers/trace/tr_texture.h +++ b/src/gallium/drivers/trace/tr_texture.h @@ -125,11 +125,11 @@ trace_resource_destroy(struct trace_screen *tr_scr, struct trace_resource *tr_tex); struct pipe_surface * -trace_surface_create(struct trace_resource *tr_tex, +trace_surf_create(struct trace_resource *tr_tex, struct pipe_surface *surface); void -trace_surface_destroy(struct trace_surface *tr_surf); +trace_surf_destroy(struct trace_surface *tr_surf); struct pipe_transfer * trace_transfer_create(struct trace_context *tr_ctx, |