Changing dst sample type to flags.

Instead of having an enum that says how to sample the dst in the shader
(or lack of dst sampling), we now rely on whether or not we have a valid
proxy in the GrDstProxyView to know whether we are sampling the dst at
all. Then if so we additionally have GrDstSampleFlags to say whether we
need to use a texture barrier and whether we are sampling from an input
attachment.

Change-Id: Id0390a8ad57ec52674922807f6c050d59b7e75a2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/416416
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2021-06-07 15:18:23 -04:00 committed by Skia Commit-Bot
parent 5b5a4c6bf5
commit 87fab9f72a
18 changed files with 53 additions and 99 deletions

View File

@ -1307,39 +1307,12 @@ private:
Context fReleaseCtx;
};
enum class GrDstSampleType {
kNone, // The dst value will not be sampled in the shader
kAsTextureCopy, // The dst value will be sampled from a copy of the dst
// The types below require a texture barrier
kAsSelfTexture, // The dst value is sampled directly from the dst itself as a texture.
kAsInputAttachment, // The dst value is sampled directly from the dst as an input attachment.
enum class GrDstSampleFlags {
kNone = 0,
kRequiresTextureBarrier = 1 << 0,
kAsInputAttachment = 1 << 1,
};
// Returns true if the sampling of the dst color in the shader is done by reading the dst directly.
// Anything that directly reads the dst will need a barrier between draws.
static constexpr bool GrDstSampleTypeDirectlySamplesDst(GrDstSampleType type) {
switch (type) {
case GrDstSampleType::kAsSelfTexture: // fall through
case GrDstSampleType::kAsInputAttachment:
return true;
case GrDstSampleType::kNone: // fall through
case GrDstSampleType::kAsTextureCopy:
return false;
}
SkUNREACHABLE;
}
static constexpr bool GrDstSampleTypeUsesTexture(GrDstSampleType type) {
switch (type) {
case GrDstSampleType::kAsSelfTexture: // fall through
case GrDstSampleType::kAsTextureCopy:
return true;
case GrDstSampleType::kNone: // fall through
case GrDstSampleType::kAsInputAttachment:
return false;
}
SkUNREACHABLE;
}
GR_MAKE_BITFIELD_CLASS_OPS(GrDstSampleFlags)
#if defined(SK_DEBUG) || GR_TEST_UTILS || defined(SK_ENABLE_DUMP_GPU)
static constexpr const char* GrBackendApiToStr(GrBackendApi api) {

View File

@ -437,12 +437,12 @@ bool GrCaps::isFormatCompressed(const GrBackendFormat& format) const {
return GrBackendFormatToCompressionType(format) != SkImage::CompressionType::kNone;
}
GrDstSampleType GrCaps::getDstSampleTypeForProxy(const GrRenderTargetProxy* rt) const {
GrDstSampleFlags GrCaps::getDstSampleFlagsForProxy(const GrRenderTargetProxy* rt) const {
SkASSERT(rt);
if (this->textureBarrierSupport() && !rt->requiresManualMSAAResolve()) {
return this->onGetDstSampleTypeForProxy(rt);
return this->onGetDstSampleFlagsForProxy(rt);
}
return GrDstSampleType::kAsTextureCopy;
return GrDstSampleFlags::kNone;
}
bool GrCaps::supportsDynamicMSAA(const GrRenderTargetProxy* rtProxy) const {

View File

@ -397,7 +397,7 @@ public:
bool disableTessellationPathRenderer() const { return fDisableTessellationPathRenderer; }
// Returns how to sample the dst values for the passed in GrRenderTargetProxy.
GrDstSampleType getDstSampleTypeForProxy(const GrRenderTargetProxy*) const;
GrDstSampleFlags getDstSampleFlagsForProxy(const GrRenderTargetProxy*) const;
/**
* This is used to try to ensure a successful copy a dst in order to perform shader-based
@ -613,8 +613,8 @@ private:
virtual GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const = 0;
virtual GrDstSampleType onGetDstSampleTypeForProxy(const GrRenderTargetProxy*) const {
return GrDstSampleType::kAsTextureCopy;
virtual GrDstSampleFlags onGetDstSampleFlagsForProxy(const GrRenderTargetProxy*) const {
return GrDstSampleFlags::kNone;
}
bool fSuppressPrints : 1;

View File

@ -28,14 +28,14 @@ public:
GrDstProxyView& operator=(const GrDstProxyView& other) {
fProxyView = other.fProxyView;
fOffset = other.fOffset;
fDstSampleType = other.fDstSampleType;
fDstSampleFlags = other.fDstSampleFlags;
return *this;
}
bool operator==(const GrDstProxyView& that) const {
return fProxyView == that.fProxyView &&
fOffset == that.fOffset &&
fDstSampleType == that.fDstSampleType;
fDstSampleFlags == that.fDstSampleFlags;
}
bool operator!=(const GrDstProxyView& that) const { return !(*this == that); }
@ -54,14 +54,14 @@ public:
}
}
GrDstSampleType dstSampleType() const { return fDstSampleType; }
GrDstSampleFlags dstSampleFlags() const { return fDstSampleFlags; }
void setDstSampleType(GrDstSampleType dstSampleType) { fDstSampleType = dstSampleType; }
void setDstSampleFlags(GrDstSampleFlags dstSampleFlags) { fDstSampleFlags = dstSampleFlags; }
private:
GrSurfaceProxyView fProxyView;
SkIPoint fOffset = {0, 0};
GrDstSampleType fDstSampleType = GrDstSampleType::kNone;
GrDstSampleFlags fDstSampleFlags = GrDstSampleFlags::kNone;
};
#endif

View File

@ -397,17 +397,14 @@ void GrOpsTask::addDrawOp(GrDrawingManager* drawingMgr, GrOp::Owner op, bool use
op->visitProxies(addDependency);
clip.visitProxies(addDependency);
if (dstProxyView.proxy()) {
if (GrDstSampleTypeUsesTexture(dstProxyView.dstSampleType())) {
if (!(dstProxyView.dstSampleFlags() & GrDstSampleFlags::kAsInputAttachment)) {
this->addSampledTexture(dstProxyView.proxy());
}
addDependency(dstProxyView.proxy(), GrMipmapped::kNo);
if (this->target(0) == dstProxyView.proxy()) {
// Since we are sampling and drawing to the same surface we will need to use
// texture barriers.
SkASSERT(GrDstSampleTypeDirectlySamplesDst(dstProxyView.dstSampleType()));
if (dstProxyView.dstSampleFlags() & GrDstSampleFlags::kRequiresTextureBarrier) {
fRenderPassXferBarriers |= GrXferBarrierFlags::kTexture;
}
SkASSERT(dstProxyView.dstSampleType() != GrDstSampleType::kAsInputAttachment ||
addDependency(dstProxyView.proxy(), GrMipmapped::kNo);
SkASSERT(!(dstProxyView.dstSampleFlags() & GrDstSampleFlags::kAsInputAttachment) ||
dstProxyView.offset().isZero());
}

View File

@ -20,7 +20,10 @@
GrPipeline::GrPipeline(const InitArgs& args,
sk_sp<const GrXferProcessor> xferProcessor,
const GrAppliedHardClip& hardClip)
: fWriteSwizzle(args.fWriteSwizzle) {
: fDstProxy(args.fDstProxyView)
, fWindowRectsState(hardClip.windowRectsState())
, fXferProcessor(std::move(xferProcessor))
, fWriteSwizzle(args.fWriteSwizzle) {
fFlags = (Flags)args.fInputFlags;
if (hardClip.hasStencilClip()) {
fFlags |= Flags::kHasStencilClip;
@ -28,14 +31,8 @@ GrPipeline::GrPipeline(const InitArgs& args,
if (hardClip.scissorState().enabled()) {
fFlags |= Flags::kScissorTestEnabled;
}
fWindowRectsState = hardClip.windowRectsState();
fXferProcessor = std::move(xferProcessor);
SkASSERT((args.fDstProxyView.dstSampleType() != GrDstSampleType::kNone) ==
SkToBool(args.fDstProxyView.proxy()));
fDstProxy = args.fDstProxyView;
// If we have any special dst sample flags we better also have a dst proxy
SkASSERT(this->dstSampleFlags() == GrDstSampleFlags::kNone || this->dstProxyView());
}
GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
@ -62,7 +59,7 @@ GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
}
GrXferBarrierType GrPipeline::xferBarrierType(const GrCaps& caps) const {
if (this->dstProxyView().proxy() && GrDstSampleTypeDirectlySamplesDst(this->dstSampleType())) {
if (this->dstSampleFlags() & GrDstSampleFlags::kRequiresTextureBarrier) {
return kTexture_GrXferBarrierType;
}
return this->getXferProcessor().xferBarrierType(caps);
@ -101,7 +98,7 @@ void GrPipeline::genKey(GrProcessorKeyBuilder* b, const GrCaps& caps) const {
b->addBits(kBlendCoeffSize, blendInfo.fSrcBlend, "srcBlend");
b->addBits(kBlendCoeffSize, blendInfo.fDstBlend, "dstBlend");
b->addBits(kBlendEquationSize, blendInfo.fEquation, "equation");
b->addBool(this->usesInputAttachment(), "inputAttach");
b->addBool(this->usesDstInputAttachment(), "inputAttach");
}
void GrPipeline::visitTextureEffects(

View File

@ -124,11 +124,9 @@ public:
// Helper functions to quickly know if this GrPipeline will access the dst as a texture or an
// input attachment.
bool usesDstTexture() const {
return GrDstSampleTypeUsesTexture(this->dstSampleType());
}
bool usesInputAttachment() const {
return this->dstSampleType() == GrDstSampleType::kAsInputAttachment;
bool usesDstTexture() const { return this->dstProxyView() && !this->usesDstInputAttachment(); }
bool usesDstInputAttachment() const {
return this->dstSampleFlags()& GrDstSampleFlags::kAsInputAttachment;
}
/**
@ -140,7 +138,7 @@ public:
SkIPoint dstTextureOffset() const { return fDstProxy.offset(); }
GrDstSampleType dstSampleType() const { return fDstProxy.dstSampleType(); }
GrDstSampleFlags dstSampleFlags() const { return fDstProxy.dstSampleFlags(); }
/** If this GrXferProcessor uses a texture to access the dst color, returns that texture. */
GrTexture* peekDstTexture() const {

View File

@ -104,7 +104,9 @@ static void gen_xp_key(const GrXferProcessor& xp,
origin = pipeline.dstProxyView().origin();
originIfDstTexture = &origin;
}
xp.getGLSLProcessorKey(*caps.shaderCaps(), b, originIfDstTexture, pipeline.dstSampleType());
xp.getGLSLProcessorKey(*caps.shaderCaps(), b, originIfDstTexture,
pipeline.dstSampleFlags() & GrDstSampleFlags::kAsInputAttachment);
}
static void gen_fp_key(const GrFragmentProcessor& fp,

View File

@ -1950,21 +1950,16 @@ bool GrSurfaceDrawContext::setupDstProxyView(const GrOp& op, GrDstProxyView* dst
return false;
}
if (fDstSampleType == GrDstSampleType::kNone) {
fDstSampleType = this->caps()->getDstSampleTypeForProxy(this->asRenderTargetProxy());
}
SkASSERT(fDstSampleType != GrDstSampleType::kNone);
auto dstSampleFlags = this->caps()->getDstSampleFlagsForProxy(this->asRenderTargetProxy());
if (GrDstSampleTypeDirectlySamplesDst(fDstSampleType)) {
// The render target is a texture or input attachment, so we can read from it directly in
// the shader. The XP will be responsible to detect this situation and request a texture
// barrier.
if (dstSampleFlags & GrDstSampleFlags::kRequiresTextureBarrier) {
// If we require a barrier to sample the dst it means we are sampling the RT itself either
// as a texture or input attachment.
dstProxyView->setProxyView(this->readSurfaceView());
dstProxyView->setOffset(0, 0);
dstProxyView->setDstSampleType(fDstSampleType);
dstProxyView->setDstSampleFlags(dstSampleFlags);
return true;
}
SkASSERT(fDstSampleType == GrDstSampleType::kAsTextureCopy);
GrColorType colorType = this->colorInfo().colorType();
// MSAA consideration: When there is support for reading MSAA samples in the shader we could
@ -2003,6 +1998,6 @@ bool GrSurfaceDrawContext::setupDstProxyView(const GrOp& op, GrDstProxyView* dst
dstProxyView->setProxyView({std::move(copy), this->origin(), this->readSwizzle()});
dstProxyView->setOffset(dstOffset);
dstProxyView->setDstSampleType(fDstSampleType);
dstProxyView->setDstSampleFlags(dstSampleFlags);
return true;
}

View File

@ -721,8 +721,6 @@ private:
bool fNeedsStencil = false;
GrDstSampleType fDstSampleType = GrDstSampleType::kNone;
#if GR_TEST_UTILS
bool fPreserveOpsOnFullClear_TestingOnly = false;
#endif

View File

@ -30,7 +30,7 @@ bool GrXferProcessor::hasSecondaryOutput() const {
void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b,
const GrSurfaceOrigin* originIfDstTexture,
GrDstSampleType dstSampleType) const {
bool usesInputAttachmentForDstRead) const {
uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
if (key) {
if (originIfDstTexture) {
@ -38,9 +38,7 @@ void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorK
if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) {
key |= 0x4;
}
// We don't just add the whole dstSampleType to the key because sampling a copy or the
// rt directly produces the same shader code.
if (dstSampleType == GrDstSampleType::kAsInputAttachment) {
if (usesInputAttachmentForDstRead) {
key |= 0x8;
}
}

View File

@ -65,7 +65,7 @@ public:
void getGLSLProcessorKey(const GrShaderCaps&,
GrProcessorKeyBuilder*,
const GrSurfaceOrigin* originIfDstTexture,
GrDstSampleType dstSampleType) const;
bool usesInputAttachmentForDstRead) const;
/** Returns a new instance of the appropriate *GL* implementation class
for the given GrXferProcessor; caller is responsible for deleting

View File

@ -4543,11 +4543,11 @@ GrSwizzle GrGLCaps::getWriteSwizzle(const GrBackendFormat& format, GrColorType c
return {};
}
GrDstSampleType GrGLCaps::onGetDstSampleTypeForProxy(const GrRenderTargetProxy* rt) const {
GrDstSampleFlags GrGLCaps::onGetDstSampleFlagsForProxy(const GrRenderTargetProxy* rt) const {
if (rt->asTextureProxy()) {
return GrDstSampleType::kAsSelfTexture;
return GrDstSampleFlags::kRequiresTextureBarrier;
}
return GrDstSampleType::kAsTextureCopy;
return GrDstSampleFlags::kNone;
}
uint64_t GrGLCaps::computeFormatKey(const GrBackendFormat& format) const {

View File

@ -503,7 +503,7 @@ private:
GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
GrDstSampleType onGetDstSampleTypeForProxy(const GrRenderTargetProxy*) const override;
GrDstSampleFlags onGetDstSampleFlagsForProxy(const GrRenderTargetProxy*) const override;
bool onSupportsDynamicMSAA(const GrRenderTargetProxy*) const override {
switch (fMSFBOType) {

View File

@ -248,7 +248,7 @@ bool GrGLSLProgramBuilder::emitAndInstallDstTexture() {
fFS.codeAppendf("%s = ", dstColor);
fFS.appendTextureLookup(fDstTextureSamplerHandle, "_dstTexCoord");
fFS.codeAppend(";\n");
} else if (this->pipeline().usesInputAttachment()) {
} else if (this->pipeline().usesDstInputAttachment()) {
// Set up an input attachment for the destination texture.
const GrSwizzle& swizzle = dstView.swizzle();
fDstTextureSamplerHandle = this->emitInputSampler(swizzle, "DstTextureInput");
@ -302,7 +302,6 @@ bool GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn,
coverageIn.size() ? coverageIn.c_str() : "float4(1)",
fFS.getPrimaryColorOutputName(),
fFS.getSecondaryColorOutputName(),
this->pipeline().dstSampleType(),
fDstTextureSamplerHandle,
fDstTextureOrigin,
this->pipeline().writeSwizzle());

View File

@ -34,7 +34,6 @@ public:
const char* inputCoverage,
const char* outputPrimary,
const char* outputSecondary,
GrDstSampleType dstSampleType,
const SamplerHandle dstTextureSamplerHandle,
GrSurfaceOrigin dstTextureOrigin,
const GrSwizzle& writeSwizzle)
@ -46,7 +45,6 @@ public:
, fInputCoverage(inputCoverage)
, fOutputPrimary(outputPrimary)
, fOutputSecondary(outputSecondary)
, fDstSampleType(dstSampleType)
, fDstTextureSamplerHandle(dstTextureSamplerHandle)
, fDstTextureOrigin(dstTextureOrigin)
, fWriteSwizzle(writeSwizzle) {}
@ -58,7 +56,6 @@ public:
const char* fInputCoverage;
const char* fOutputPrimary;
const char* fOutputSecondary;
GrDstSampleType fDstSampleType;
const SamplerHandle fDstTextureSamplerHandle;
GrSurfaceOrigin fDstTextureOrigin;
GrSwizzle fWriteSwizzle;

View File

@ -1690,15 +1690,15 @@ GrSwizzle GrVkCaps::getWriteSwizzle(const GrBackendFormat& format, GrColorType c
return {};
}
GrDstSampleType GrVkCaps::onGetDstSampleTypeForProxy(const GrRenderTargetProxy* rt) const {
GrDstSampleFlags GrVkCaps::onGetDstSampleFlagsForProxy(const GrRenderTargetProxy* rt) const {
bool isMSAAWithResolve = rt->numSamples() > 1 && rt->asTextureProxy();
// TODO: Currently if we have an msaa rt with a resolve, the supportsVkInputAttachment call
// references whether the resolve is supported as an input attachment. We need to add a check to
// allow checking the color attachment (msaa or not) supports input attachment specifically.
if (!isMSAAWithResolve && rt->supportsVkInputAttachment()) {
return GrDstSampleType::kAsInputAttachment;
return GrDstSampleFlags::kRequiresTextureBarrier | GrDstSampleFlags::kAsInputAttachment;
}
return GrDstSampleType::kAsTextureCopy;
return GrDstSampleFlags::kNone;
}
uint64_t GrVkCaps::computeFormatKey(const GrBackendFormat& format) const {

View File

@ -293,7 +293,7 @@ private:
GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
GrDstSampleType onGetDstSampleTypeForProxy(const GrRenderTargetProxy*) const override;
GrDstSampleFlags onGetDstSampleFlagsForProxy(const GrRenderTargetProxy*) const override;
// ColorTypeInfo for a specific format
struct ColorTypeInfo {