Merge Vulkan Compute work into master.

Bug: skia:
Change-Id: I37ee0c30620bd998586a22f5d6e8177ebcecb178
Reviewed-on: https://skia-review.googlesource.com/147083
Reviewed-by: Allan MacKinnon <allanmac@google.com>
Commit-Queue: Allan MacKinnon <allanmac@google.com>
Auto-Submit: Allan MacKinnon <allanmac@google.com>
diff --git a/src/compute/common/cuda/assert_cuda.c b/src/compute/common/cuda/assert_cuda.c
new file mode 100644
index 0000000..275aca1
--- /dev/null
+++ b/src/compute/common/cuda/assert_cuda.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+//
+//
+//
+
+#include <cuda_runtime_api.h>
+
+//
+//
+//
+
+#include "assert_cuda.h"
+
+//
+//
+//
+
+cudaError_t
+assert_cuda(cudaError_t  const code,
+            char const * const file,
+            int          const line,
+            bool         const abort)
+{
+  if (code != cudaSuccess)
+    {
+      const char* const cuda_err_str = cudaGetErrorString(code);
+
+      fprintf(stderr,
+              "\"%s\", line %d: assert_cuda ( %d ) = \"%s\"",
+              file,line,code,cuda_err_str);
+
+      if (abort)
+        {
+          cudaDeviceReset();
+          exit(code);
+        }
+    }
+
+  return code;
+}
+
+//
+//
+//
diff --git a/src/compute/common/cuda/assert_cuda.h b/src/compute/common/cuda/assert_cuda.h
new file mode 100644
index 0000000..65c340d
--- /dev/null
+++ b/src/compute/common/cuda/assert_cuda.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#pragma once
+
+//
+//
+//
+
+#include <driver_types.h>
+#include <stdbool.h>
+
+//
+//
+//
+
+cudaError_t
+assert_cuda(cudaError_t  const code,
+            char const * const file,
+            int          const line,
+            bool         const abort);
+
+//
+//
+//
+
+#define cuda(...) assert_cuda((cuda##__VA_ARGS__), __FILE__, __LINE__, true);
+
+//
+//
+//
diff --git a/src/compute/common/macros.h b/src/compute/common/macros.h
index 266b58f..eb6fabf 100644
--- a/src/compute/common/macros.h
+++ b/src/compute/common/macros.h
@@ -36,7 +36,7 @@
 //
 //
 
-#if defined(_MSC_VER)
+#if defined( _MSC_VER )
 #define ALLOCA_MACRO(n)         _alloca(n)
 #else
 #define ALLOCA_MACRO(n)         alloca(n)
@@ -53,13 +53,70 @@
 #define BITS_TO_MASK_AT_64(n,b) (BITS_TO_MASK_64(n)<<(b))
 
 //
-// Convert 4 byte pointer to network order dword to a host order.
+//
+//
+
+#define STRINGIFY2_MACRO(a)     #a
+#define STRINGIFY_MACRO(a)      STRINGIFY2_MACRO(a)
+
+//
+//
+//
+
+#define EVAL_MACRO(x)           x
+#define CONCAT_MACRO(a,b)       EVAL_MACRO(a)##EVAL_MACRO(b)
+
+//
+// Convert byte pointer to a network order 32-bit integer to host
+// order.
 //
 
 #define NPBTOHL_MACRO(pb4)      ((((pb4)[0])<<24) | (((pb4)[1])<<16) |  \
                                  (((pb4)[2])<< 8) |   (pb4)[3])
 
