summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFrancisco Jerez <[email protected]>2015-04-22 16:43:51 +0300
committerFrancisco Jerez <[email protected]>2015-08-11 15:07:39 +0300
commitfb19df7a626d02cb54614d4610af2d14720a2ef3 (patch)
tree2aa53e7d1428c7bab3cd4f7ac1f606170e96bc89 /src
parent3569742ec458c0a881857d9deb782c1e11f195d8 (diff)
i965/fs: Import image access validity checks.
These utility functions check whether an image access is valid. According to the spec an invalid image access should have no effect on the image and yield well-defined results. Typically the hardware implements correct bounds and surface checking by itself, but in some cases (typed atomics on IVB and untyped messages elsewhere) we need to implement it in software to work around lacking hardware support. v2: Drop VEC4 suport. v3: Rebase. Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp b/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp
index cac958d49c1..5ee04dece88 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp
@@ -161,3 +161,58 @@ namespace brw {
}
}
}
+
+namespace {
+ namespace image_validity {
+ /**
+ * Check whether there is an image bound at the given index and write
+ * the comparison result to f0.0. Returns an appropriate predication
+ * mode to use on subsequent image operations.
+ */
+ brw_predicate
+ emit_surface_check(const fs_builder &bld, const fs_reg &image)
+ {
+ const brw_device_info *devinfo = bld.shader->devinfo;
+ const fs_reg size = offset(image, bld, BRW_IMAGE_PARAM_SIZE_OFFSET);
+
+ if (devinfo->gen == 7 && !devinfo->is_haswell) {
+ /* Check the first component of the size field to find out if the
+ * image is bound. Necessary on IVB for typed atomics because
+ * they don't seem to respect null surfaces and will happily
+ * corrupt or read random memory when no image is bound.
+ */
+ bld.CMP(bld.null_reg_ud(),
+ retype(size, BRW_REGISTER_TYPE_UD),
+ fs_reg(0), BRW_CONDITIONAL_NZ);
+
+ return BRW_PREDICATE_NORMAL;
+ } else {
+ /* More recent platforms implement compliant behavior when a null
+ * surface is bound.
+ */
+ return BRW_PREDICATE_NONE;
+ }
+ }
+
+ /**
+ * Check whether the provided coordinates are within the image bounds
+ * and write the comparison result to f0.0. Returns an appropriate
+ * predication mode to use on subsequent image operations.
+ */
+ brw_predicate
+ emit_bounds_check(const fs_builder &bld, const fs_reg &image,
+ const fs_reg &addr, unsigned dims)
+ {
+ const fs_reg size = offset(image, bld, BRW_IMAGE_PARAM_SIZE_OFFSET);
+
+ for (unsigned c = 0; c < dims; ++c)
+ set_predicate(c == 0 ? BRW_PREDICATE_NONE : BRW_PREDICATE_NORMAL,
+ bld.CMP(bld.null_reg_ud(),
+ offset(retype(addr, BRW_REGISTER_TYPE_UD), bld, c),
+ offset(size, bld, c),
+ BRW_CONDITIONAL_L));
+
+ return BRW_PREDICATE_NORMAL;
+ }
+ }
+}