Restrict ops that can be executed when we have a wrapped vulkan secondary command buffer.
Bug: skia: Change-Id: Ib58ba23053d019988a23cfb489808bad3122d867 Reviewed-on: https://skia-review.googlesource.com/c/178936 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
5f1692c60a
commit
be7fc46627
@ -127,6 +127,8 @@ bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context,
|
|||||||
renderTargetContext->fsaaType(),
|
renderTargetContext->fsaaType(),
|
||||||
GrAllowMixedSamples::kYes,
|
GrAllowMixedSamples::kYes,
|
||||||
*context->contextPriv().caps());
|
*context->contextPriv().caps());
|
||||||
|
SkASSERT(!renderTargetContext->wrapsVkSecondaryCB());
|
||||||
|
canDrawArgs.fTargetIsWrappedVkSecondaryCB = false;
|
||||||
canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
|
canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
|
||||||
|
|
||||||
// the 'false' parameter disallows use of the SW path renderer
|
// the 'false' parameter disallows use of the SW path renderer
|
||||||
@ -156,8 +158,10 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
|
|||||||
// a clip gets complex enough it can just be done in SW regardless
|
// a clip gets complex enough it can just be done in SW regardless
|
||||||
// of whether it would invoke the GrSoftwarePathRenderer.
|
// of whether it would invoke the GrSoftwarePathRenderer.
|
||||||
|
|
||||||
// If we're avoiding stencils, always use SW:
|
// If we're avoiding stencils, always use SW. This includes drawing into a wrapped vulkan
|
||||||
if (context->contextPriv().caps()->avoidStencilBuffers()) {
|
// secondary command buffer which can't handle stencils.
|
||||||
|
if (context->contextPriv().caps()->avoidStencilBuffers() ||
|
||||||
|
renderTargetContext->wrapsVkSecondaryCB()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +262,8 @@ bool GrClipStackClip::applyClipMask(GrContext* context, GrRenderTargetContext* r
|
|||||||
|
|
||||||
// If the stencil buffer is multisampled we can use it to do everything.
|
// If the stencil buffer is multisampled we can use it to do everything.
|
||||||
if ((GrFSAAType::kNone == renderTargetContext->fsaaType() && reducedClip.maskRequiresAA()) ||
|
if ((GrFSAAType::kNone == renderTargetContext->fsaaType() && reducedClip.maskRequiresAA()) ||
|
||||||
context->contextPriv().caps()->avoidStencilBuffers()) {
|
context->contextPriv().caps()->avoidStencilBuffers() ||
|
||||||
|
renderTargetContext->wrapsVkSecondaryCB()) {
|
||||||
sk_sp<GrTextureProxy> result;
|
sk_sp<GrTextureProxy> result;
|
||||||
if (UseSWOnlyPath(context, hasUserStencilSettings, renderTargetContext, reducedClip)) {
|
if (UseSWOnlyPath(context, hasUserStencilSettings, renderTargetContext, reducedClip)) {
|
||||||
// The clip geometry is complex enough that it will be more efficient to create it
|
// The clip geometry is complex enough that it will be more efficient to create it
|
||||||
@ -277,7 +282,8 @@ bool GrClipStackClip::applyClipMask(GrContext* context, GrRenderTargetContext* r
|
|||||||
|
|
||||||
// If alpha or software clip mask creation fails, fall through to the stencil code paths,
|
// If alpha or software clip mask creation fails, fall through to the stencil code paths,
|
||||||
// unless stencils are disallowed.
|
// unless stencils are disallowed.
|
||||||
if (context->contextPriv().caps()->avoidStencilBuffers()) {
|
if (context->contextPriv().caps()->avoidStencilBuffers() ||
|
||||||
|
renderTargetContext->wrapsVkSecondaryCB()) {
|
||||||
SkDebugf("WARNING: Clip mask requires stencil, but stencil unavailable. "
|
SkDebugf("WARNING: Clip mask requires stencil, but stencil unavailable. "
|
||||||
"Clip will be ignored.\n");
|
"Clip will be ignored.\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -50,6 +50,7 @@ bool GrPathRenderer::drawPath(const DrawPathArgs& args) {
|
|||||||
canArgs.fViewMatrix = args.fViewMatrix;
|
canArgs.fViewMatrix = args.fViewMatrix;
|
||||||
canArgs.fShape = args.fShape;
|
canArgs.fShape = args.fShape;
|
||||||
canArgs.fAAType = args.fAAType;
|
canArgs.fAAType = args.fAAType;
|
||||||
|
canArgs.fTargetIsWrappedVkSecondaryCB = args.fRenderTargetContext->wrapsVkSecondaryCB();
|
||||||
canArgs.validate();
|
canArgs.validate();
|
||||||
|
|
||||||
canArgs.fHasUserStencilSettings = !args.fUserStencilSettings->isUnused();
|
canArgs.fHasUserStencilSettings = !args.fUserStencilSettings->isUnused();
|
||||||
|
@ -80,8 +80,9 @@ public:
|
|||||||
const SkMatrix* fViewMatrix;
|
const SkMatrix* fViewMatrix;
|
||||||
const GrShape* fShape;
|
const GrShape* fShape;
|
||||||
GrAAType fAAType;
|
GrAAType fAAType;
|
||||||
|
bool fTargetIsWrappedVkSecondaryCB;
|
||||||
|
|
||||||
// These next two are only used by GrStencilAndCoverPathRenderer
|
// This is only used by GrStencilAndCoverPathRenderer
|
||||||
bool fHasUserStencilSettings;
|
bool fHasUserStencilSettings;
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
|
@ -855,6 +855,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context,
|
|||||||
canDrawArgs.fShape = &shape;
|
canDrawArgs.fShape = &shape;
|
||||||
canDrawArgs.fAAType = aaType;
|
canDrawArgs.fAAType = aaType;
|
||||||
canDrawArgs.fHasUserStencilSettings = false;
|
canDrawArgs.fHasUserStencilSettings = false;
|
||||||
|
canDrawArgs.fTargetIsWrappedVkSecondaryCB = renderTargetContext->wrapsVkSecondaryCB();
|
||||||
|
|
||||||
GrDrawingManager* dm = context->contextPriv().drawingManager();
|
GrDrawingManager* dm = context->contextPriv().drawingManager();
|
||||||
pr = dm->getPathRenderer(canDrawArgs, false, GrPathRendererChain::DrawType::kStencil,
|
pr = dm->getPathRenderer(canDrawArgs, false, GrPathRendererChain::DrawType::kStencil,
|
||||||
|
@ -241,6 +241,13 @@ void GrRenderTargetContext::drawGlyphRunList(
|
|||||||
SkDEBUGCODE(this->validate();)
|
SkDEBUGCODE(this->validate();)
|
||||||
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
|
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
|
||||||
|
|
||||||
|
// Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan
|
||||||
|
// secondary command buffers because it would require stopping and starting a render pass which
|
||||||
|
// we don't have access to.
|
||||||
|
if (this->wrapsVkSecondaryCB()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
|
GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
|
||||||
atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
|
atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
|
||||||
fSurfaceProps, blob);
|
fSurfaceProps, blob);
|
||||||
@ -1577,6 +1584,8 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
|
|||||||
canDrawArgs.fShape = &shape;
|
canDrawArgs.fShape = &shape;
|
||||||
canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
|
canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
|
||||||
canDrawArgs.fAAType = aaType;
|
canDrawArgs.fAAType = aaType;
|
||||||
|
SkASSERT(!fRenderTargetContext->wrapsVkSecondaryCB());
|
||||||
|
canDrawArgs.fTargetIsWrappedVkSecondaryCB = false;
|
||||||
canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
|
canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
|
||||||
|
|
||||||
// Don't allow the SW renderer
|
// Don't allow the SW renderer
|
||||||
@ -1644,6 +1653,7 @@ void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
|
|||||||
canDrawArgs.fViewMatrix = &viewMatrix;
|
canDrawArgs.fViewMatrix = &viewMatrix;
|
||||||
canDrawArgs.fShape = &originalShape;
|
canDrawArgs.fShape = &originalShape;
|
||||||
canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
|
canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
|
||||||
|
canDrawArgs.fTargetIsWrappedVkSecondaryCB = this->wrapsVkSecondaryCB();
|
||||||
canDrawArgs.fHasUserStencilSettings = false;
|
canDrawArgs.fHasUserStencilSettings = false;
|
||||||
|
|
||||||
GrPathRenderer* pr;
|
GrPathRenderer* pr;
|
||||||
@ -1777,6 +1787,13 @@ void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDraw
|
|||||||
bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
|
bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
|
||||||
const GrOp& op,
|
const GrOp& op,
|
||||||
GrXferProcessor::DstProxy* dstProxy) {
|
GrXferProcessor::DstProxy* dstProxy) {
|
||||||
|
// If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
|
||||||
|
// don't actually have a VkImage to make a copy of. Additionally we don't have the power to
|
||||||
|
// start and stop the render pass in order to make the copy.
|
||||||
|
if (rtProxy->wrapsVkSecondaryCB()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->caps()->textureBarrierSupport()) {
|
if (this->caps()->textureBarrierSupport()) {
|
||||||
if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
|
if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
|
||||||
// The render target is a texture, so we can read from it directly in the shader. The XP
|
// The render target is a texture, so we can read from it directly in the shader. The XP
|
||||||
|
@ -1230,6 +1230,14 @@ sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkImage* image) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
|
sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
|
||||||
|
// If we are wrapping a vulkan secondary command buffer, then we can't snap off a special image
|
||||||
|
// since it would require us to make a copy of the underlying VkImage which we don't have access
|
||||||
|
// to. Additionaly we can't stop and start the render pass that is used with the secondary
|
||||||
|
// command buffer.
|
||||||
|
if (this->accessRenderTargetContext()->wrapsVkSecondaryCB()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
sk_sp<GrTextureProxy> proxy(this->accessRenderTargetContext()->asTextureProxyRef());
|
sk_sp<GrTextureProxy> proxy(this->accessRenderTargetContext()->asTextureProxyRef());
|
||||||
if (!proxy) {
|
if (!proxy) {
|
||||||
// When the device doesn't have a texture, we create a temporary texture.
|
// When the device doesn't have a texture, we create a temporary texture.
|
||||||
@ -1258,14 +1266,18 @@ sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
|
|||||||
|
|
||||||
sk_sp<SkSpecialImage> SkGpuDevice::snapBackImage(const SkIRect& subset) {
|
sk_sp<SkSpecialImage> SkGpuDevice::snapBackImage(const SkIRect& subset) {
|
||||||
GrRenderTargetContext* rtc = this->accessRenderTargetContext();
|
GrRenderTargetContext* rtc = this->accessRenderTargetContext();
|
||||||
if (!rtc) {
|
|
||||||
|
// If we are wrapping a vulkan secondary command buffer, then we can't snap off a special image
|
||||||
|
// since it would require us to make a copy of the underlying VkImage which we don't have access
|
||||||
|
// to. Additionaly we can't stop and start the render pass that is used with the secondary
|
||||||
|
// command buffer.
|
||||||
|
if (rtc->wrapsVkSecondaryCB()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GrContext* ctx = this->context();
|
GrContext* ctx = this->context();
|
||||||
if (!rtc->asSurfaceProxy()) {
|
SkASSERT(rtc->asSurfaceProxy());
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto srcProxy =
|
auto srcProxy =
|
||||||
GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), subset,
|
GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), subset,
|
||||||
|
@ -641,7 +641,8 @@ GrPathRenderer::CanDrawPath
|
|||||||
GrDefaultPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
|
GrDefaultPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
|
||||||
bool isHairline = IsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr);
|
bool isHairline = IsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr);
|
||||||
// If we aren't a single_pass_shape or hairline, we require stencil buffers.
|
// If we aren't a single_pass_shape or hairline, we require stencil buffers.
|
||||||
if (!(single_pass_shape(*args.fShape) || isHairline) && args.fCaps->avoidStencilBuffers()) {
|
if (!(single_pass_shape(*args.fShape) || isHairline) &&
|
||||||
|
(args.fCaps->avoidStencilBuffers() || args.fTargetIsWrappedVkSecondaryCB)) {
|
||||||
return CanDrawPath::kNo;
|
return CanDrawPath::kNo;
|
||||||
}
|
}
|
||||||
// This can draw any path with any simple fill style but doesn't do coverage-based antialiasing.
|
// This can draw any path with any simple fill style but doesn't do coverage-based antialiasing.
|
||||||
|
@ -35,6 +35,7 @@ GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrResourceProvider*
|
|||||||
|
|
||||||
GrPathRenderer::CanDrawPath
|
GrPathRenderer::CanDrawPath
|
||||||
GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
|
GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
|
||||||
|
SkASSERT(!args.fTargetIsWrappedVkSecondaryCB);
|
||||||
// GrPath doesn't support hairline paths. An arbitrary path effect could produce a hairline
|
// GrPath doesn't support hairline paths. An arbitrary path effect could produce a hairline
|
||||||
// path.
|
// path.
|
||||||
if (args.fShape->style().strokeRec().isHairlineStyle() ||
|
if (args.fShape->style().strokeRec().isHairlineStyle() ||
|
||||||
|
@ -176,9 +176,21 @@ bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy*
|
|||||||
int dstSampleCnt = 0;
|
int dstSampleCnt = 0;
|
||||||
int srcSampleCnt = 0;
|
int srcSampleCnt = 0;
|
||||||
if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
|
if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
|
||||||
|
// Copying to or from render targets that wrap a secondary command buffer is not allowed
|
||||||
|
// since they would require us to know the VkImage, which we don't have, as well as need us
|
||||||
|
// to stop and start the VkRenderPass which we don't have access to.
|
||||||
|
if (rtProxy->wrapsVkSecondaryCB()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
dstSampleCnt = rtProxy->numColorSamples();
|
dstSampleCnt = rtProxy->numColorSamples();
|
||||||
}
|
}
|
||||||
if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
|
if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
|
||||||
|
// Copying to or from render targets that wrap a secondary command buffer is not allowed
|
||||||
|
// since they would require us to know the VkImage, which we don't have, as well as need us
|
||||||
|
// to stop and start the VkRenderPass which we don't have access to.
|
||||||
|
if (rtProxy->wrapsVkSecondaryCB()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
srcSampleCnt = rtProxy->numColorSamples();
|
srcSampleCnt = rtProxy->numColorSamples();
|
||||||
}
|
}
|
||||||
SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
|
SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
|
||||||
|
@ -1773,6 +1773,15 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
|||||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||||
const SkIRect& srcRect, const SkIPoint& dstPoint,
|
const SkIRect& srcRect, const SkIPoint& dstPoint,
|
||||||
bool canDiscardOutsideDstRect) {
|
bool canDiscardOutsideDstRect) {
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
if (GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget())) {
|
||||||
|
SkASSERT(!srcRT->wrapsSecondaryCommandBuffer());
|
||||||
|
}
|
||||||
|
if (GrVkRenderTarget* dstRT = static_cast<GrVkRenderTarget*>(dst->asRenderTarget())) {
|
||||||
|
SkASSERT(!dstRT->wrapsSecondaryCommandBuffer());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GrPixelConfig dstConfig = dst->config();
|
GrPixelConfig dstConfig = dst->config();
|
||||||
GrPixelConfig srcConfig = src->config();
|
GrPixelConfig srcConfig = src->config();
|
||||||
|
|
||||||
@ -1799,6 +1808,9 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
|||||||
GrRenderTarget* dstRT = dst->asRenderTarget();
|
GrRenderTarget* dstRT = dst->asRenderTarget();
|
||||||
if (dstRT) {
|
if (dstRT) {
|
||||||
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
|
GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
|
||||||
|
if (vkRT->wrapsSecondaryCommandBuffer()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
dstImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
|
dstImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
|
||||||
} else {
|
} else {
|
||||||
SkASSERT(dst->asTexture());
|
SkASSERT(dst->asTexture());
|
||||||
@ -1839,6 +1851,12 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
|
|||||||
GrVkImage* image = nullptr;
|
GrVkImage* image = nullptr;
|
||||||
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
|
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
|
||||||
if (rt) {
|
if (rt) {
|
||||||
|
// Reading from render targets that wrap a secondary command buffer is not allowed since
|
||||||
|
// it would require us to know the VkImage, which we don't have, as well as need us to
|
||||||
|
// stop and start the VkRenderPass which we don't have access to.
|
||||||
|
if (rt->wrapsSecondaryCommandBuffer()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// resolve the render target if necessary
|
// resolve the render target if necessary
|
||||||
switch (rt->getResolveType()) {
|
switch (rt->getResolveType()) {
|
||||||
case GrVkRenderTarget::kCantResolve_ResolveType:
|
case GrVkRenderTarget::kCantResolve_ResolveType:
|
||||||
@ -2039,6 +2057,7 @@ void GrVkGpu::submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBu
|
|||||||
const VkClearValue* colorClear,
|
const VkClearValue* colorClear,
|
||||||
GrVkRenderTarget* target, GrSurfaceOrigin origin,
|
GrVkRenderTarget* target, GrSurfaceOrigin origin,
|
||||||
const SkIRect& bounds) {
|
const SkIRect& bounds) {
|
||||||
|
SkASSERT (!target->wrapsSecondaryCommandBuffer());
|
||||||
const SkIRect* pBounds = &bounds;
|
const SkIRect* pBounds = &bounds;
|
||||||
SkIRect flippedBounds;
|
SkIRect flippedBounds;
|
||||||
if (kBottomLeft_GrSurfaceOrigin == origin) {
|
if (kBottomLeft_GrSurfaceOrigin == origin) {
|
||||||
|
Loading…
Reference in New Issue
Block a user