summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2016-07-21 22:23:13 -0700
committerFrancisco Jerez <currojerez@riseup.net>2016-08-25 18:36:07 -0700
commitdc96968dbf7b359a24a991def16e382379f4b11a (patch)
treeccc4f3c40395ecdd58e8543ef94cbb2ec52579f6 /src/mesa/drivers/dri/i965/brw_wm_surface_state.c
parent49ea2bd17500cbe3cc5f39b59162eaae1278167d (diff)
downloadexternal_mesa3d-dc96968dbf7b359a24a991def16e382379f4b11a.zip
external_mesa3d-dc96968dbf7b359a24a991def16e382379f4b11a.tar.gz
external_mesa3d-dc96968dbf7b359a24a991def16e382379f4b11a.tar.bz2
i965: Implement support for overriding the texture target in brw_emit_surface_state.
This allows the caller to bind a miptree using a texture target other than the one it it was created with. The code should work even if the memory layouts of the specified and original targets don't match, as long as the caller only intends to access a single slice of the miptree structure. This will be exploited by the next commit in order to support non-coherent framebuffer fetch of a single layer of a 3D texture (since some generations lack the minimum array element control for 3D textures bound to the sampler unit), and multiple layers of a 1D array texture (since binding it as an actual 1D array texture would require state-dependent recompiles because the same shader couldn't simultaneously work for 1D and 2D array textures due to the different texel fetch coordinate ordering). Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_wm_surface_state.c')
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 15ff142..7756020 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -79,12 +79,57 @@ brw_emit_surface_state(struct brw_context *brw,
uint32_t mocs, uint32_t *surf_offset, int surf_index,
unsigned read_domains, unsigned write_domains)
{
- assert(mt->target == target);
const struct surface_state_info ss_info = surface_state_infos[brw->gen];
+ uint32_t tile_x = 0, tile_y = 0;
+ uint32_t offset = mt->offset;
struct isl_surf surf;
intel_miptree_get_isl_surf(brw, mt, &surf);
+ surf.dim = get_isl_surf_dim(target);
+
+ const enum isl_dim_layout dim_layout =
+ get_isl_dim_layout(brw->intelScreen->devinfo, mt->tiling, target);
+
+ if (surf.dim_layout != dim_layout) {
+ /* The layout of the specified texture target is not compatible with the
+ * actual layout of the miptree structure in memory -- You're entering
+ * dangerous territory, this can only possibly work if you only intended
+ * to access a single level and slice of the texture, and the hardware
+ * supports the tile offset feature in order to allow non-tile-aligned
+ * base offsets, since we'll have to point the hardware to the first
+ * texel of the level instead of relying on the usual base level/layer
+ * controls.
+ */
+ assert(brw->has_surface_tile_offset);
+ assert(view.levels == 1 && view.array_len == 1);
+
+ offset += intel_miptree_get_tile_offsets(mt, view.base_level,
+ view.base_array_layer,
+ &tile_x, &tile_y);
+
+ /* Minify the logical dimensions of the texture. */
+ const unsigned l = view.base_level - mt->first_level;
+ surf.logical_level0_px.width = minify(surf.logical_level0_px.width, l);
+ surf.logical_level0_px.height = surf.dim <= ISL_SURF_DIM_1D ? 1 :
+ minify(surf.logical_level0_px.height, l);
+ surf.logical_level0_px.depth = surf.dim <= ISL_SURF_DIM_2D ? 1 :
+ minify(surf.logical_level0_px.depth, l);
+
+ /* Only the base level and layer can be addressed with the overridden
+ * layout.
+ */
+ surf.logical_level0_px.array_len = 1;
+ surf.levels = 1;
+ surf.dim_layout = dim_layout;
+
+ /* The requested slice of the texture is now at the base level and
+ * layer.
+ */
+ view.base_level = 0;
+ view.base_array_layer = 0;
+ }
+
union isl_color_value clear_color = { .u32 = { 0, 0, 0, 0 } };
struct isl_surf *aux_surf = NULL, aux_surf_s;
@@ -109,14 +154,15 @@ brw_emit_surface_state(struct brw_context *brw,
surf_index, surf_offset);
isl_surf_fill_state(&brw->isl_dev, dw, .surf = &surf, .view = &view,
- .address = mt->bo->offset64 + mt->offset,
+ .address = mt->bo->offset64 + offset,
.aux_surf = aux_surf, .aux_usage = aux_usage,
.aux_address = aux_offset,
- .mocs = mocs, .clear_color = clear_color);
+ .mocs = mocs, .clear_color = clear_color,
+ .x_offset_sa = tile_x, .y_offset_sa = tile_y);
drm_intel_bo_emit_reloc(brw->batch.bo,
*surf_offset + 4 * ss_info.reloc_dw,
- mt->bo, mt->offset,
+ mt->bo, offset,
read_domains, write_domains);
if (aux_surf) {