-#define NTOHL_MACRO(nl)         ntohl(nl)
+//
+//
+//
+
+#if   defined( _MSC_VER )
+
+#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
+#define NTOHL_MACRO(x)          _byteswap_ulong(x)
+#else
+#define NTOHL_MACRO(x)          x
+#endif
+
+#elif defined( __GNUC__ )
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define NTOHL_MACRO(x)          __builtin_bswap32(x)
+#else
+#define NTOHL_MACRO(x)          x
+#endif
+
+#else
+//
+// FIXME -- CLANG, etc.
+//
+#endif
+
+//
+//
+//
+
+#if   defined( _MSC_VER )
+
+#define STATIC_ASSERT_MACRO(...) static_assert(__VA_ARGS__)
+
+#elif defined( __GNUC__ )
+
+#define STATIC_ASSERT_MACRO(...) _Static_assert(__VA_ARGS__)
+
+#else
+//
+// FIXME -- CLANG, etc.
+//
+#endif
 
 //
 //
diff --git a/src/compute/common/util.c b/src/compute/common/util.c
index 51a8e01..ed05f14 100644
--- a/src/compute/common/util.c
+++ b/src/compute/common/util.c
@@ -6,8 +6,16 @@
  *
  */
 
+#ifdef _MSC_VER
+
 #include <intrin.h>
 
+#else
+
+
+
+#endif
+
 //
 //
 //
