[graphite] Add command buffer test

Adds test of command buffer submission with GPU recording (if enabled).
Also adds programmatic GPU recording support.

Bug: skia:12466
Change-Id: I85aba9f7e5e09f62f2ddc7040d1ff84bb9b4ae09
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/460337
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2021-10-18 12:15:47 -04:00 committed by SkCQ
parent 2764d524e7
commit 0c56bbaffe
10 changed files with 109 additions and 12 deletions

View File

@ -92,6 +92,9 @@ config("skia_private") {
"SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1", "SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1",
"GR_TEST_UTILS=1", "GR_TEST_UTILS=1",
] ]
if (skia_enable_graphite) {
defines += [ "GRAPHITE_TEST_UTILS=1" ]
}
} }
libs = [] libs = []
lib_dirs = [] lib_dirs = []

View File

@ -7,13 +7,10 @@
#include "experimental/graphite/src/ContextPriv.h" #include "experimental/graphite/src/ContextPriv.h"
#include "experimental/graphite/src/Caps.h"
#include "experimental/graphite/src/Gpu.h"
namespace skgpu { namespace skgpu {
const Caps* ContextPriv::caps() { Gpu* ContextPriv::gpu() {
return fContext->fGpu->caps(); return fContext->fGpu.get();
} }
} // namespace skgpu } // namespace skgpu

View File

@ -12,14 +12,14 @@
namespace skgpu { namespace skgpu {
class Caps; class Gpu;
/** Class that adds methods to Context that are only intended for use internal to Skia. /** Class that adds methods to Context that are only intended for use internal to Skia.
This class is purely a privileged window into Context. It should never have additional This class is purely a privileged window into Context. It should never have additional
data members or virtual methods. */ data members or virtual methods. */
class ContextPriv { class ContextPriv {
public: public:
const Caps* caps(); Gpu* gpu();
private: private:
friend class Context; // to construct/copy this type. friend class Context; // to construct/copy this type.

View File

@ -36,14 +36,19 @@ Gpu::~Gpu() {
fResourceProvider.reset(); fResourceProvider.reset();
} }
sk_sp<const Caps> Gpu::refCaps() const {
return fCaps;
}
bool Gpu::submit(sk_sp<CommandBuffer> commandBuffer) { bool Gpu::submit(sk_sp<CommandBuffer> commandBuffer) {
if (!commandBuffer) { if (!commandBuffer) {
return false; return false;
} }
if (!commandBuffer->hasWork()) { // TODO: re-enable when we have work items to include in command buffer
return true; // if (!commandBuffer->hasWork()) {
} // return true;
// }
return this->onSubmit(std::move(commandBuffer)); return this->onSubmit(std::move(commandBuffer));
} }

View File

@ -28,13 +28,18 @@ public:
* Gets the capabilities of the draw target. * Gets the capabilities of the draw target.
*/ */
const Caps* caps() const { return fCaps.get(); } const Caps* caps() const { return fCaps.get(); }
sk_sp<const Caps> refCaps() const { return fCaps; } sk_sp<const Caps> refCaps() const;
ResourceProvider* resourceProvider() const { return fResourceProvider.get(); } ResourceProvider* resourceProvider() const { return fResourceProvider.get(); }
bool submit(sk_sp<CommandBuffer>); bool submit(sk_sp<CommandBuffer>);
void checkForFinishedWork(SyncToCpu); void checkForFinishedWork(SyncToCpu);
#if GRAPHITE_TEST_UTILS
virtual void testingOnly_startCapture() {}
virtual void testingOnly_endCapture() {}
#endif
protected: protected:
Gpu(sk_sp<const Caps>); Gpu(sk_sp<const Caps>);

View File

@ -34,6 +34,11 @@ private:
bool onSubmit(sk_sp<skgpu::CommandBuffer>) override; bool onSubmit(sk_sp<skgpu::CommandBuffer>) override;
#if GRAPHITE_TEST_UTILS
void testingOnly_startCapture() override;
void testingOnly_endCapture() override;
#endif
sk_cfp<id<MTLDevice>> fDevice; sk_cfp<id<MTLDevice>> fDevice;
sk_cfp<id<MTLCommandQueue>> fQueue; sk_cfp<id<MTLCommandQueue>> fQueue;
}; };

View File

@ -62,4 +62,37 @@ bool Gpu::onSubmit(sk_sp<skgpu::CommandBuffer> commandBuffer) {
return true; return true;
} }
#if GRAPHITE_TEST_UTILS
void Gpu::testingOnly_startCapture() {
if (@available(macOS 10.13, iOS 11.0, *)) {
// TODO: add newer Metal interface as well
MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
if (captureManager.isCapturing) {
return;
}
if (@available(macOS 10.15, iOS 13.0, *)) {
MTLCaptureDescriptor* captureDescriptor = [[MTLCaptureDescriptor alloc] init];
captureDescriptor.captureObject = fQueue.get();
NSError *error;
if (![captureManager startCaptureWithDescriptor: captureDescriptor error:&error])
{
NSLog(@"Failed to start capture, error %@", error);
}
} else {
[captureManager startCaptureWithCommandQueue: fQueue.get()];
}
}
}
void Gpu::testingOnly_endCapture() {
if (@available(macOS 10.13, iOS 11.0, *)) {
MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
if (captureManager.isCapturing) {
[captureManager stopCapture];
}
}
}
#endif
} // namespace skgpu::mtl } // namespace skgpu::mtl

