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>

Change-Id: Idd0d8f63c7bb1cdd4d905c483f2fe7ed2b34b05f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252306
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2019-11-01 14:15:47 -04:00 committed by Skia Commit-Bot
parent 5625412f02
commit 2245bf8313
7 changed files with 71 additions and 47 deletions

View File

@ -291,7 +291,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

@ -497,6 +497,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;
}
// We could actually query and get a max size for each config, however maxImageDimension2D will
// give the minimum max size across all configs. So for simplicity we will use that for now.
fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
@ -563,7 +567,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;
@ -1187,12 +1191,7 @@ void GrVkCaps::FormatInfo::initSampleCounts(const GrVkInterface* interface,
if (flags & VK_SAMPLE_COUNT_16_BIT) {
fColorSampleCounts.push_back(16);
}
if (flags & VK_SAMPLE_COUNT_32_BIT) {
fColorSampleCounts.push_back(32);
}
if (flags & VK_SAMPLE_COUNT_64_BIT) {
fColorSampleCounts.push_back(64);
}
// Standard sample locations are not defined for 32 or 64 samples, so we omit these options.
}
void GrVkCaps::FormatInfo::init(const GrVkInterface* interface,

View File

@ -1814,6 +1814,48 @@ 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}};
switch (renderTarget->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

@ -72,10 +72,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);
}
}