Add program pre-compilation to Vulkan backend

This CL fills out the GrVkGpu::compile method and updates GrVkCaps::makeDesc to both reconstruct the GrVkRenderPass AttachmentsDescriptor and AttachmentFlags from the GrProgramDesc.

In the 'compile' case, the renderPass info is used to get a renderpass and then a pipeline state.

In the 'makeDesc' case, the renderPass info is used to create the ProgramDesc.

Bug: skia:9455
Change-Id: I3810651232c95c3d837d96655853ea54056c70cb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/288462
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2020-06-26 08:30:07 -04:00 committed by Skia Commit-Bot
parent f63713518c
commit 24e2f6e25e
8 changed files with 126 additions and 26 deletions

View File

@ -71,11 +71,10 @@ private:
const GrCaps* caps = this->caps();
if (this->backend() == GrBackendApi::kVulkan ||
this->backend() == GrBackendApi::kMetal ||
if (this->backend() == GrBackendApi::kMetal ||
this->backend() == GrBackendApi::kDirect3D ||
this->backend() == GrBackendApi::kDawn) {
// Currently Vulkan, Metal, Direct3D, and Dawn require a live renderTarget to
// Currently Metal, Direct3D, and Dawn require a live renderTarget to
// compute the key
return;
}

View File

@ -975,8 +975,7 @@ int GrRenderTargetContextPriv::maxWindowRectangles() const {
*fRenderTargetContext->caps());
}
GrOpsTask::CanDiscardPreviousOps GrRenderTargetContext::canDiscardPreviousOpsOnFullClear(
) const {
GrOpsTask::CanDiscardPreviousOps GrRenderTargetContext::canDiscardPreviousOpsOnFullClear() const {
#if GR_TEST_UTILS
if (fPreserveOpsOnFullClear_TestingOnly) {
return GrOpsTask::CanDiscardPreviousOps::kNo;

View File

@ -1701,13 +1701,39 @@ GrProgramDesc GrVkCaps::makeDesc(const GrRenderTarget* rt, const GrProgramInfo&
// GrVkPipelineStateBuilder.cpp).
b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
if (rt) {
GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
bool needsStencil = programInfo.numStencilSamples() || programInfo.isStencilEnabled();
// TODO: support failure in getSimpleRenderPass
const GrVkRenderPass* rp = vkRT->getSimpleRenderPass(needsStencil);
SkASSERT(rp);
rp->genKey(&b);
bool needsStencil = programInfo.numStencilSamples() || programInfo.isStencilEnabled();
// TODO: support failure in getSimpleRenderPass
const GrVkRenderPass* rp = vkRT->getSimpleRenderPass(needsStencil);
SkASSERT(rp);
rp->genKey(&b);
#ifdef SK_DEBUG
if (!rp->isExternal()) {
// This is to ensure ReconstructAttachmentsDescriptor keeps matching
// getSimpleRenderPass' result
GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
GrVkRenderPass::AttachmentFlags attachmentFlags;
GrVkRenderTarget::ReconstructAttachmentsDescriptor(*this, programInfo,
&attachmentsDescriptor,
&attachmentFlags);
SkASSERT(rp->isCompatible(attachmentsDescriptor, attachmentFlags));
}
#endif
} else {
GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
GrVkRenderPass::AttachmentFlags attachmentFlags;
GrVkRenderTarget::ReconstructAttachmentsDescriptor(*this, programInfo,
&attachmentsDescriptor,
&attachmentFlags);
// kExternal_AttachmentFlag is only set for wrapped secondary command buffers - which
// will always go through the above 'rt' path (i.e., we can always pass 0 as the final
// parameter to GenKey).
GrVkRenderPass::GenKey(&b, attachmentFlags, attachmentsDescriptor, 0);
}
GrStencilSettings stencil = programInfo.nonGLStencilSettings();
stencil.genKey(&b, true);

View File

@ -1896,8 +1896,33 @@ void GrVkGpu::deleteBackendTexture(const GrBackendTexture& tex) {
}
}
bool GrVkGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
return false;
bool GrVkGpu::compile(const GrProgramDesc& desc, const GrProgramInfo& programInfo) {
SkASSERT(!(GrProcessor::CustomFeatures::kSampleLocations & programInfo.requestedFeatures()));
GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
GrVkRenderPass::AttachmentFlags attachmentFlags;
GrVkRenderTarget::ReconstructAttachmentsDescriptor(this->vkCaps(), programInfo,
&attachmentsDescriptor, &attachmentFlags);
sk_sp<const GrVkRenderPass> renderPass(this->resourceProvider().findCompatibleRenderPass(
&attachmentsDescriptor,
attachmentFlags));
if (!renderPass) {
return false;
}
Stats::ProgramCacheResult stat;
auto pipelineState = this->resourceProvider().findOrCreateCompatiblePipelineState(
desc,
programInfo,
renderPass->vkRenderPass(),
&stat);
if (!pipelineState) {
return false;
}
return stat != Stats::ProgramCacheResult::kHit;
}
#if GR_TEST_UTILS

View File

@ -266,19 +266,25 @@ bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps,
}
void GrVkRenderPass::genKey(GrProcessorKeyBuilder* b) const {
b->add32(fAttachmentFlags);
if (fAttachmentFlags & kColor_AttachmentFlag) {
b->add32(fAttachmentsDescriptor.fColor.fFormat);
b->add32(fAttachmentsDescriptor.fColor.fSamples);
GenKey(b, fAttachmentFlags, fAttachmentsDescriptor, (uint64_t)fRenderPass);
}
void GrVkRenderPass::GenKey(GrProcessorKeyBuilder* b,
AttachmentFlags attachmentFlags,
const AttachmentsDescriptor& attachmentsDescriptor,
uint64_t externalRenderPass) {
b->add32(attachmentFlags);
if (attachmentFlags & kColor_AttachmentFlag) {
b->add32(attachmentsDescriptor.fColor.fFormat);
b->add32(attachmentsDescriptor.fColor.fSamples);
}
if (fAttachmentFlags & kStencil_AttachmentFlag) {
b->add32(fAttachmentsDescriptor.fStencil.fFormat);
b->add32(fAttachmentsDescriptor.fStencil.fSamples);
if (attachmentFlags & kStencil_AttachmentFlag) {
b->add32(attachmentsDescriptor.fStencil.fFormat);
b->add32(attachmentsDescriptor.fStencil.fSamples);
}
if (fAttachmentFlags & kExternal_AttachmentFlag) {
SkASSERT(!(fAttachmentFlags & ~kExternal_AttachmentFlag));
uint64_t handle = (uint64_t)fRenderPass;
b->add32((uint32_t)(handle & 0xFFFFFFFF));
b->add32((uint32_t)(handle>>32));
if (attachmentFlags & kExternal_AttachmentFlag) {
SkASSERT(!(attachmentFlags & ~kExternal_AttachmentFlag));
b->add32((uint32_t)(externalRenderPass & 0xFFFFFFFF));
b->add32((uint32_t)(externalRenderPass>>32));
}
}

View File

@ -108,6 +108,8 @@ public:
bool isCompatibleExternalRP(VkRenderPass) const;
SkDEBUGCODE(bool isExternal() const { return fAttachmentFlags & kExternal_AttachmentFlag; })
bool equalLoadStoreOps(const LoadStoreOps& colorOps,
const LoadStoreOps& stencilOps) const;
@ -120,7 +122,12 @@ public:
uint32_t clearValueCount() const { return fClearValueCount; }
void genKey(GrProcessorKeyBuilder* b) const;
void genKey(GrProcessorKeyBuilder*) const;
static void GenKey(GrProcessorKeyBuilder*,
AttachmentFlags,
const AttachmentsDescriptor&,
uint64_t externalRenderPass);
#ifdef SK_TRACE_MANAGED_RESOURCES
void dumpInfo() const override {

View File

@ -343,6 +343,36 @@ void GrVkRenderTarget::getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescr
desc->fAttachmentCount = attachmentCount;
}
void GrVkRenderTarget::ReconstructAttachmentsDescriptor(const GrVkCaps& vkCaps,
const GrProgramInfo& programInfo,
GrVkRenderPass::AttachmentsDescriptor* desc,
GrVkRenderPass::AttachmentFlags* flags) {
VkFormat format;
SkAssertResult(programInfo.backendFormat().asVkFormat(&format));
desc->fColor.fFormat = format;
desc->fColor.fSamples = programInfo.numSamples();
*flags = GrVkRenderPass::kColor_AttachmentFlag;
uint32_t attachmentCount = 1;
SkASSERT(!programInfo.isStencilEnabled() || programInfo.numStencilSamples());
if (programInfo.numStencilSamples()) {
const GrVkCaps::StencilFormat& stencilFormat = vkCaps.preferredStencilFormat();
desc->fStencil.fFormat = stencilFormat.fInternalFormat;
desc->fStencil.fSamples = programInfo.numStencilSamples();
#ifdef SK_DEBUG
if (vkCaps.mixedSamplesSupport()) {
SkASSERT(desc->fStencil.fSamples >= desc->fColor.fSamples);
} else {
SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
}
#endif
*flags |= GrVkRenderPass::kStencil_AttachmentFlag;
++attachmentCount;
}
desc->fAttachmentCount = attachmentCount;
}
GrVkRenderTarget::~GrVkRenderTarget() {
// either release or abandon should have been called by the owner of this object.
SkASSERT(!fMSAAImage);

View File

@ -100,6 +100,14 @@ public:
GrVkRenderPass::AttachmentFlags* flags,
bool withStencil) const;
// Reconstruct the render target attachment information from the programInfo. This includes
// which attachments the render target will have (color, stencil) and the attachments' formats
// and sample counts - cf. getAttachmentsDescriptor.
static void ReconstructAttachmentsDescriptor(const GrVkCaps& vkCaps,
const GrProgramInfo& programInfo,
GrVkRenderPass::AttachmentsDescriptor* desc,
GrVkRenderPass::AttachmentFlags* flags);
void addResources(GrVkCommandBuffer& commandBuffer, bool withStencil);
void addWrappedGrSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> cmdBuffer) {