diff options
author | Chad Versace <chad.versace@linux.intel.com> | 2013-04-05 16:35:47 -0700 |
---|---|---|
committer | Chad Versace <chad.versace@linux.intel.com> | 2013-04-10 10:55:26 -0700 |
commit | e4484a0309ab44a790df29a599fb2b01eb885d5a (patch) | |
tree | 0fd5b682b3ce728c0894e93a561412a77ace16ff | |
parent | 916d1ea7dc5ac6cba358eafd766440f836a74c16 (diff) |
intel/hsw: Enable hiz (v2)
Enable hiz by setting intel_context::has_hiz. However, to work around
a hardware bug, we selectively enable hiz for only nicely aligned miptree
slices.
No Piglit regressions on Haswell 0x0d26 rev07 when based atop
mesa-master-4ad3601.
Improves the performance of GLB27_TRex_C24Z16_FixedTimeStep by 18.52%
(hsw-0x0d26-rev07; kernel-3.9.0-rc1; GLBenchmark 2.7.0 Release a68901;
samples=3).
v2: Replace the check for IS_HASWELL(devid) in intel_miptree_slice_has_hiz()
with a conditional set of has_hiz. [for anholt]
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_context.c | 2 | ||||
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_mipmap_tree.c | 51 |
2 files changed, 51 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 990fbeab5d1c..797a4c80a377 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -694,7 +694,7 @@ intelInitContext(struct intel_context *intel, intel->has_separate_stencil = intel->intelScreen->hw_has_separate_stencil; intel->must_use_separate_stencil = intel->intelScreen->hw_must_use_separate_stencil; - intel->has_hiz = intel->gen >= 6 && !intel->is_haswell; + intel->has_hiz = intel->gen >= 6; intel->has_llc = intel->intelScreen->hw_has_llc; intel->has_swizzling = intel->intelScreen->hw_has_swizzling; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index df6badebacec..bd313689be04 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -29,6 +29,7 @@ #include <GL/internal/dri_interface.h> #include "intel_batchbuffer.h" +#include "intel_chipset.h" #include "intel_context.h" #include "intel_mipmap_tree.h" #include "intel_regions.h" @@ -985,6 +986,53 @@ intel_miptree_alloc_mcs(struct intel_context *intel, return mt->mcs_mt; } +/** + * Helper for intel_miptree_alloc_hiz() that sets + * \c mt->level[level].slice[layer].has_hiz. Return true if and only if + * \c has_hiz was set. + */ +static bool +intel_miptree_slice_enable_hiz(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + assert(mt->hiz_mt); + + if (intel->is_haswell) { + /* Disable HiZ for some slices to work around a hardware bug. + * + * Haswell hardware fails to respect + * 3DSTATE_DEPTH_BUFFER.Depth_Coordinate_Offset_X/Y when during HiZ + * ambiguate operations. The failure is inconsistent and affected by + * other GPU contexts. Running a heavy GPU workload in a separate + * process causes the failure rate to drop to nearly 0. + * + * To workaround the bug, we enable HiZ only when we can guarantee that + * the Depth Coordinate Offset fields will be set to 0. The function + * brw_get_depthstencil_tile_masks() is used to calculate the fields, + * and the function is sometimes called in such a way that the presence + * of an attached stencil buffer changes the fuction's return value. + * + * The largest tile size considered by brw_get_depthstencil_tile_masks() + * is that of the stencil buffer. Therefore, if this hiz slice's + * corresponding depth slice has an offset that is aligned to the + * stencil buffer tile size, 64x64 pixels, then + * 3DSTATE_DEPTH_BUFFER.Depth_Coordinate_Offset_X/Y is set to 0. + */ + uint32_t depth_x_offset = mt->level[level].slice[layer].x_offset; + uint32_t depth_y_offset = mt->level[level].slice[layer].y_offset; + if ((depth_x_offset & 63) || (depth_y_offset & 63)) { + return false; + } + } + + mt->level[level].slice[layer].has_hiz = true; + return true; +} + + + bool intel_miptree_alloc_hiz(struct intel_context *intel, struct intel_mipmap_tree *mt, @@ -1010,7 +1058,8 @@ intel_miptree_alloc_hiz(struct intel_context *intel, struct intel_resolve_map *head = &mt->hiz_map; for (int level = mt->first_level; level <= mt->last_level; ++level) { for (int layer = 0; layer < mt->level[level].depth; ++layer) { - mt->level[level].slice[layer].has_hiz = true; + if (!intel_miptree_slice_enable_hiz(intel, mt, level, layer)) + continue; head->next = malloc(sizeof(*head->next)); head->next->prev = head; |