Add GrVkTexelBuffer class

Bug: skia:
Change-Id: I6111902f58df3af92702d974a52d9c7f267634d4
Reviewed-on: https://skia-review.googlesource.com/15628
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 92dc7d6..1fc1488 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -484,6 +484,8 @@
   "$_src/gpu/vk/GrVkBackendContext.cpp",
   "$_src/gpu/vk/GrVkBuffer.cpp",
   "$_src/gpu/vk/GrVkBuffer.h",
+  "$_src/gpu/vk/GrVkBufferView.cpp",
+  "$_src/gpu/vk/GrVkBufferView.h",
   "$_src/gpu/vk/GrVkCaps.cpp",
   "$_src/gpu/vk/GrVkCaps.h",
   "$_src/gpu/vk/GrVkCommandBuffer.cpp",
@@ -537,6 +539,8 @@
   "$_src/gpu/vk/GrVkSemaphore.h",
   "$_src/gpu/vk/GrVkStencilAttachment.cpp",
   "$_src/gpu/vk/GrVkStencilAttachment.h",
+  "$_src/gpu/vk/GrVkTexelBuffer.cpp",
+  "$_src/gpu/vk/GrVkTexelBuffer.h",
   "$_src/gpu/vk/GrVkTexture.cpp",
   "$_src/gpu/vk/GrVkTexture.h",
   "$_src/gpu/vk/GrVkTextureRenderTarget.cpp",
diff --git a/src/gpu/vk/GrVkBuffer.cpp b/src/gpu/vk/GrVkBuffer.cpp
index a0faa21..d0332b9 100644
--- a/src/gpu/vk/GrVkBuffer.cpp
+++ b/src/gpu/vk/GrVkBuffer.cpp
@@ -44,6 +44,8 @@
         case kCopyWrite_Type:
             bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
             break;
+        case kTexel_Type:
+            bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
     }
     if (!desc.fDynamic) {
         bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
diff --git a/src/gpu/vk/GrVkBuffer.h b/src/gpu/vk/GrVkBuffer.h
index e58d5e4..6d0c1fd 100644
--- a/src/gpu/vk/GrVkBuffer.h
+++ b/src/gpu/vk/GrVkBuffer.h
@@ -43,6 +43,7 @@
         kVertex_Type,
         kIndex_Type,
         kUniform_Type,
+        kTexel_Type,
         kCopyRead_Type,
         kCopyWrite_Type,
     };
diff --git a/src/gpu/vk/GrVkBufferView.cpp b/src/gpu/vk/GrVkBufferView.cpp
new file mode 100644
index 0000000..b7e35c7
--- /dev/null
+++ b/src/gpu/vk/GrVkBufferView.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrVkBufferView.h"
+#include "GrVkGpu.h"
+#include "GrVkUtil.h"
+
+const GrVkBufferView* GrVkBufferView::Create(const GrVkGpu* gpu, VkBuffer buffer, VkFormat format,
+                                             VkDeviceSize offset, VkDeviceSize range) {
+    VkBufferView bufferView;
+
+    // Create the VkBufferView
+    VkBufferViewCreateInfo viewInfo;
+    memset(&viewInfo, 0, sizeof(VkBufferViewCreateInfo));
+    viewInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
+    viewInfo.pNext = nullptr;
+    viewInfo.flags = 0;
+    viewInfo.buffer = buffer;
+    viewInfo.format = format;
+    viewInfo.offset = offset;
+    viewInfo.range = range;
+
+    VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateBufferView(gpu->device(), &viewInfo,
+                                                                   nullptr, &bufferView));
+    if (err) {
+        return nullptr;
+    }
+
+    return new GrVkBufferView(bufferView);
+}
+
+void GrVkBufferView::freeGPUData(const GrVkGpu* gpu) const {
+    GR_VK_CALL(gpu->vkInterface(), DestroyBufferView(gpu->device(), fBufferView, nullptr));
+}
diff --git a/src/gpu/vk/GrVkBufferView.h b/src/gpu/vk/GrVkBufferView.h
new file mode 100644
index 0000000..fc53258
--- /dev/null
+++ b/src/gpu/vk/GrVkBufferView.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrVkBufferView_DEFINED
+#define GrVkBufferView_DEFINED
+
+#include "GrTypes.h"
+
+#include "GrVkResource.h"
+
+#include "vk/GrVkDefines.h"
+
+class GrVkBufferView : public GrVkResource {
+public:
+    static const GrVkBufferView* Create(const GrVkGpu* gpu, VkBuffer buffer, VkFormat format,
+                                        VkDeviceSize offset, VkDeviceSize range);
+
+    VkBufferView bufferView() const { return fBufferView; }
+
+#ifdef SK_TRACE_VK_RESOURCES
+    void dumpInfo() const override {
+        SkDebugf("GrVkBufferView: %d (%d refs)\n", fBufferView, this->getRefCnt());
+    }
+#endif
+
+private:
+    GrVkBufferView(VkBufferView bufferView) : INHERITED(), fBufferView(bufferView) {}
+
+    GrVkBufferView(const GrVkBufferView&);
+    GrVkBufferView& operator=(const GrVkBufferView&);
+
+    void freeGPUData(const GrVkGpu* gpu) const override;
+
+    VkBufferView  fBufferView;
+
+    typedef GrVkResource INHERITED;
+};
+
+#endif
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 447e59d..c271133 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -27,6 +27,7 @@
 #include "GrVkRenderPass.h"
 #include "GrVkResourceProvider.h"
 #include "GrVkSemaphore.h"
