[graphite] Add Buffer and MtlBuffer classes.
Bug: skia:12466
Change-Id: I3252f36c3f78642c55f127379ceba99b4845822e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/458717
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/experimental/graphite/include/private/GraphiteTypesPriv.h b/experimental/graphite/include/private/GraphiteTypesPriv.h
index 99f7f80..13ddf21 100644
--- a/experimental/graphite/include/private/GraphiteTypesPriv.h
+++ b/experimental/graphite/include/private/GraphiteTypesPriv.h
@@ -9,10 +9,19 @@
#define skgpu_GraphiteTypesPriv_DEFINED
#include "experimental/graphite/include/GraphiteTypes.h"
+#include "include/core/SkMath.h"
namespace skgpu {
/**
+ * align up to a power of 2
+ */
+static inline constexpr size_t AlignTo(size_t x, size_t alignment) {
+ SkASSERT(alignment && SkIsPow2(alignment));
+ return (x + alignment - 1) & ~(alignment - 1);
+}
+
+/**
* Is the Texture renderable or not
*/
enum class Renderable : bool {
@@ -26,6 +35,28 @@
kDepthStencil,
};
+/**
+ * What a GPU buffer will be used for
+ */
+enum class BufferType {
+ kVertex,
+ kIndex,
+ kXferCpuToGpu,
+ kXferGpuToCpu,
+ kUniform,
+};
+static const int kBufferTypeCount = static_cast<int>(BufferType::kUniform) + 1;
+
+/**
+ * When creating the memory for a resource should we use a memory type that prioritizes the
+ * effeciency of GPU reads even if it involves extra work to write CPU data to it. For example, we
+ * would want this for buffers that we cache to read the same data many times on the GPU.
+ */
+enum class PrioritizeGpuReads : bool {
+ kNo = false,
+ kYes = true,
+};
+
} // namespace skgpu
#endif // skgpu_GraphiteTypesPriv_DEFINED
diff --git a/experimental/graphite/src/Buffer.cpp b/experimental/graphite/src/Buffer.cpp
new file mode 100644
index 0000000..fdca838
--- /dev/null
+++ b/experimental/graphite/src/Buffer.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "experimental/graphite/src/Buffer.h"
+
+namespace skgpu {
+
+void* Buffer::map() {
+ if (!this->isMapped()) {
+ this->onMap();
+ }
+ return fMapPtr;
+}
+
+void Buffer::unmap() {
+ SkASSERT(this->isMapped());
+ this->onUnmap();
+ fMapPtr = nullptr;
+}
+
+} // namespace skgpu
+
diff --git a/experimental/graphite/src/Buffer.h b/experimental/graphite/src/Buffer.h
new file mode 100644
index 0000000..edb142e
--- /dev/null
+++ b/experimental/graphite/src/Buffer.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skgpu_Buffer_DEFINED
+#define skgpu_Buffer_DEFINED
+
+#include "experimental/graphite/include/private/GraphiteTypesPriv.h"
+#include "include/core/SkRefCnt.h"
+
+namespace skgpu {
+
+class Buffer : public SkRefCnt {
+public:
+ size_t size() const { return fSize; }
+
+ void* map();
+ void unmap();
+
+ bool isMapped() const { return fMapPtr; }
+
+protected:
+ Buffer(size_t size, BufferType type, PrioritizeGpuReads prioritizeGpuReads)
+ : fSize(size), fType(type), fPrioritizeGpuReads(prioritizeGpuReads) {}
+
+ void* fMapPtr = nullptr;
+
+private:
+ virtual void onMap() = 0;
+ virtual void onUnmap() = 0;
+
+ // TODO: Remove these getters once we start using fType and fPrioritizeGpuReads in key
+ // generation. For now this silences compiler unused member warnings.
+ BufferType bufferType() const { return fType; }
+ PrioritizeGpuReads prioritizeGpuReads() const { return fPrioritizeGpuReads; }
+
+ size_t fSize;
+ BufferType fType;
+ PrioritizeGpuReads fPrioritizeGpuReads;
+};
+
+} // namespace skgpu
+
+#endif // skgpu_Buffer_DEFINED
+
diff --git a/experimental/graphite/src/mtl/MtlBuffer.h b/experimental/graphite/src/mtl/MtlBuffer.h
new file mode 100644
index 0000000..d110961
--- /dev/null
+++ b/experimental/graphite/src/mtl/MtlBuffer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skgpu_MtlBuffer_DEFINED
+#define skgpu_MtlBuffer_DEFINED
+
+#include "experimental/graphite/src/Buffer.h"
+
+#include "experimental/graphite/include/mtl/MtlTypes.h"
+
+#import <Metal/Metal.h>
+
+namespace skgpu::mtl {
+
+class Gpu;
+
+class Buffer : public skgpu::Buffer {
+public:
+ sk_sp<Buffer> Make(const Gpu*, size_t size, BufferType type, PrioritizeGpuReads);
+
+private:
+ Buffer(size_t size, BufferType type, PrioritizeGpuReads, sk_cfp<id<MTLBuffer>>);
+
+ void onMap() override;
+ void onUnmap() override;
+
+ sk_cfp<id<MTLBuffer>> fBuffer;
+};
+
+} // namespace skgpu::mtl
+
+#endif // skgpu_MtlBuffer_DEFINED
+
diff --git a/experimental/graphite/src/mtl/MtlBuffer.mm b/experimental/graphite/src/mtl/MtlBuffer.mm
new file mode 100644
index 0000000..05ff8a5
--- /dev/null
+++ b/experimental/graphite/src/mtl/MtlBuffer.mm
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "experimental/graphite/src/mtl/MtlBuffer.h"
+
+#include "experimental/graphite/src/mtl/MtlGpu.h"
+
+namespace skgpu::mtl {
+
+#ifdef SK_ENABLE_MTL_DEBUG_INFO
+NSString* kBufferTypeNames[kBufferTypeCount] = {
+ @"Vertex",
+ @"Index",
+ @"Xfer CPU to GPU",
+ @"Xfer GPU to CPU",
+ @"Uniform",
+};
+#endif
+
+sk_sp<Buffer> Buffer::Make(const Gpu* gpu,
+ size_t size,
+ BufferType type,
+ PrioritizeGpuReads prioritizeGpuReads) {
+ if (size <= 0) {
+ return nullptr;
+ }
+
+ const Caps& mtlCaps = gpu->mtlCaps();
+
+ NSUInteger options = 0;
+ if (@available(macOS 10.11, iOS 9.0, *)) {
+ if (prioritizeGpuReads == PrioritizeGpuReads::kNo) {
+#ifdef SK_BUILD_FOR_MAC
+ if (mtlCaps.isMac()) {
+ options |= MTLResourceStorageModeManaged;
+ } else {
+ SkASSERT(mtlCaps.isApple());
+ options |= MTLResourceStorageModeShared;
+ }
+#else
+ options |= MTLResourceStorageModeShared;
+#endif
+ } else {
+ options |= MTLResourceStorageModePrivate;
+ }
+ }
+
+ size = AlignTo(size, mtlCaps.getMinBufferAlignment());
+ sk_cfp<id<MTLBuffer>> buffer([gpu->device() newBufferWithLength: size options: options]);
+#ifdef SK_ENABLE_MTL_DEBUG_INFO
+ (*buffer).label = kBufferTypeNames[(int)type];
+#endif
+
+ return sk_sp<Buffer>(new Buffer(size, type, prioritizeGpuReads, std::move(buffer)));
+}
+
+Buffer::Buffer(size_t size,
+ BufferType type,
+ PrioritizeGpuReads prioritizeGpuReads,
+ sk_cfp<id<MTLBuffer>> buffer)
+ : skgpu::Buffer(size, type, prioritizeGpuReads)
+ , fBuffer(std::move(buffer)) {}
+
+void Buffer::onMap() {
+ SkASSERT(fBuffer);
+ SkASSERT(!this->isMapped());
+
+ if ((*fBuffer).storageMode == MTLStorageModePrivate) {
+ return;
+ }
+
+ fMapPtr = static_cast<char*>((*fBuffer).contents);
+}
+
+void Buffer::onUnmap() {
+ SkASSERT(fBuffer);
+ SkASSERT(this->isMapped());
+#ifdef SK_BUILD_FOR_MAC
+ if ((*fBuffer).storageMode == MTLStorageModeManaged) {
+ [*fBuffer didModifyRange: NSMakeRange(0, this->size())];
+ }
+#endif
+ fMapPtr = nullptr;
+}
+
+} // namespace skgpu::mtl
+
diff --git a/experimental/graphite/src/mtl/MtlCaps.h b/experimental/graphite/src/mtl/MtlCaps.h
index 3db340c..296e77d 100644
--- a/experimental/graphite/src/mtl/MtlCaps.h
+++ b/experimental/graphite/src/mtl/MtlCaps.h
@@ -29,6 +29,11 @@
uint32_t sampleCount,
Protected) override;
+ bool isMac() const { return fGPUFamily == GPUFamily::kMac; }
+ bool isApple()const { return fGPUFamily == GPUFamily::kApple; }
+
+ size_t getMinBufferAlignment() const { return this->isMac() ? 4 : 1; }
+
private:
void initGPUFamily(const id<MTLDevice>);
@@ -40,8 +45,6 @@
kMac,
kApple,
};
- bool isMac() const { return fGPUFamily == GPUFamily::kMac; }
- bool isApple()const { return fGPUFamily == GPUFamily::kApple; }
static bool GetGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group);
static bool GetGPUFamilyFromFeatureSet(id<MTLDevice> device, GPUFamily* gpuFamily,
int* group);
diff --git a/gn/graphite.gni b/gn/graphite.gni
index 0116a34..d3dfb47 100644
--- a/gn/graphite.gni
+++ b/gn/graphite.gni
@@ -17,6 +17,8 @@
"$_include/SkStuff.h",
"$_include/TextureInfo.h",
"$_include/private/GraphiteTypesPriv.h",
+ "$_src/Buffer.cpp",
+ "$_src/Buffer.h",
"$_src/Caps.cpp",
"$_src/Caps.h",
"$_src/CommandBuffer.cpp",
@@ -69,6 +71,8 @@
"$_include/mtl/MtlBackendContext.h",
"$_include/mtl/MtlTypes.h",
"$_include/private/MtlTypesPriv.h",
+ "$_src/mtl/MtlBuffer.h",
+ "$_src/mtl/MtlBuffer.mm",
"$_src/mtl/MtlCaps.h",
"$_src/mtl/MtlCaps.mm",
"$_src/mtl/MtlCommandBuffer.h",