Reland "Reland "Implement sample mask and sample locations support in Vulkan""

This is a reland of 97e917a25f, this
time with MSAA CCPR disabled.

Original change's description:
> Reland "Implement sample mask and sample locations support in Vulkan"
>
> This is a reland of 8b915a0c27
>
> Original change's description:
> > Implement sample mask and sample locations support in Vulkan
> >
> > Change-Id: I372695ec5360def42a8a997675993264740b0da4
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252038
> > Commit-Queue: Chris Dalton <csmartdalton@google.com>
> > Reviewed-by: Chris Dalton <csmartdalton@google.com>
>
> TBR=ethannicholas@google.com
>
> Change-Id: I20de36719db52ad4dfc5290101d48a8fd9601c11
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252936
> Reviewed-by: Chris Dalton <csmartdalton@google.com>
> Commit-Queue: Chris Dalton <csmartdalton@google.com>

TBR=ethannicholas@google.com

Change-Id: Ie0861dc20df1fa622cb26ed78369d29976e3be10
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/254608
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2019-11-14 10:01:16 -07:00 committed by Skia Commit-Bot
parent 3876a9f267
commit 8a0f50944b
7 changed files with 85 additions and 41 deletions

View File

@ -294,7 +294,8 @@ void GrGLSLFragmentShaderBuilder::onFinalize() {
if (CustomFeatures::kSampleLocations & fProgramBuilder->processorFeatures()) {
const SkTArray<SkPoint>& sampleLocations = fProgramBuilder->getSampleLocations();
this->definitions().append("const float2 _sampleOffsets[] = float2[](");
this->definitions().appendf("const float2 _sampleOffsets[%i] = float2[%i](",
sampleLocations.count(), sampleLocations.count());
for (int i = 0; i < sampleLocations.count(); ++i) {
SkPoint offset = sampleLocations[i] - SkPoint::Make(.5f, .5f);
if (kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {

View File

@ -441,6 +441,10 @@ void GrVkCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDevicePropertie
// GrCaps workarounds
////////////////////////////////////////////////////////////////////////////
// Temporarily disable the MSAA implementation of CCPR while we work out a crash on Win10
// GTX660 and incorrect rendring on Adreno.
fDriverBlacklistMSAACCPR = true;
if (kARM_VkVendor == properties.vendorID) {
fInstanceAttribSupport = false;
fAvoidWritePixelsFastPath = true; // bugs.skia.org/8064
@ -473,6 +477,10 @@ void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
static const uint32_t kMaxVertexAttributes = 64;
fMaxVertexAttributes = SkTMin(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes);
if (properties.limits.standardSampleLocations) {
fSampleLocationsSupport = true;
}
if (extensions.hasExtension(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, 1)) {
// We "disable" multisample by colocating all samples at pixel center.
fMultisampleDisableSupport = true;
@ -548,7 +556,7 @@ void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties,
// to be true with Vulkan as well.
shaderCaps->fPreferFlatInterpolation = kQualcomm_VkVendor != properties.vendorID;
// GrShaderCaps
shaderCaps->fSampleMaskSupport = true;
shaderCaps->fShaderDerivativeSupport = true;

View File

@ -1833,6 +1833,59 @@ GrBackendTexture GrVkGpu::onCreateBackendTexture(SkISize dimensions,
return GrBackendTexture(dimensions.width(), dimensions.height(), info);
}
void GrVkGpu::querySampleLocations(GrRenderTarget* renderTarget,
SkTArray<SkPoint>* sampleLocations) {
// In Vulkan, sampleLocationsSupport() means that the platform uses the standard sample
// locations defined by the spec.
SkASSERT(this->caps()->sampleLocationsSupport());
static SkPoint kStandardSampleLocations_1[1] = {
{0.5f, 0.5f}};
static SkPoint kStandardSampleLocations_2[2] = {
{0.75f, 0.75f}, {0.25f, 0.25f}};
static SkPoint kStandardSampleLocations_4[4] = {
{0.375f, 0.125f}, {0.875f, 0.375f}, {0.125f, 0.625f}, {0.625f, 0.875f}};
static SkPoint kStandardSampleLocations_8[8] = {
{0.5625f, 0.3125f}, {0.4375f, 0.6875f}, {0.8125f, 0.5625f}, {0.3125f, 0.1875f},
{0.1875f, 0.8125f}, {0.0625f, 0.4375f}, {0.6875f, 0.9375f}, {0.9375f, 0.0625f}};
static SkPoint kStandardSampleLocations_16[16] = {
{0.5625f, 0.5625f}, {0.4375f, 0.3125f}, {0.3125f, 0.625f}, {0.75f, 0.4375f},
{0.1875f, 0.375f}, {0.625f, 0.8125f}, {0.8125f, 0.6875f}, {0.6875f, 0.1875f},
{0.375f, 0.875f}, {0.5f, 0.0625f}, {0.25f, 0.125f}, {0.125f, 0.75f},
{0.0f, 0.5f}, {0.9375f, 0.25f}, {0.875f, 0.9375f}, {0.0625f, 0.0f}};
int numSamples = renderTarget->numSamples();
if (1 == numSamples) {
SkASSERT(this->caps()->mixedSamplesSupport());
if (auto* stencil = renderTarget->renderTargetPriv().getStencilAttachment()) {
numSamples = stencil->numSamples();
}
}
SkASSERT(numSamples > 1);
SkASSERT(!renderTarget->renderTargetPriv().getStencilAttachment() ||
numSamples == renderTarget->renderTargetPriv().getStencilAttachment()->numSamples());
switch (numSamples) {
case 1:
sampleLocations->push_back_n(1, kStandardSampleLocations_1);
break;
case 2:
sampleLocations->push_back_n(2, kStandardSampleLocations_2);
break;
case 4:
sampleLocations->push_back_n(4, kStandardSampleLocations_4);
break;
case 8:
sampleLocations->push_back_n(8, kStandardSampleLocations_8);
break;
case 16:
sampleLocations->push_back_n(16, kStandardSampleLocations_16);
break;
default:
SK_ABORT("Invalid vulkan sample count.");
break;
}
}
void GrVkGpu::deleteBackendTexture(const GrBackendTexture& tex) {
SkASSERT(GrBackendApi::kVulkan == tex.fBackend);

View File

@ -75,10 +75,7 @@ public:
kSkip_SyncQueue
};
void querySampleLocations(GrRenderTarget*, SkTArray<SkPoint>*) override {
SkASSERT(!this->caps()->sampleLocationsSupport());
SK_ABORT("Sample locations not yet implemented for Vulkan.");
}
void querySampleLocations(GrRenderTarget*, SkTArray<SkPoint>*) override;
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}

View File

@ -1166,9 +1166,6 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
case SK_HEIGHT_BUILTIN:
fInputs.fRTHeight = true;
break;
case SK_SAMPLEMASK_BUILTIN:
fUsesSampleMask = true;
break;
#ifndef SKSL_STANDALONE
case SK_FRAGCOORD_BUILTIN:
fInputs.fFlipY = true;
@ -2425,25 +2422,6 @@ void IRGenerator::setRefKind(const Expression& expr, VariableReference::RefKind
}
}
void IRGenerator::removeSampleMask(std::vector<std::unique_ptr<ProgramElement>>* out) {
for (const auto& e : *out) {
switch (e->fKind) {
case ProgramElement::kVar_Kind: {
VarDeclarations& vd = (VarDeclarations&) *e;
for (auto iter = vd.fVars.begin(); iter != vd.fVars.end(); ++iter) {
SkASSERT((*iter)->fKind == Statement::kVarDeclaration_Kind);
const auto& v = (VarDeclaration&) **iter;
if (v.fVar->fName == "sk_SampleMask") {
vd.fVars.erase(iter);
return;
}
}
}
default: break;
}
}
}
void IRGenerator::convertProgram(Program::Kind kind,
const char* text,
size_t length,
@ -2509,9 +2487,6 @@ void IRGenerator::convertProgram(Program::Kind kind,
ABORT("unsupported declaration: %s\n", decl.description().c_str());
}
}
if (!fUsesSampleMask) {
this->removeSampleMask(out);
}
}

View File

@ -169,7 +169,6 @@ private:
Variable* fRTAdjustInterfaceBlock;
int fRTAdjustFieldIndex;
bool fStarted = false;
bool fUsesSampleMask = false;
friend class AutoSymbolTable;
friend class AutoLoopLevel;

View File

@ -2713,6 +2713,22 @@ void SPIRVCodeGenerator::writePrecisionModifier(Precision precision, SpvId id) {
}
}
bool is_dead(const Variable& var) {
if (var.fReadCount || var.fWriteCount) {
return false;
}
// not entirely sure what the rules are for when it's safe to elide interface variables, but it
// causes various problems to elide some of them even when dead. But it also causes problems
// *not* to elide sk_SampleMask when it's not being used.
if (!(var.fModifiers.fFlags & (Modifiers::kIn_Flag |
Modifiers::kOut_Flag |
Modifiers::kUniform_Flag |
Modifiers::kBuffer_Flag))) {
return true;
}
return var.fModifiers.fLayout.fBuiltin == SK_SAMPLEMASK_BUILTIN;
}
#define BUILTIN_IGNORE 9999
void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl,
OutputStream& out) {
@ -2737,13 +2753,7 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio
SkASSERT(!fProgram.fSettings.fFragColorIsInOut);
continue;
}
if (!var->fReadCount && !var->fWriteCount &&
!(var->fModifiers.fFlags & (Modifiers::kIn_Flag |
Modifiers::kOut_Flag |
Modifiers::kUniform_Flag |
Modifiers::kBuffer_Flag))) {
// variable is dead and not an input / output var (the Vulkan debug layers complain if
// we elide an interface var, even if it's dead)
if (is_dead(*var)) {
continue;
}
SpvStorageClass_ storageClass;
@ -3161,7 +3171,8 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
SpvId id = this->writeInterfaceBlock(intf);
if (((intf.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) ||
(intf.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag)) &&
intf.fVariable.fModifiers.fLayout.fBuiltin == -1) {
intf.fVariable.fModifiers.fLayout.fBuiltin == -1 &&
!is_dead(intf.fVariable)) {
interfaceVars.insert(id);
}
}
@ -3190,7 +3201,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
const Variable* var = entry.first;
if (var->fStorage == Variable::kGlobal_Storage &&
((var->fModifiers.fFlags & Modifiers::kIn_Flag) ||
(var->fModifiers.fFlags & Modifiers::kOut_Flag))) {
(var->fModifiers.fFlags & Modifiers::kOut_Flag)) && !is_dead(*var)) {
interfaceVars.insert(entry.second);
}
}