[Mesa-dev] [PATCH 10/23] i965: Import image access validity checks.

Francisco Jerez currojerez at riseup.net
Tue Apr 28 11:44:21 PDT 2015


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.
---
 src/mesa/drivers/dri/i965/brw_ir_surface_builder.h | 60 ++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h b/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h
index e24e484..6fbade1 100644
--- a/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h
+++ b/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h
@@ -551,6 +551,66 @@ namespace brw {
          return emit_extract(layout, bld, dsts, rsize);
       }
    }
+
+   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.
+       */
+      template<typename B, typename S>
+      brw_predicate
+      emit_surface_check(const B &bld, const S &image)
+      {
+         const brw_device_info *devinfo = bld.devinfo;
+         const unsigned chan_size = S::traits::chan_size;
+         const S size = offset(image, BRW_IMAGE_PARAM_SIZE_OFFSET / chan_size);
+
+         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.
+             */
+            exec_reduce(BRW_PREDICATE_ALIGN16_REPLICATE_X,
+                        bld.CMP(writemask(bld.null_reg_ud(), WRITEMASK_X),
+                                retype(size, BRW_REGISTER_TYPE_UD),
+                                S(0), BRW_CONDITIONAL_NZ));
+
+            return bld.reduced_predicate(BRW_PREDICATE_ALIGN16_REPLICATE_X);
+         } 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.
+       */
+      template<typename B, typename S>
+      brw_predicate
+      emit_bounds_check(const B &bld, const S &image, const S &addr,
+                        unsigned dims)
+      {
+         const unsigned chan_size = S::traits::chan_size;
+         const S size = offset(image, BRW_IMAGE_PARAM_SIZE_OFFSET / chan_size);
+
+         /* Using resize() in the source values makes sure that the flag
+          * register result has valid comparison bits replicated to all four
+          * channels and we can use the ALL4H predication mode.
+          */
+         exec_reduce(BRW_PREDICATE_ALIGN16_ALL4H,
+                     bld.CMP(bld.null_reg_ud(),
+                             resize(retype(addr, BRW_REGISTER_TYPE_UD), dims),
+                             resize(size, dims), BRW_CONDITIONAL_L));
+
+         return bld.reduced_predicate(BRW_PREDICATE_ALIGN16_ALL4H);
+      }
+   }
 }
 
 #endif
-- 
2.3.5



More information about the mesa-dev mailing list