[graphite] Move work and resource tracking to CommandBuffer base class.
Also adds test of texture copyback to CommandBufferTest, and
endEncoding() to BlitCommandEncoder.
Bug: skia:12466
Change-Id: I57e4646aacc1d950cc16b70d7feeced1a04e6867
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/462078
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/experimental/graphite/src/CommandBuffer.cpp b/experimental/graphite/src/CommandBuffer.cpp
index 5cd9961..c5407c5 100644
--- a/experimental/graphite/src/CommandBuffer.cpp
+++ b/experimental/graphite/src/CommandBuffer.cpp
@@ -11,6 +11,9 @@
#include "experimental/graphite/src/RenderPipeline.h"
#include "src/core/SkTraceEvent.h"
+#include "experimental/graphite/src/Buffer.h"
+#include "experimental/graphite/src/Texture.h"
+
namespace skgpu {
CommandBuffer::CommandBuffer() {}
@@ -21,10 +24,47 @@
fTrackedResources.reset();
}
+void CommandBuffer::beginRenderPass(const RenderPassDesc& renderPassDesc) {
+ this->onBeginRenderPass(renderPassDesc);
+
+ auto& colorInfo = renderPassDesc.fColorAttachment;
+ if (colorInfo.fTexture) {
+ this->trackResource(std::move(colorInfo.fTexture));
+ }
+ if (colorInfo.fStoreOp == StoreOp::kStore) {
+ fHasWork = true;
+ }
+}
+
void CommandBuffer::setRenderPipeline(sk_sp<RenderPipeline> renderPipeline) {
this->onSetRenderPipeline(renderPipeline);
this->trackResource(std::move(renderPipeline));
fHasWork = true;
}
+static bool check_max_blit_width(int widthInPixels) {
+ if (widthInPixels > 32767) {
+ SkASSERT(false); // surfaces should not be this wide anyway
+ return false;
+ }
+ return true;
+}
+
+void CommandBuffer::copyTextureToBuffer(sk_sp<skgpu::Texture> texture,
+ SkIRect srcRect,
+ sk_sp<skgpu::Buffer> buffer,
+ size_t bufferOffset,
+ size_t bufferRowBytes) {
+ if (!check_max_blit_width(srcRect.width())) {
+ return;
+ }
+
+ this->onCopyTextureToBuffer(texture, srcRect, buffer, bufferOffset, bufferRowBytes);
+
+ this->trackResource(std::move(texture));
+ this->trackResource(std::move(buffer));
+
+ fHasWork = true;
+}
+
} // namespace skgpu
diff --git a/experimental/graphite/src/CommandBuffer.h b/experimental/graphite/src/CommandBuffer.h
index cfc5fdc..3adb6e4c 100644
--- a/experimental/graphite/src/CommandBuffer.h
+++ b/experimental/graphite/src/CommandBuffer.h
@@ -9,6 +9,7 @@
#define skgpu_CommandBuffer_DEFINED
#include "experimental/graphite/include/private/GraphiteTypesPriv.h"
+#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/private/SkTArray.h"
@@ -48,16 +49,16 @@
bool hasWork() { return fHasWork; }
- virtual void beginRenderPass(const RenderPassDesc&) = 0;
+ void beginRenderPass(const RenderPassDesc&);
virtual void endRenderPass() = 0;
void setRenderPipeline(sk_sp<RenderPipeline> renderPipeline);
- virtual void copyTextureToBuffer(sk_sp<Texture>,
- SkIRect srcRect,
- sk_sp<Buffer>,
- size_t bufferOffset,
- size_t bufferRowBytes) = 0;
+ void copyTextureToBuffer(sk_sp<Texture>,
+ SkIRect srcRect,
+ sk_sp<Buffer>,
+ size_t bufferOffset,
+ size_t bufferRowBytes);
void draw(PrimitiveType type, unsigned int vertexStart, unsigned int vertexCount) {
this->onDraw(type, vertexStart, vertexCount);
@@ -70,6 +71,16 @@
void trackResource(sk_sp<SkRefCnt> resource) {
fTrackedResources.push_back(std::move(resource));
}
+
+ virtual void onBeginRenderPass(const RenderPassDesc&) = 0;
+
+ virtual void onCopyTextureToBuffer(sk_sp<Texture>,
+ SkIRect srcRect,
+ sk_sp<Buffer>,
+ size_t bufferOffset,
+ size_t bufferRowBytes) = 0;
+
+private:
void releaseResources();
virtual void onSetRenderPipeline(sk_sp<RenderPipeline>&) = 0;
@@ -78,7 +89,6 @@
bool fHasWork = false;
-private:
inline static constexpr int kInitialTrackedResourcesCount = 32;
SkSTArray<kInitialTrackedResourcesCount, sk_sp<SkRefCnt>> fTrackedResources;
};
diff --git a/experimental/graphite/src/mtl/MtlBlitCommandEncoder.h b/experimental/graphite/src/mtl/MtlBlitCommandEncoder.h
index 1abe683..fdc38cc 100644
--- a/experimental/graphite/src/mtl/MtlBlitCommandEncoder.h
+++ b/experimental/graphite/src/mtl/MtlBlitCommandEncoder.h
@@ -56,6 +56,10 @@
destinationBytesPerImage: bufferRowBytes * srcRect.height()];
}
+ void endEncoding() {
+ [(*fCommandEncoder) endEncoding];
+ }
+
private:
BlitCommandEncoder(sk_cfp<id<MTLBlitCommandEncoder>> encoder)
: fCommandEncoder(std::move(encoder)) {}
diff --git a/experimental/graphite/src/mtl/MtlCommandBuffer.h b/experimental/graphite/src/mtl/MtlCommandBuffer.h
index 3248e92..1658946 100644
--- a/experimental/graphite/src/mtl/MtlCommandBuffer.h
+++ b/experimental/graphite/src/mtl/MtlCommandBuffer.h
@@ -41,23 +41,25 @@
}
bool commit();
- void copyTextureToBuffer(sk_sp<skgpu::Texture>,
- SkIRect srcRect,
- sk_sp<skgpu::Buffer>,
- size_t bufferOffset,
- size_t bufferRowBytes) override;
-
private:
CommandBuffer(sk_cfp<id<MTLCommandBuffer>> cmdBuffer, const Gpu* gpu);
- void beginRenderPass(const RenderPassDesc&) override;
+ void onBeginRenderPass(const RenderPassDesc&) override;
void endRenderPass() override;
void onSetRenderPipeline(sk_sp<skgpu::RenderPipeline>&) override;
void onDraw(PrimitiveType type, unsigned int vertexStart, unsigned int vertexCount) override;
+ void onCopyTextureToBuffer(sk_sp<skgpu::Texture>,
+ SkIRect srcRect,
+ sk_sp<skgpu::Buffer>,
+ size_t bufferOffset,
+ size_t bufferRowBytes) override;
+
+
BlitCommandEncoder* getBlitCommandEncoder();
+ void endBlitCommandEncoder();
sk_cfp<id<MTLCommandBuffer>> fCommandBuffer;
sk_sp<RenderCommandEncoder> fActiveRenderCommandEncoder;
diff --git a/experimental/graphite/src/mtl/MtlCommandBuffer.mm b/experimental/graphite/src/mtl/MtlCommandBuffer.mm
index ba7885e..bca53f7 100644
--- a/experimental/graphite/src/mtl/MtlCommandBuffer.mm
+++ b/experimental/graphite/src/mtl/MtlCommandBuffer.mm
@@ -13,7 +13,6 @@
#include "experimental/graphite/src/mtl/MtlRenderCommandEncoder.h"
#include "experimental/graphite/src/mtl/MtlRenderPipeline.h"
#include "experimental/graphite/src/mtl/MtlTexture.h"
-#include "include/core/SkRect.h"
namespace skgpu::mtl {
@@ -49,7 +48,8 @@
CommandBuffer::~CommandBuffer() {}
bool CommandBuffer::commit() {
- // TODO: end any encoding
+ SkASSERT(!fActiveRenderCommandEncoder);
+ this->endBlitCommandEncoder();
[(*fCommandBuffer) commit];
// TODO: better error reporting
@@ -62,8 +62,9 @@
return ((*fCommandBuffer).status != MTLCommandBufferStatusError);
}
-void CommandBuffer::beginRenderPass(const RenderPassDesc& renderPassDesc) {
+void CommandBuffer::onBeginRenderPass(const RenderPassDesc& renderPassDesc) {
SkASSERT(!fActiveRenderCommandEncoder);
+ this->endBlitCommandEncoder();
auto& colorInfo = renderPassDesc.fColorAttachment;
@@ -103,14 +104,7 @@
fActiveRenderCommandEncoder = RenderCommandEncoder::Make(fCommandBuffer.get(),
descriptor.get());
- if (colorTexture) {
- this->trackResource(std::move(colorInfo.fTexture));
- }
this->trackResource(fActiveRenderCommandEncoder);
-
- if (colorInfo.fStoreOp == StoreOp::kStore) {
- fHasWork = true;
- }
}
void CommandBuffer::endRenderPass() {
@@ -119,14 +113,6 @@
fActiveRenderCommandEncoder.reset();
}
-static bool check_max_blit_width(int widthInPixels) {
- if (widthInPixels > 32767) {
- SkASSERT(false); // surfaces should not be this wide anyway
- return false;
- }
- return true;
-}
-
BlitCommandEncoder* CommandBuffer::getBlitCommandEncoder() {
if (fActiveBlitCommandEncoder) {
return fActiveBlitCommandEncoder.get();
@@ -144,17 +130,20 @@
return fActiveBlitCommandEncoder.get();
}
-void CommandBuffer::copyTextureToBuffer(sk_sp<skgpu::Texture> texture,
+void CommandBuffer::endBlitCommandEncoder() {
+ if (fActiveBlitCommandEncoder) {
+ fActiveBlitCommandEncoder->endEncoding();
+ fActiveBlitCommandEncoder.reset();
+ }
+}
+
+void CommandBuffer::onCopyTextureToBuffer(sk_sp<skgpu::Texture> texture,
SkIRect srcRect,
sk_sp<skgpu::Buffer> buffer,
size_t bufferOffset,
size_t bufferRowBytes) {
SkASSERT(!fActiveRenderCommandEncoder);
- if (!check_max_blit_width(srcRect.width())) {
- return;
- }
-
id<MTLTexture> mtlTexture = static_cast<Texture*>(texture.get())->mtlTexture();
id<MTLBuffer> mtlBuffer = static_cast<Buffer*>(buffer.get())->mtlBuffer();
@@ -174,11 +163,6 @@
#ifdef SK_ENABLE_MTL_DEBUG_INFO
blitCmdEncoder->popDebugGroup();
#endif
-
- this->trackResource(std::move(texture));
- this->trackResource(std::move(buffer));
-
- fHasWork = true;
}
void CommandBuffer::onSetRenderPipeline(sk_sp<skgpu::RenderPipeline>& renderPipeline) {
diff --git a/tests/graphite/CommandBufferTest.cpp b/tests/graphite/CommandBufferTest.cpp
index fb33523..179db27 100644
--- a/tests/graphite/CommandBufferTest.cpp
+++ b/tests/graphite/CommandBufferTest.cpp
@@ -11,6 +11,7 @@
#include "experimental/graphite/src/ContextPriv.h"
#include "experimental/graphite/include/mtl/MtlTypes.h"
+#include "experimental/graphite/src/Buffer.h"
#include "experimental/graphite/src/CommandBuffer.h"
#include "experimental/graphite/src/Gpu.h"
#include "experimental/graphite/src/RenderPipeline.h"
@@ -52,8 +53,10 @@
sk_sp<Texture> texture = gpu->resourceProvider()->findOrCreateTexture(textureSize,
textureInfo);
+ REPORTER_ASSERT(reporter, texture);
+
RenderPassDesc renderPassDesc = {};
- renderPassDesc.fColorAttachment.fTexture = std::move(texture);
+ renderPassDesc.fColorAttachment.fTexture = texture;
renderPassDesc.fColorAttachment.fLoadOp = LoadOp::kClear;
renderPassDesc.fColorAttachment.fStoreOp = StoreOp::kStore;
renderPassDesc.fClearColor = { 1, 0, 0, 1 };
@@ -67,10 +70,21 @@
commandBuffer->endRenderPass();
+ sk_sp<Buffer> buffer = gpu->resourceProvider()->findOrCreateBuffer(1024*768*4,
+ BufferType::kXferGpuToCpu,
+ PrioritizeGpuReads::kNo);
+ REPORTER_ASSERT(reporter, buffer);
+ SkIRect srcRect = { 0, 0, 1024, 768 };
+ size_t rowBytes = 1024*4;
+ commandBuffer->copyTextureToBuffer(texture, srcRect, buffer, 0, rowBytes);
+
bool result = gpu->submit(commandBuffer);
REPORTER_ASSERT(reporter, result);
gpu->checkForFinishedWork(skgpu::SyncToCpu::kYes);
+ uint32_t* pixels = (uint32_t*)(buffer->map());
+ REPORTER_ASSERT(reporter, pixels[0] == 0xffff0000);
+
#if GRAPHITE_TEST_UTILS && CAPTURE_COMMANDBUFFER
gpu->testingOnly_endCapture();
#endif