diff options
author | Ilia Mirkin <[email protected]> | 2016-11-09 17:16:36 -0500 |
---|---|---|
committer | Ilia Mirkin <[email protected]> | 2016-11-22 20:27:20 -0500 |
commit | 7cfb364b1a373bce6b0b273556953fbb78c139e9 (patch) | |
tree | e05dc9618e147c13553360900bdef49ea069a8c2 /src/gallium/drivers/swr/swr_context.cpp | |
parent | 5d2b5996e1e85e3b4c167570f1eecb5a131d5837 (diff) |
swr: rework resource layout and surface setup
This is a bit of a mega-commit, but unfortunately there's no great way
to break this up since a lot of different pieces have to match up. Here
we do the following:
- change surface layout to match swr's Load/StoreTile expectations
- fix sampler settings to respect all sampler view parameters
- fix stencil sampling to read from secondary resource
- respect pipe surface format, level, and layer settings
- fix resource map/unmap based on the new layout logic
- fix resource map/unmap to copy proper parts of stencil values in and
out of the matching depth texture
These fix a massive quantity of piglits, including all the
tex-miplevel-selection ones.
Note that the swr native miptree layout isn't extremely space-efficient,
and we end up using it for all textures, not just the renderable ones. A
back-of-the-envelope calculation suggests about 10%-25% increased memory
usage for miptrees, depending on the number of LODs. Single-LOD textures
should be unaffected.
There are a handful of regressions as a result of this change:
- Some textureGrad tests, these failures match llvmpipe. (There are
debug settings allowing improved gallivm sampling accurancy.)
- Some layered clearing tests as swr doesn't currently support that. It
was getting lucky before because enough other things were broken.
Signed-off-by: Ilia Mirkin <[email protected]>
Reviewed-by: Bruce Cherniak <[email protected]>
Diffstat (limited to 'src/gallium/drivers/swr/swr_context.cpp')
-rw-r--r-- | src/gallium/drivers/swr/swr_context.cpp | 103 |
1 files changed, 77 insertions, 26 deletions
diff --git a/src/gallium/drivers/swr/swr_context.cpp b/src/gallium/drivers/swr/swr_context.cpp index 3f5771219f6..5a1927cb349 100644 --- a/src/gallium/drivers/swr/swr_context.cpp +++ b/src/gallium/drivers/swr/swr_context.cpp @@ -139,21 +139,35 @@ swr_transfer_map(struct pipe_context *pipe, if (!pt) return NULL; pipe_resource_reference(&pt->resource, resource); + pt->usage = (pipe_transfer_usage)usage; pt->level = level; pt->box = *box; - pt->stride = spr->row_stride[level]; - pt->layer_stride = spr->img_stride[level]; - - /* if we're mapping the depth/stencil, copy in stencil */ - if (spr->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT - && spr->has_stencil) { - for (unsigned i = 0; i < spr->alignedWidth * spr->alignedHeight; i++) { - spr->swr.pBaseAddress[4 * i + 3] = spr->secondary.pBaseAddress[i]; - } - } else if (spr->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT - && spr->has_stencil) { - for (unsigned i = 0; i < spr->alignedWidth * spr->alignedHeight; i++) { - spr->swr.pBaseAddress[8 * i + 4] = spr->secondary.pBaseAddress[i]; + pt->stride = spr->swr.pitch; + pt->layer_stride = spr->swr.qpitch * spr->swr.pitch; + + /* if we're mapping the depth/stencil, copy in stencil for the section + * being read in + */ + if (usage & PIPE_TRANSFER_READ && spr->has_depth && spr->has_stencil) { + size_t zbase, sbase; + for (int z = box->z; z < box->z + box->depth; z++) { + zbase = (z * spr->swr.qpitch + box->y) * spr->swr.pitch + + spr->mip_offsets[level]; + sbase = (z * spr->secondary.qpitch + box->y) * spr->secondary.pitch + + spr->secondary_mip_offsets[level]; + for (int y = box->y; y < box->y + box->height; y++) { + if (spr->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT) { + for (int x = box->x; x < box->x + box->width; x++) + spr->swr.pBaseAddress[zbase + 4 * x + 3] = + spr->secondary.pBaseAddress[sbase + x]; + } else if (spr->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { + for (int x = box->x; x < box->x + box->width; x++) + spr->swr.pBaseAddress[zbase + 8 * x + 4] = + spr->secondary.pBaseAddress[sbase + x]; + } + zbase += spr->swr.pitch; + sbase += spr->secondary.pitch; + } } } @@ -167,23 +181,60 @@ swr_transfer_map(struct pipe_context *pipe, } static void -swr_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) +swr_transfer_flush_region(struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *flush_box) { assert(transfer->resource); + assert(transfer->usage & PIPE_TRANSFER_WRITE); - struct swr_resource *res = swr_resource(transfer->resource); - /* if we're mapping the depth/stencil, copy out stencil */ - if (res->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT - && res->has_stencil) { - for (unsigned i = 0; i < res->alignedWidth * res->alignedHeight; i++) { - res->secondary.pBaseAddress[i] = res->swr.pBaseAddress[4 * i + 3]; - } - } else if (res->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT - && res->has_stencil) { - for (unsigned i = 0; i < res->alignedWidth * res->alignedHeight; i++) { - res->secondary.pBaseAddress[i] = res->swr.pBaseAddress[8 * i + 4]; + struct swr_resource *spr = swr_resource(transfer->resource); + if (!spr->has_depth || !spr->has_stencil) + return; + + size_t zbase, sbase; + struct pipe_box box = *flush_box; + box.x += transfer->box.x; + box.y += transfer->box.y; + box.z += transfer->box.z; + for (int z = box.z; z < box.z + box.depth; z++) { + zbase = (z * spr->swr.qpitch + box.y) * spr->swr.pitch + + spr->mip_offsets[transfer->level]; + sbase = (z * spr->secondary.qpitch + box.y) * spr->secondary.pitch + + spr->secondary_mip_offsets[transfer->level]; + for (int y = box.y; y < box.y + box.height; y++) { + if (spr->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT) { + for (int x = box.x; x < box.x + box.width; x++) + spr->secondary.pBaseAddress[sbase + x] = + spr->swr.pBaseAddress[zbase + 4 * x + 3]; + } else if (spr->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { + for (int x = box.x; x < box.x + box.width; x++) + spr->secondary.pBaseAddress[sbase + x] = + spr->swr.pBaseAddress[zbase + 8 * x + 4]; + } + zbase += spr->swr.pitch; + sbase += spr->secondary.pitch; } } +} + +static void +swr_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) +{ + assert(transfer->resource); + + struct swr_resource *spr = swr_resource(transfer->resource); + /* if we're mapping the depth/stencil, copy in stencil for the section + * being written out + */ + if (transfer->usage & PIPE_TRANSFER_WRITE && + !(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) && + spr->has_depth && spr->has_stencil) { + struct pipe_box box; + u_box_3d(0, 0, 0, transfer->box.width, transfer->box.height, + transfer->box.depth, &box); + swr_transfer_flush_region(pipe, transfer, &box); + } pipe_resource_reference(&transfer->resource, NULL); FREE(transfer); @@ -424,8 +475,8 @@ swr_create_context(struct pipe_screen *p_screen, void *priv, unsigned flags) ctx->pipe.surface_destroy = swr_surface_destroy; ctx->pipe.transfer_map = swr_transfer_map; ctx->pipe.transfer_unmap = swr_transfer_unmap; + ctx->pipe.transfer_flush_region = swr_transfer_flush_region; - ctx->pipe.transfer_flush_region = u_default_transfer_flush_region; ctx->pipe.buffer_subdata = u_default_buffer_subdata; ctx->pipe.texture_subdata = u_default_texture_subdata; |