Add ddl support to drawing to wrapped vulkan secondary command buffers.
Bug: skia:
Change-Id: I3ddb6b1e923b8c1733b6a0e219efffa36e665fa2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/189282
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index d65320a..d4f5555 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -691,7 +691,8 @@
sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
LazyInstantiateCallback&& callback, const GrBackendFormat& format,
const GrSurfaceDesc& desc, GrSurfaceOrigin origin, GrInternalSurfaceFlags surfaceFlags,
- const TextureInfo* textureInfo, SkBackingFit fit, SkBudgeted budgeted) {
+ const TextureInfo* textureInfo, SkBackingFit fit, SkBudgeted budgeted,
+ bool wrapsVkSecondaryCB) {
SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
(desc.fWidth > 0 && desc.fHeight > 0));
@@ -714,13 +715,21 @@
: LazyInstantiationType::kMultipleUse;
if (textureInfo) {
+ // Wrapped vulkan secondary command buffers don't support texturing since we won't have an
+ // actual VkImage to texture from.
+ SkASSERT(!wrapsVkSecondaryCB);
return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(
std::move(callback), lazyType, format, desc, origin, textureInfo->fMipMapped,
fit, budgeted, surfaceFlags));
}
+ GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB =
+ wrapsVkSecondaryCB ? GrRenderTargetProxy::WrapsVkSecondaryCB::kYes
+ : GrRenderTargetProxy::WrapsVkSecondaryCB::kNo;
+
return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
- std::move(callback), lazyType, format, desc, origin, fit, budgeted, surfaceFlags));
+ std::move(callback), lazyType, format, desc, origin, fit, budgeted, surfaceFlags,
+ vkSCB));
}
sk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(LazyInstantiateCallback&& callback,
diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h
index 8f3007d..40f2e62 100644
--- a/src/gpu/GrProxyProvider.h
+++ b/src/gpu/GrProxyProvider.h
@@ -180,7 +180,8 @@
GrInternalSurfaceFlags,
const TextureInfo*,
SkBackingFit,
- SkBudgeted);
+ SkBudgeted,
+ bool wrapsVkSecondaryCB);
/**
* Fully lazy proxies have unspecified width and height. Methods that rely on those values
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
index 3f7b7e0..a9f23ff 100644
--- a/src/gpu/GrRenderTargetProxy.cpp
+++ b/src/gpu/GrRenderTargetProxy.cpp
@@ -39,12 +39,13 @@
LazyInstantiationType lazyType,
const GrBackendFormat& format, const GrSurfaceDesc& desc,
GrSurfaceOrigin origin, SkBackingFit fit,
- SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)
+ SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags,
+ WrapsVkSecondaryCB wrapsVkSecondaryCB)
: INHERITED(std::move(callback), lazyType, format, desc, origin, fit, budgeted,
surfaceFlags)
, fSampleCnt(desc.fSampleCnt)
, fNeedsStencil(false)
- , fWrapsVkSecondaryCB(WrapsVkSecondaryCB::kNo) {
+ , fWrapsVkSecondaryCB(wrapsVkSecondaryCB) {
SkASSERT(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags));
}
diff --git a/src/gpu/GrTextureRenderTargetProxy.cpp b/src/gpu/GrTextureRenderTargetProxy.cpp
index 3e52b2c..d217876 100644
--- a/src/gpu/GrTextureRenderTargetProxy.cpp
+++ b/src/gpu/GrTextureRenderTargetProxy.cpp
@@ -46,7 +46,7 @@
// Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null
// callbacks to the texture and RT proxies simply to route to the appropriate constructors.
, GrRenderTargetProxy(LazyInstantiateCallback(), lazyType, format, desc, origin, fit,
- budgeted, surfaceFlags)
+ budgeted, surfaceFlags, WrapsVkSecondaryCB::kNo)
, GrTextureProxy(LazyInstantiateCallback(), lazyType, format, desc, origin, mipMapped,
fit, budgeted, surfaceFlags) {}
diff --git a/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp b/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp
index 7618141..8083f57 100644
--- a/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp
+++ b/src/gpu/vk/GrVkSecondaryCBDrawContext.cpp
@@ -9,10 +9,13 @@
#include "GrContext.h"
#include "GrContextPriv.h"
+#include "GrContextThreadSafeProxyPriv.h"
#include "GrRenderTargetContext.h"
+#include "SkDeferredDisplayList.h"
#include "SkGpuDevice.h"
#include "SkImageInfo.h"
-#include "SkSurfaceProps.h"
+#include "SkSurfaceCharacterization.h"
+#include "SkSurfacePriv.h"
#include "vk/GrVkTypes.h"
sk_sp<GrVkSecondaryCBDrawContext> GrVkSecondaryCBDrawContext::Make(GrContext* ctx,
@@ -39,11 +42,14 @@
return nullptr;
}
- return sk_sp<GrVkSecondaryCBDrawContext>(new GrVkSecondaryCBDrawContext(std::move(device)));
+ return sk_sp<GrVkSecondaryCBDrawContext>(new GrVkSecondaryCBDrawContext(std::move(device),
+ props));
}
-GrVkSecondaryCBDrawContext::GrVkSecondaryCBDrawContext(sk_sp<SkGpuDevice> device)
- : fDevice(device) {}
+GrVkSecondaryCBDrawContext::GrVkSecondaryCBDrawContext(sk_sp<SkGpuDevice> device,
+ const SkSurfaceProps* props)
+ : fDevice(device)
+ , fProps(SkSurfacePropsCopyOrDefault(props)) {}
GrVkSecondaryCBDrawContext::~GrVkSecondaryCBDrawContext() {
SkASSERT(!fDevice);
@@ -71,3 +77,96 @@
fDevice.reset();
}
+bool GrVkSecondaryCBDrawContext::characterize(SkSurfaceCharacterization* characterization) const {
+ GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
+ GrContext* ctx = fDevice->context();
+
+ int maxResourceCount;
+ size_t maxResourceBytes;
+ ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
+
+ // We current don't support textured GrVkSecondaryCBDrawContexts.
+ SkASSERT(!rtc->asTextureProxy());
+
+ // TODO: the addition of colorType to the surfaceContext should remove this calculation
+ SkColorType ct;
+ if (!GrPixelConfigToColorType(rtc->colorSpaceInfo().config(), &ct)) {
+ return false;
+ }
+
+ SkImageInfo ii = SkImageInfo::Make(rtc->width(), rtc->height(), ct, kPremul_SkAlphaType,
+ rtc->colorSpaceInfo().refColorSpace());
+
+ characterization->set(ctx->threadSafeProxy(), maxResourceBytes, ii, rtc->origin(),
+ rtc->colorSpaceInfo().config(), rtc->fsaaType(), rtc->numStencilSamples(),
+ SkSurfaceCharacterization::Textureable(false),
+ SkSurfaceCharacterization::MipMapped(false),
+ SkSurfaceCharacterization::UsesGLFBO0(false),
+ SkSurfaceCharacterization::VulkanSecondaryCBCompatible(true),
+ this->props());
+
+ return true;
+}
+
+bool GrVkSecondaryCBDrawContext::isCompatible(
+ const SkSurfaceCharacterization& characterization) const {
+ GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
+ GrContext* ctx = fDevice->context();
+
+ if (!characterization.isValid()) {
+ return false;
+ }
+
+ if (!characterization.vulkanSecondaryCBCompatible()) {
+ return false;
+ }
+
+ // As long as the current state in the context allows for greater or equal resources,
+ // we allow the DDL to be replayed.
+ // DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
+ int maxResourceCount;
+ size_t maxResourceBytes;
+ ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
+
+ if (characterization.isTextureable()) {
+ // We don't support textureable DDL when rendering to a GrVkSecondaryCBDrawContext.
+ return false;
+ }
+
+ if (characterization.usesGLFBO0()) {
+ return false;
+ }
+
+ // TODO: the addition of colorType to the surfaceContext should remove this calculation
+ SkColorType rtcColorType;
+ if (!GrPixelConfigToColorType(rtc->colorSpaceInfo().config(), &rtcColorType)) {
+ return false;
+ }
+
+ return characterization.contextInfo() && characterization.contextInfo()->priv().matches(ctx) &&
+ characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
+ characterization.origin() == rtc->origin() &&
+ characterization.config() == rtc->colorSpaceInfo().config() &&
+ characterization.width() == rtc->width() &&
+ characterization.height() == rtc->height() &&
+ characterization.colorType() == rtcColorType &&
+ characterization.fsaaType() == rtc->fsaaType() &&
+ characterization.stencilCount() == rtc->numStencilSamples() &&
+ SkColorSpace::Equals(characterization.colorSpace(),
+ rtc->colorSpaceInfo().colorSpace()) &&
+ characterization.surfaceProps() == rtc->surfaceProps();
+}
+
+bool GrVkSecondaryCBDrawContext::draw(SkDeferredDisplayList* ddl) {
+ if (!ddl || !this->isCompatible(ddl->characterization())) {
+ return false;
+ }
+
+ GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
+ GrContext* ctx = fDevice->context();
+
+ ctx->priv().copyOpListsFromDDL(ddl, rtc->asRenderTargetProxy());
+ return true;
+}
+
+
diff --git a/src/gpu/vk/GrVkSecondaryCBDrawContext.h b/src/gpu/vk/GrVkSecondaryCBDrawContext.h
index c6ea9f9..23d6903 100644
--- a/src/gpu/vk/GrVkSecondaryCBDrawContext.h
+++ b/src/gpu/vk/GrVkSecondaryCBDrawContext.h
@@ -10,6 +10,7 @@
#include "SkTypes.h"
#include "SkRefCnt.h"
+#include "SkSurfaceProps.h"
class GrBackendSemaphore;
class GrContext;
@@ -91,15 +92,20 @@
// are still in use by the GPU.
void releaseResources();
+ const SkSurfaceProps& props() const { return fProps; }
+
// TODO: Fill out these calls to support DDL
bool characterize(SkSurfaceCharacterization* characterization) const;
bool draw(SkDeferredDisplayList* deferredDisplayList);
private:
- explicit GrVkSecondaryCBDrawContext(sk_sp<SkGpuDevice>);
+ explicit GrVkSecondaryCBDrawContext(sk_sp<SkGpuDevice>, const SkSurfaceProps*);
+
+ bool isCompatible(const SkSurfaceCharacterization& characterization) const;
sk_sp<SkGpuDevice> fDevice;
std::unique_ptr<SkCanvas> fCachedCanvas;
+ const SkSurfaceProps fProps;
typedef SkRefCnt INHERITED;
};