+#include "GrVkTexelBuffer.h"
 #include "GrVkTexture.h"
 #include "GrVkTextureRenderTarget.h"
 #include "GrVkTransferBuffer.h"
@@ -151,6 +152,7 @@
     fHeaps[kVertexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
     fHeaps[kIndexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
     fHeaps[kUniformBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 256*1024));
+    fHeaps[kTexelBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
     fHeaps[kCopyReadBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
     fHeaps[kCopyWriteBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
 }
@@ -256,6 +258,13 @@
             SkASSERT(kStream_GrAccessPattern == accessPattern);
             buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
             break;
+        case kTexel_GrBufferType:
+            SkASSERT(kDynamic_GrAccessPattern == accessPattern);
+            buff = GrVkTexelBuffer::Create(this, size);
+            break;
+        case kDrawIndirect_GrBufferType:
+            SkFAIL("DrawIndirect Buffers not supported  in vulkan backend.");
+            return nullptr;
         default:
             SkFAIL("Unknown buffer type.");
             return nullptr;
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index ac21923..b47d428 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -151,6 +151,7 @@
         kVertexBuffer_Heap,
         kIndexBuffer_Heap,
         kUniformBuffer_Heap,
+        kTexelBuffer_Heap,
         kCopyReadBuffer_Heap,
         kCopyWriteBuffer_Heap,
 
diff --git a/src/gpu/vk/GrVkImageView.h b/src/gpu/vk/GrVkImageView.h
index 1398987..cd9f831 100644
--- a/src/gpu/vk/GrVkImageView.h
+++ b/src/gpu/vk/GrVkImageView.h
@@ -21,7 +21,7 @@
         kStencil_Type
     };
 
-    static const GrVkImageView* Create(const GrVkGpu* gpu, VkImage image, VkFormat format, 
+    static const GrVkImageView* Create(const GrVkGpu* gpu, VkImage image, VkFormat format,
                                        Type viewType, uint32_t miplevels);
 
     VkImageView imageView() const { return fImageView; }
diff --git a/src/gpu/vk/GrVkMemory.cpp b/src/gpu/vk/GrVkMemory.cpp
index 2764102..31dea10 100644
--- a/src/gpu/vk/GrVkMemory.cpp
+++ b/src/gpu/vk/GrVkMemory.cpp
@@ -40,14 +40,16 @@
         GrVkGpu::kVertexBuffer_Heap,
         GrVkGpu::kIndexBuffer_Heap,
         GrVkGpu::kUniformBuffer_Heap,
+        GrVkGpu::kTexelBuffer_Heap,
         GrVkGpu::kCopyReadBuffer_Heap,
         GrVkGpu::kCopyWriteBuffer_Heap,
     };
     GR_STATIC_ASSERT(0 == GrVkBuffer::kVertex_Type);
     GR_STATIC_ASSERT(1 == GrVkBuffer::kIndex_Type);
     GR_STATIC_ASSERT(2 == GrVkBuffer::kUniform_Type);
-    GR_STATIC_ASSERT(3 == GrVkBuffer::kCopyRead_Type);
-    GR_STATIC_ASSERT(4 == GrVkBuffer::kCopyWrite_Type);
+    GR_STATIC_ASSERT(3 == GrVkBuffer::kTexel_Type);
+    GR_STATIC_ASSERT(4 == GrVkBuffer::kCopyRead_Type);
+    GR_STATIC_ASSERT(5 == GrVkBuffer::kCopyWrite_Type);
 
     return kBufferToHeap[type];
 }
diff --git a/src/gpu/vk/GrVkTexelBuffer.cpp b/src/gpu/vk/GrVkTexelBuffer.cpp
new file mode 100644
index 0000000..b579ea0
--- /dev/null
+++ b/src/gpu/vk/GrVkTexelBuffer.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrVkTexelBuffer.h"
+
+#include "GrVkGpu.h"
+
+GrVkTexelBuffer::GrVkTexelBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc,
+                                   const GrVkBuffer::Resource* bufferResource)
+    : INHERITED(gpu, desc.fSizeInBytes, kTexel_GrBufferType,
+                kDynamic_GrAccessPattern)
+    , GrVkBuffer(desc, bufferResource) {
+    this->registerWithCache(SkBudgeted::kYes);
+}
+
+GrVkTexelBuffer* GrVkTexelBuffer::Create(GrVkGpu* gpu, size_t size) {
+    GrVkBuffer::Desc desc;
+    desc.fDynamic = true;
+    desc.fType = GrVkBuffer::kTexel_Type;
+    desc.fSizeInBytes = size;
+
+    const GrVkBuffer::Resource* bufferResource = GrVkBuffer::Create(gpu, desc);
+    if (!bufferResource) {
+        return nullptr;
+    }
+    GrVkTexelBuffer* buffer = new GrVkTexelBuffer(gpu, desc, bufferResource);
+    if (!buffer) {
+        bufferResource->unref(gpu);
+    }
+    return buffer;
+}
+
+void GrVkTexelBuffer::onRelease() {
+    if (!this->wasDestroyed()) {
+        this->vkRelease(this->getVkGpu());
+    }
+
+    INHERITED::onRelease();
+}
+
+void GrVkTexelBuffer::onAbandon() {
+    this->vkAbandon();
+    INHERITED::onAbandon();
+}
+
+void GrVkTexelBuffer::onMap() {
+    if (!this->wasDestroyed()) {
+        this->GrBuffer::fMapPtr = this->vkMap(this->getVkGpu());
+    }
+}
+
+void GrVkTexelBuffer::onUnmap() {
+    if (!this->wasDestroyed()) {
+        this->vkUnmap(this->getVkGpu());
+    }
+}
+
+bool GrVkTexelBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
+    if (!this->wasDestroyed()) {
+        return this->vkUpdateData(this->getVkGpu(), src, srcSizeInBytes);
+    } else {
+        return false;
+    }
+}
+
+GrVkGpu* GrVkTexelBuffer::getVkGpu() const {
+    SkASSERT(!this->wasDestroyed());
+    return static_cast<GrVkGpu*>(this->getGpu());
+}
diff --git a/src/gpu/vk/GrVkTexelBuffer.h b/src/gpu/vk/GrVkTexelBuffer.h
new file mode 100644
index 0000000..449e3fc
--- /dev/null
+++ b/src/gpu/vk/GrVkTexelBuffer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrVkTexelBuffer_DEFINED
+#define GrVkTexelBuffer_DEFINED
+
+#include "GrBuffer.h"
+#include "GrVkBuffer.h"
+
+class GrVkGpu;
+
+class GrVkTexelBuffer : public GrBuffer, public GrVkBuffer {
+public:
+    static GrVkTexelBuffer* Create(GrVkGpu* gpu, size_t size);
+
+protected:
+    void onAbandon() override;
+    void onRelease() override;
+
+private:
+    GrVkTexelBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc,
+                    const GrVkBuffer::Resource* resource);
+
+    void onMap() override;
+    void onUnmap() override;
+    bool onUpdateData(const void* src, size_t srcSizeInBytes) override;
+
+    GrVkGpu* getVkGpu() const;
+
+    typedef GrBuffer INHERITED;
+};
+
+#endif