Use LazyProxy to set up Metal swapchain.
The purpose of this is to delay acquiring the next drawable in the swapchain to avoid stalling and gain better parallel execution between the CPU and GPU. Change-Id: I40ef7672394fd00616de43685530d2feaf7cab2d Reviewed-on: https://skia-review.googlesource.com/c/skia/+/249005 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
7b86d4e8a2
commit
cbf59e0e39
@ -5,13 +5,23 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/gpu/GrBackendSurface.h"
|
||||
#include "include/gpu/GrContext.h"
|
||||
#include "include/gpu/mtl/GrMtlTypes.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrProxyProvider.h"
|
||||
#include "src/gpu/GrRenderTargetContext.h"
|
||||
#include "src/gpu/GrResourceProvider.h"
|
||||
#include "src/gpu/GrResourceProviderPriv.h"
|
||||
#include "src/image/SkSurface_Gpu.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
#include "include/gpu/GrSurface.h"
|
||||
#include "src/gpu/mtl/GrMtlRenderTarget.h"
|
||||
|
||||
#ifdef SK_METAL
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
@ -24,37 +34,68 @@ sk_sp<SkSurface> SkSurface::MakeFromCAMetalLayer(GrContext* context,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
const SkSurfaceProps* surfaceProps,
|
||||
GrMTLHandle* drawable) {
|
||||
// TODO: Apple recommends grabbing the drawable (which we're implicitly doing here)
|
||||
// for as little time as possible. I'm not sure it matters for our test apps, but
|
||||
// you can get better throughput by doing any offscreen renders, texture uploads, or
|
||||
// other non-dependant tasks first before grabbing the drawable.
|
||||
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
|
||||
const GrCaps* caps = context->priv().caps();
|
||||
|
||||
CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer;
|
||||
id<CAMetalDrawable> currentDrawable = [metalLayer nextDrawable];
|
||||
GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(metalLayer.pixelFormat);
|
||||
|
||||
GrMtlTextureInfo fbInfo;
|
||||
fbInfo.fTexture.retain((__bridge const void*)(currentDrawable.texture));
|
||||
GrColorType grColorType = SkColorTypeToGrColorType(colorType);
|
||||
|
||||
CGSize size = [metalLayer drawableSize];
|
||||
sk_sp<SkSurface> surface;
|
||||
if (sampleCnt <= 1) {
|
||||
GrBackendRenderTarget backendRT(size.width,
|
||||
size.height,
|
||||
sampleCnt,
|
||||
fbInfo);
|
||||
|
||||
surface = SkSurface::MakeFromBackendRenderTarget(context, backendRT, origin, colorType,
|
||||
colorSpace, surfaceProps);
|
||||
} else {
|
||||
GrBackendTexture backendTexture(size.width,
|
||||
size.height,
|
||||
GrMipMapped::kNo,
|
||||
fbInfo);
|
||||
|
||||
surface = SkSurface::MakeFromBackendTexture(context, backendTexture, origin, sampleCnt,
|
||||
colorType, colorSpace, surfaceProps);
|
||||
GrPixelConfig config = caps->getConfigFromBackendFormat(backendFormat, grColorType);
|
||||
if (config == kUnknown_GrPixelConfig) {
|
||||
return nullptr;
|
||||
}
|
||||
*drawable = (__bridge_retained GrMTLHandle) currentDrawable;
|
||||
|
||||
GrSurfaceDesc desc;
|
||||
desc.fWidth = metalLayer.frame.size.width;
|
||||
desc.fHeight = metalLayer.frame.size.height;
|
||||
desc.fConfig = config;
|
||||
|
||||
sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
|
||||
[layer, drawable, sampleCnt, config](GrResourceProvider* resourceProvider) {
|
||||
CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer;
|
||||
id<CAMetalDrawable> currentDrawable = [metalLayer nextDrawable];
|
||||
|
||||
CGSize size = [metalLayer drawableSize];
|
||||
GrSurfaceDesc desc;
|
||||
desc.fWidth = size.width;
|
||||
desc.fHeight = size.height;
|
||||
desc.fConfig = config;
|
||||
|
||||
GrMtlGpu* mtlGpu = (GrMtlGpu*) resourceProvider->priv().gpu();
|
||||
auto surface = GrMtlRenderTarget::MakeWrappedRenderTarget(mtlGpu, desc, sampleCnt,
|
||||
currentDrawable.texture);
|
||||
if (surface && sampleCnt > 1) {
|
||||
surface->setRequiresManualMSAAResolve();
|
||||
}
|
||||
|
||||
*drawable = (__bridge_retained GrMTLHandle) currentDrawable;
|
||||
return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
|
||||
},
|
||||
backendFormat,
|
||||
desc,
|
||||
sampleCnt,
|
||||
origin,
|
||||
sampleCnt > 1 ? GrInternalSurfaceFlags::kRequiresManualMSAAResolve
|
||||
: GrInternalSurfaceFlags::kNone,
|
||||
nullptr, // not textureable
|
||||
GrMipMapsStatus::kNotAllocated,
|
||||
SkBackingFit::kExact,
|
||||
SkBudgeted::kYes,
|
||||
GrProtected::kNo,
|
||||
false,
|
||||
GrSurfaceProxy::UseAllocator::kYes);
|
||||
|
||||
auto c = context->priv().makeWrappedSurfaceContext(std::move(proxy),
|
||||
grColorType,
|
||||
kPremul_SkAlphaType,
|
||||
colorSpace,
|
||||
surfaceProps);
|
||||
SkASSERT(c->asRenderTargetContext());
|
||||
std::unique_ptr<GrRenderTargetContext> rtc(c.release()->asRenderTargetContext());
|
||||
|
||||
sk_sp<SkSurface> surface = SkSurface_Gpu::MakeWrappedRenderTarget(context, std::move(rtc));
|
||||
return surface;
|
||||
}
|
||||
#endif
|
||||
|
@ -44,7 +44,7 @@ protected:
|
||||
id<MTLDevice> fDevice;
|
||||
id<MTLCommandQueue> fQueue;
|
||||
CAMetalLayer* fMetalLayer;
|
||||
id<CAMetalDrawable> fCurrentDrawable;
|
||||
GrMTLHandle fDrawableHandle;
|
||||
};
|
||||
|
||||
} // namespace sk_app
|
||||
|
@ -76,28 +76,27 @@ void MetalWindowContext::destroyContext() {
|
||||
sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
|
||||
sk_sp<SkSurface> surface;
|
||||
if (fContext) {
|
||||
GrMTLHandle drawable;
|
||||
surface = SkSurface::MakeFromCAMetalLayer(fContext.get(), (__bridge GrMTLHandle)fMetalLayer,
|
||||
kTopLeft_GrSurfaceOrigin, fSampleCount,
|
||||
kBGRA_8888_SkColorType,
|
||||
fDisplayParams.fColorSpace,
|
||||
&fDisplayParams.fSurfaceProps,
|
||||
&drawable);
|
||||
// ARC is off in sk_app, so we need to release the CF ref manually
|
||||
fCurrentDrawable = (id<CAMetalDrawable>)drawable;
|
||||
CFRelease(drawable);
|
||||
&fDrawableHandle);
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void MetalWindowContext::swapBuffers() {
|
||||
// ARC is off in sk_app, so we need to release the CF ref manually
|
||||
id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle;
|
||||
CFRelease(fDrawableHandle);
|
||||
|
||||
id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer];
|
||||
commandBuffer.label = @"Present";
|
||||
|
||||
[commandBuffer presentDrawable:fCurrentDrawable];
|
||||
[commandBuffer presentDrawable:currentDrawable];
|
||||
[commandBuffer commit];
|
||||
fCurrentDrawable = nil;
|
||||
}
|
||||
|
||||
void MetalWindowContext::setDisplayParams(const DisplayParams& params) {
|
||||
|
Loading…
Reference in New Issue
Block a user