View File

@ -328,6 +328,7 @@ metal_tests_sources = [
graphite_tests_sources = [ graphite_tests_sources = [
"$_tests/graphite/CapsTest.cpp", "$_tests/graphite/CapsTest.cpp",
"$_tests/graphite/CommandBufferTest.cpp",
"$_tests/graphite/MaskTest.cpp", "$_tests/graphite/MaskTest.cpp",
"$_tests/graphite/RectTest.cpp", "$_tests/graphite/RectTest.cpp",
"$_tests/graphite/ShapeTest.cpp", "$_tests/graphite/ShapeTest.cpp",

View File

@ -8,10 +8,12 @@
#include "tests/Test.h" #include "tests/Test.h"
#include "experimental/graphite/include/Context.h" #include "experimental/graphite/include/Context.h"
#include "experimental/graphite/src/Caps.h"
#include "experimental/graphite/src/ContextPriv.h" #include "experimental/graphite/src/ContextPriv.h"
#include "experimental/graphite/src/Gpu.h"
DEF_GRAPHITE_TEST_FOR_CONTEXTS(CapsTest, reporter, context) { DEF_GRAPHITE_TEST_FOR_CONTEXTS(CapsTest, reporter, context) {
// TODO: Jim takes this over // TODO: Jim takes this over
auto caps = context->priv().caps(); auto caps = context->priv().gpu()->caps();
REPORTER_ASSERT(reporter, caps); REPORTER_ASSERT(reporter, caps);
} }

View File

@ -0,0 +1,46 @@
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "tests/Test.h"
#include "experimental/graphite/include/Context.h"
#include "experimental/graphite/src/ContextPriv.h"
#include "experimental/graphite/include/mtl/MtlTypes.h"
#include "experimental/graphite/src/CommandBuffer.h"
#include "experimental/graphite/src/Gpu.h"
#include "experimental/graphite/src/RenderPipeline.h"
#include "experimental/graphite/src/ResourceProvider.h"
#include "experimental/graphite/src/Texture.h"
#if GRAPHITE_TEST_UTILS
// set to 1 if you want to do GPU capture of the commandBuffer
#define CAPTURE_COMMANDBUFFER 0
#endif
/*
* This is to test the various pieces of the CommandBuffer interface.
*/
DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
auto gpu = context->priv().gpu();
REPORTER_ASSERT(reporter, gpu);
#if GRAPHITE_TEST_UTILS && CAPTURE_COMMANDBUFFER
gpu->testingOnly_startCapture();
#endif
auto commandBuffer = gpu->resourceProvider()->createCommandBuffer();
// add test commands here
bool result = gpu->submit(commandBuffer);
REPORTER_ASSERT(reporter, result);
gpu->checkForFinishedWork(skgpu::SyncToCpu::kYes);
#if GRAPHITE_TEST_UTILS && CAPTURE_COMMANDBUFFER
gpu->testingOnly_endCapture();
#endif
}