@@ -59,7 +67,7 @@
 uint32_t
 msb_idx_u32(uint32_t n)
 {
-#ifdef _MSC_VER
+#if defined( _MSC_VER )
 
   uint32_t index;
 
@@ -67,10 +75,9 @@
 
   return index;
 
-#elif defined(__GNUC__)
+#elif defined( __GNUC__ )
 
-#error "BUSTED msb_index()"
-  return 31 - __builtin_clz(mask);
+  return __builtin_clz(n) ^ 31;
 
 #else
 
diff --git a/src/compute/common/vk/assert_vk.c b/src/compute/common/vk/assert_vk.c
new file mode 100644
index 0000000..a3a9da4
--- /dev/null
+++ b/src/compute/common/vk/assert_vk.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+//
+//
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+
+//
+//
+//
+
+#include "assert_vk.h"
+
+//
+//
+//
+
+#define VK_RESULT_TO_STRING(result) case result: return #result
+
+//
+// FIXME -- results and errors
+//
+
+char const *
+vk_get_result_string(VkResult const result)
+{
+  switch (result)
+    {
+      //
+      // Results
+      //
+      VK_RESULT_TO_STRING(VK_SUCCESS);
+      VK_RESULT_TO_STRING(VK_NOT_READY);
+      VK_RESULT_TO_STRING(VK_TIMEOUT);
+      VK_RESULT_TO_STRING(VK_EVENT_SET);
+      VK_RESULT_TO_STRING(VK_EVENT_RESET);
+      VK_RESULT_TO_STRING(VK_INCOMPLETE);
+      //
+      // Errors
+      //
+      VK_RESULT_TO_STRING(VK_ERROR_OUT_OF_HOST_MEMORY);
+      VK_RESULT_TO_STRING(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+      VK_RESULT_TO_STRING(VK_ERROR_INITIALIZATION_FAILED);
+      VK_RESULT_TO_STRING(VK_ERROR_DEVICE_LOST);
+      VK_RESULT_TO_STRING(VK_ERROR_MEMORY_MAP_FAILED);
+      VK_RESULT_TO_STRING(VK_ERROR_LAYER_NOT_PRESENT);
+      VK_RESULT_TO_STRING(VK_ERROR_EXTENSION_NOT_PRESENT);
+      VK_RESULT_TO_STRING(VK_ERROR_FEATURE_NOT_PRESENT);
+      VK_RESULT_TO_STRING(VK_ERROR_INCOMPATIBLE_DRIVER);
+      VK_RESULT_TO_STRING(VK_ERROR_TOO_MANY_OBJECTS);
+      VK_RESULT_TO_STRING(VK_ERROR_FORMAT_NOT_SUPPORTED);
+      VK_RESULT_TO_STRING(VK_ERROR_FRAGMENTED_POOL);
+      VK_RESULT_TO_STRING(VK_ERROR_OUT_OF_POOL_MEMORY);
+      VK_RESULT_TO_STRING(VK_ERROR_INVALID_EXTERNAL_HANDLE);
+      VK_RESULT_TO_STRING(VK_ERROR_SURFACE_LOST_KHR);
+      VK_RESULT_TO_STRING(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
+      VK_RESULT_TO_STRING(VK_SUBOPTIMAL_KHR);
+      VK_RESULT_TO_STRING(VK_ERROR_OUT_OF_DATE_KHR);
+      VK_RESULT_TO_STRING(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
+      VK_RESULT_TO_STRING(VK_ERROR_VALIDATION_FAILED_EXT);
+      VK_RESULT_TO_STRING(VK_ERROR_INVALID_SHADER_NV);
+      VK_RESULT_TO_STRING(VK_ERROR_FRAGMENTATION_EXT);
+      VK_RESULT_TO_STRING(VK_ERROR_NOT_PERMITTED_EXT);
+
+      //
+      // Extensions: vk_xyz
+      //
+    default:
+      return "UNKNOWN VULKAN RESULT";
+    }
+}
+
+//
+//
+//
+
+VkResult
+assert_vk(VkResult const result, char const * const file, int const line, bool const abort)
+{
+  if (result != VK_SUCCESS)
+    {
+      char const * const vk_result_str = vk_get_result_string(result);
+
+      fprintf(stderr,
+              "\"%s\", line %d: assert_vk( %d ) = \"%s\"",
+              file,line,result,vk_result_str);
+
+      if (abort)
+        {
+          // stop profiling and reset device here if necessary
+          exit(result);
+        }
+    }
+
+  return result;
+}
+
+//
+//
+//
diff --git a/src/compute/common/vk/assert_vk.h b/src/compute/common/vk/assert_vk.h
new file mode 100644
index 0000000..1090644
--- /dev/null
+++ b/src/compute/common/vk/assert_vk.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#pragma once
+
+//
+//
+//
+
+#include <vulkan/vulkan.h>
+#include <stdbool.h>
+
+//
+//
+//
+
+char const *
+vk_get_result_string(VkResult const result);
+
+VkResult
+assert_vk(VkResult     const result,
+          char const * const file,
+          int          const line,
+          bool         const abort);
+
+//
+//
+//
+
+#define vk(...)    assert_vk((vk##__VA_ARGS__), __FILE__, __LINE__, true);
+#define vk_ok(err) assert_vk(err,               __FILE__, __LINE__, true);
+
+//
+//
+//
diff --git a/src/compute/common/vk/event_pool.c b/src/compute/common/vk/event_pool.c
new file mode 100644
index 0000000..b10b160
--- /dev/null
+++ b/src/compute/common/vk/event_pool.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+//
+//
+//
+
+#include "event_pool.h"
+#include "host_alloc.h"
+#include "assert_vk.h"
+
+//
+//
+//
+
+struct vk_event_pool
+{
+  VkEvent                     * events;
+  VkAllocationCallbacks const * allocator;
+  VkDevice                      device;
+  uint32_t                      resize;
+  uint32_t                      size;
+  uint32_t                      next;
+};
+
+static
+void
+vk_event_pool_resize(struct vk_event_pool * const event_pool)
+{
+  static struct VkEventCreateInfo const eci = {
+    .sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
+    .pNext = NULL,
+    .flags = 0
+  };
+
+  // FIXME -- respect allocator
+
+  event_pool->size  += event_pool->resize;
+  event_pool->events = vk_host_realloc(event_pool->allocator,
+                                       event_pool->events,
+                                       sizeof(VkEvent) * event_pool->size);
+
+  for (uint32_t ii=event_pool->next; ii<event_pool->size; ii++)
+    {
+      vk(CreateEvent(event_pool->device,
+                     &eci,
+                     event_pool->allocator,
+                     event_pool->events+ii));
+    }
+}
+
+struct vk_event_pool *
+vk_event_pool_create(VkDevice device, VkAllocationCallbacks const * allocator, uint32_t const resize)
+{
+  struct vk_event_pool * const event_pool = vk_host_alloc(allocator,sizeof(*event_pool));
+
+  event_pool->events    = NULL;
+  event_pool->allocator = allocator;
+  event_pool->device    = device;
+  event_pool->resize    = resize;
+  event_pool->size      = 0;
+  event_pool->next      = 0;
+
+  vk_event_pool_resize(event_pool);
+
+  return event_pool;
+}
+
+void
+vk_event_pool_release(struct vk_event_pool * const event_pool)
+{
+  for (uint32_t ii=0; ii<event_pool->size; ii++)
+    {
+      vkDestroyEvent(event_pool->device,
+                     event_pool->events[ii],
+                     event_pool->allocator);
+    }
+
+  vk_host_free(event_pool->allocator,event_pool->events);
+  vk_host_free(event_pool->allocator,event_pool);
+}
+
+void
+vk_event_pool_reset(struct vk_event_pool * const event_pool)
+{
+  for (uint32_t ii=0; ii<event_pool->next; ii++)
+    vk(ResetEvent(event_pool->device,event_pool->events[ii]));
+
+  event_pool->next = 0;
+}
+
+VkEvent
+vk_event_pool_acquire(struct vk_event_pool * const event_pool)
+{
+  if (event_pool->next == event_pool->size)
+    vk_event_pool_resize(event_pool);
+
+  return event_pool->events[event_pool->next++];
+}
+
+//
+//
+//
diff --git a/src/compute/common/vk/event_pool.h b/src/compute/common/vk/event_pool.h
new file mode 100644
index 0000000..f4036a9
--- /dev/null
+++ b/src/compute/common/vk/event_pool.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#pragma once
+
+//
+//
+//
+
+#include <vulkan/vulkan.h>
+
+//
+//
+//
+
+struct vk_event_pool *
+vk_event_pool_create(VkDevice device, VkAllocationCallbacks const * allocator, uint32_t const resize);
+
+void
+vk_event_pool_release(struct vk_event_pool * const event_pool);
+
+void
+vk_event_pool_reset(struct vk_event_pool * const event_pool);
+
+VkEvent
+vk_event_pool_acquire(struct vk_event_pool * const event_pool);
+
+//
+//
+//
diff --git a/src/compute/common/vk/host_alloc.c b/src/compute/common/vk/host_alloc.c
new file mode 100644
index 0000000..f163f7b
--- /dev/null
+++ b/src/compute/common/vk/host_alloc.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+//
+//
+//
+
+#include <stdlib.h>
+
+//
+//
+//
+
+#include "host_alloc.h"
+
+//
+//
+//
+
+void *
+vk_host_alloc(VkAllocationCallbacks const * allocator, size_t size)
+{
+  return malloc(size);
+}
+
+void *
+vk_host_realloc(VkAllocationCallbacks const * allocator, void * ptr, size_t new_size)
+{
+  return realloc(ptr,new_size);
+}
+
+void
+vk_host_free(VkAllocationCallbacks const * allocator, void * ptr)
+{
+  free(ptr);
+}
+
+//
+//
+//
diff --git a/src/compute/common/vk/host_alloc.h b/src/compute/common/vk/host_alloc.h
new file mode 100644
index 0000000..361f949
--- /dev/null
+++ b/src/compute/common/vk/host_alloc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#pragma once
+
+//
+//
+//
+
+#include <vulkan/vulkan.h>
+
+//
+//
+//
+
+void *
+vk_host_alloc(VkAllocationCallbacks const * allocator, size_t size);
+
+void *
+vk_host_realloc(VkAllocationCallbacks const * allocator, void * ptr, size_t new_size);
+
+void
+vk_host_free(VkAllocationCallbacks const * allocator, void * ptr);
+
+//
+//
+//