anv: avoid crashes when failing to allocate batches
authorIago Toral Quiroga <itoral@igalia.com>
Thu, 9 Mar 2017 13:22:25 +0000 (14:22 +0100)
committerIago Toral Quiroga <itoral@igalia.com>
Thu, 16 Mar 2017 10:40:05 +0000 (11:40 +0100)
Most of the time we use macros that handle this situation transparently,
but there are some cases were we need to handle this explicitly.

This patch makes sure we don't crash, notice that error handling takes
place in the function that actually failed the allocation,
anv_batch_emit_dwords(), which will set the status field of the batch
so it can be used at a later moment to report the error to the user.

v2:
  - Not crashing is not good enough, we need to keep track of the error
    (Topi, Jason). Iago: now that we track errors in the batch, this
    is being handled.
  - Added guards in a few more places that needed it (Iago)

v3:
  - Check result of anv_batch_emitn() for NULL before calling memset()
    in emit_vertex_input() (Topi)

Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/intel/blorp/blorp_genX_exec.h
src/intel/vulkan/anv_private.h
src/intel/vulkan/genX_pipeline.c

index f0c4f38578f66d5d5335d2fc5f825b84e03a001c..dc1b7735ab3e59c5153fc0672c7cd578effec0f2 100644 (file)
@@ -110,14 +110,16 @@ _blorp_combine_address(struct blorp_batch *batch, void *location,
         _blorp_cmd_pack(cmd)(batch, (void *)_dst, &name),         \
         _dst = NULL)
 
-#define blorp_emitn(batch, cmd, n) ({                    \
-      uint32_t *_dw = blorp_emit_dwords(batch, n);       \
-      struct cmd template = {                            \
-         _blorp_cmd_header(cmd),                         \
-         .DWordLength = n - _blorp_cmd_length_bias(cmd), \
-      };                                                 \
-      _blorp_cmd_pack(cmd)(batch, _dw, &template);       \
-      _dw + 1; /* Array starts at dw[1] */               \
+#define blorp_emitn(batch, cmd, n) ({                       \
+      uint32_t *_dw = blorp_emit_dwords(batch, n);          \
+      if (_dw) {                                            \
+         struct cmd template = {                            \
+            _blorp_cmd_header(cmd),                         \
+            .DWordLength = n - _blorp_cmd_length_bias(cmd), \
+         };                                                 \
+         _blorp_cmd_pack(cmd)(batch, _dw, &template);       \
+      }                                                     \
+      _dw ? _dw + 1 : NULL; /* Array starts at dw[1] */     \
    })
 
 /* 3DSTATE_URB
@@ -274,6 +276,8 @@ blorp_emit_vertex_buffers(struct blorp_batch *batch,
 
    const unsigned num_dwords = 1 + GENX(VERTEX_BUFFER_STATE_length) * 2;
    uint32_t *dw = blorp_emitn(batch, GENX(3DSTATE_VERTEX_BUFFERS), num_dwords);
+   if (!dw)
+      return;
 
    for (unsigned i = 0; i < 2; i++) {
       GENX(VERTEX_BUFFER_STATE_pack)(batch, dw, &vb[i]);
@@ -379,6 +383,8 @@ blorp_emit_vertex_elements(struct blorp_batch *batch,
    const unsigned num_dwords =
       1 + GENX(VERTEX_ELEMENT_STATE_length) * num_elements;
    uint32_t *dw = blorp_emitn(batch, GENX(3DSTATE_VERTEX_ELEMENTS), num_dwords);
+   if (!dw)
+      return;
 
    for (unsigned i = 0; i < num_elements; i++) {
       GENX(VERTEX_ELEMENT_STATE_pack)(batch, dw, &ve[i]);
@@ -1019,6 +1025,9 @@ blorp_emit_depth_stencil_state(struct blorp_batch *batch,
    uint32_t offset = 0;
    uint32_t *dw = blorp_emit_dwords(batch,
                                     GENX(3DSTATE_WM_DEPTH_STENCIL_length));
+   if (!dw)
+      return 0;
+
    GENX(3DSTATE_WM_DEPTH_STENCIL_pack)(NULL, dw, &ds);
 #else
    uint32_t offset;
index 0177a42dcc0b31687021f66ad1c49573736cbdbe..87538de1a578b74b526e9c026ad7096a3036dddb 100644 (file)
@@ -779,15 +779,17 @@ _anv_combine_address(struct anv_batch *batch, void *location,
       VG(VALGRIND_CHECK_MEM_IS_DEFINED(dst, __anv_cmd_length(struc) * 4)); \
    } while (0)
 
-#define anv_batch_emitn(batch, n, cmd, ...) ({          \
-      void *__dst = anv_batch_emit_dwords(batch, n);    \
-      struct cmd __template = {                         \
-         __anv_cmd_header(cmd),                         \
-        .DWordLength = n - __anv_cmd_length_bias(cmd),  \
-         __VA_ARGS__                                    \
-      };                                                \
-      __anv_cmd_pack(cmd)(batch, __dst, &__template);   \
-      __dst;                                            \
+#define anv_batch_emitn(batch, n, cmd, ...) ({             \
+      void *__dst = anv_batch_emit_dwords(batch, n);       \
+      if (__dst) {                                         \
+         struct cmd __template = {                         \
+            __anv_cmd_header(cmd),                         \
+           .DWordLength = n - __anv_cmd_length_bias(cmd),  \
+            __VA_ARGS__                                    \
+         };                                                \
+         __anv_cmd_pack(cmd)(batch, __dst, &__template);   \
+      }                                                    \
+      __dst;                                               \
    })
 
 #define anv_batch_emit_merge(batch, dwords0, dwords1)                   \
@@ -796,6 +798,8 @@ _anv_combine_address(struct anv_batch *batch, void *location,
                                                                         \
       STATIC_ASSERT(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1));        \
       dw = anv_batch_emit_dwords((batch), ARRAY_SIZE(dwords0));         \
+      if (!dw)                                                          \
+         break;                                                         \
       for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++)                \
          dw[i] = (dwords0)[i] | (dwords1)[i];                           \
       VG(VALGRIND_CHECK_MEM_IS_DEFINED(dw, ARRAY_SIZE(dwords0) * 4));\
index a6ec3b6f10452faafc46958b614c46c620dd4edd..0c8d3d5a74f5922dfce18474f662b7d180bb952e 100644 (file)
@@ -112,6 +112,8 @@ emit_vertex_input(struct anv_pipeline *pipeline,
    const uint32_t num_dwords = 1 + total_elems * 2;
    p = anv_batch_emitn(&pipeline->batch, num_dwords,
                        GENX(3DSTATE_VERTEX_ELEMENTS));
+   if (!p)
+      return;
    memset(p + 1, 0, (num_dwords - 1) * 4);
 
    for (uint32_t i = 0; i < info->vertexAttributeDescriptionCount; i++) {
@@ -389,10 +391,14 @@ emit_3dstate_sbe(struct anv_pipeline *pipeline)
 
    uint32_t *dw = anv_batch_emit_dwords(&pipeline->batch,
                                         GENX(3DSTATE_SBE_length));
+   if (!dw)
+      return;
    GENX(3DSTATE_SBE_pack)(&pipeline->batch, dw, &sbe);
 
 #if GEN_GEN >= 8
    dw = anv_batch_emit_dwords(&pipeline->batch, GENX(3DSTATE_SBE_SWIZ_length));
+   if (!dw)
+      return;
    GENX(3DSTATE_SBE_SWIZ_pack)(&pipeline->batch, dw, &swiz);
 #endif
 }