static bool use_flat_interpolation(GrGLSLVaryingHandler::Interpolation interpolation, const GrShaderCaps& shaderCaps) { switch (interpolation) { using Interpolation = GrGLSLVaryingHandler::Interpolation; case Interpolation::kInterpolated: return false; case Interpolation::kCanBeFlat: SkASSERT(!shaderCaps.preferFlatInterpolation() || shaderCaps.flatInterpolationSupport()); return shaderCaps.preferFlatInterpolation(); case Interpolation::kMustBeFlat: SkASSERT(shaderCaps.flatInterpolationSupport()); return true; } SK_ABORT("Invalid interpolation"); return false; }
GrBitmapTextGeoProc::GrBitmapTextGeoProc(const GrShaderCaps& caps, GrColor color, const sk_sp<GrTextureProxy>* proxies, int numActiveProxies, const GrSamplerState& params, GrMaskFormat format, const SkMatrix& localMatrix, bool usesW) : INHERITED(kGrBitmapTextGeoProc_ClassID) , fColor(color) , fLocalMatrix(localMatrix) , fUsesW(usesW) , fMaskFormat(format) { SkASSERT(numActiveProxies <= kMaxTextures); if (usesW) { fInPosition = {"inPosition", kFloat3_GrVertexAttribType, kFloat3_GrSLType}; } else { fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType}; } fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType, caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType }; int cnt = 2; bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat || kA565_GrMaskFormat == fMaskFormat; if (hasVertexColor) { fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType}; ++cnt; } this->setVertexAttributeCnt(cnt); if (numActiveProxies) { fAtlasSize = proxies[0]->isize(); } for (int i = 0; i < numActiveProxies; ++i) { SkASSERT(proxies[i]); SkASSERT(proxies[i]->isize() == fAtlasSize); fTextureSamplers[i].reset(proxies[i]->textureType(), proxies[i]->config(), params); } this->setTextureSamplerCnt(numActiveProxies); }
// Will the given round rect look good if we use HW derivatives? static bool can_use_hw_derivatives_with_coverage( const GrShaderCaps& shaderCaps, const SkMatrix& viewMatrix, const SkRRect& rrect) { if (!shaderCaps.shaderDerivativeSupport()) { return false; } Sk2f x = Sk2f(viewMatrix.getScaleX(), viewMatrix.getSkewX()); Sk2f y = Sk2f(viewMatrix.getSkewY(), viewMatrix.getScaleY()); Sk2f devScale = (x*x + y*y).sqrt(); switch (rrect.getType()) { case SkRRect::kEmpty_Type: case SkRRect::kRect_Type: return true; case SkRRect::kOval_Type: case SkRRect::kSimple_Type: return can_use_hw_derivatives_with_coverage(devScale, rrect.getSimpleRadii()); case SkRRect::kNinePatch_Type: { Sk2f r0 = Sk2f::Load(SkRRectPriv::GetRadiiArray(rrect)); Sk2f r1 = Sk2f::Load(SkRRectPriv::GetRadiiArray(rrect) + 2); Sk2f minRadii = Sk2f::Min(r0, r1); Sk2f maxRadii = Sk2f::Max(r0, r1); return can_use_hw_derivatives_with_coverage(devScale, Sk2f(minRadii[0], maxRadii[1])) && can_use_hw_derivatives_with_coverage(devScale, Sk2f(maxRadii[0], minRadii[1])); } case SkRRect::kComplex_Type: { for (int i = 0; i < 4; ++i) { auto corner = static_cast<SkRRect::Corner>(i); if (!can_use_hw_derivatives_with_coverage(devScale, rrect.radii(corner))) { return false; } } return true; } } SK_ABORT("Invalid round rect type."); return false; // Add this return to keep GCC happy. }
bool GrTextUtils::CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, const SkSurfaceProps& props, const GrShaderCaps& caps) { // TODO: support perspective (need getMaxScale replacement) if (viewMatrix.hasPerspective()) { return false; } SkScalar maxScale = viewMatrix.getMaxScale(); SkScalar scaledTextSize = maxScale*skPaint.getTextSize(); // Hinted text looks far better at small resolutions // Scaling up beyond 2x yields undesireable artifacts if (scaledTextSize < kMinDFFontSize || scaledTextSize > kLargeDFFontLimit) { return false; } bool useDFT = props.isUseDeviceIndependentFonts(); #if SK_FORCE_DISTANCE_FIELD_TEXT useDFT = true; #endif if (!useDFT && scaledTextSize < kLargeDFFontSize) { return false; } // rasterizers and mask filters modify alpha, which doesn't // translate well to distance if (skPaint.getRasterizer() || skPaint.getMaskFilter() || !caps.shaderDerivativeSupport()) { return false; } // TODO: add some stroking support if (skPaint.getStyle() != SkPaint::kFill_Style) { return false; } return true; }
void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties, uint32_t featureFlags) { GrShaderCaps* shaderCaps = fShaderCaps.get(); shaderCaps->fVersionDeclString = "#version 330\n"; // fConfigOutputSwizzle will default to RGBA so we only need to set it for alpha only config. for (int i = 0; i < kGrPixelConfigCnt; ++i) { GrPixelConfig config = static_cast<GrPixelConfig>(i); if (GrPixelConfigIsAlphaOnly(config)) { shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRR(); shaderCaps->fConfigOutputSwizzle[i] = GrSwizzle::AAAA(); } else { if (kGray_8_GrPixelConfig == config) { shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRA(); } else if (kRGBA_4444_GrPixelConfig == config) { // The vulkan spec does not require R4G4B4A4 to be supported for texturing so we // store the data in a B4G4R4A4 texture and then swizzle it when doing texture reads // or writing to outputs. Since we're not actually changing the data at all, the // only extra work is the swizzle in the shader for all operations. shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::BGRA(); shaderCaps->fConfigOutputSwizzle[i] = GrSwizzle::BGRA(); } else { shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGBA(); } } } if (kImagination_VkVendor == properties.vendorID) { shaderCaps->fAtan2ImplementedAsAtanYOverX = true; } // Vulkan is based off ES 3.0 so the following should all be supported shaderCaps->fUsesPrecisionModifiers = true; shaderCaps->fFlatInterpolationSupport = true; // GrShaderCaps shaderCaps->fShaderDerivativeSupport = true; shaderCaps->fGeometryShaderSupport = SkToBool(featureFlags & kGeometryShader_GrVkFeatureFlag); shaderCaps->fDualSourceBlendingSupport = SkToBool(featureFlags & kDualSrcBlend_GrVkFeatureFlag); if (kAMD_VkVendor == properties.vendorID) { // Currently DualSourceBlending is not working on AMD. vkCreateGraphicsPipeline fails when // using a draw with dual source. Looking into whether it is driver bug or issue with our // SPIR-V. Bug skia:6405 shaderCaps->fDualSourceBlendingSupport = false; } shaderCaps->fIntegerSupport = true; shaderCaps->fTexelBufferSupport = true; shaderCaps->fTexelFetchSupport = true; shaderCaps->fVertexIDSupport = true; // Assume the minimum precisions mandated by the SPIR-V spec. shaderCaps->fShaderPrecisionVaries = true; for (int s = 0; s < kGrShaderTypeCount; ++s) { auto& highp = shaderCaps->fFloatPrecisions[s][kHigh_GrSLPrecision]; highp.fLogRangeLow = highp.fLogRangeHigh = 127; highp.fBits = 23; auto& mediump = shaderCaps->fFloatPrecisions[s][kMedium_GrSLPrecision]; mediump.fLogRangeLow = mediump.fLogRangeHigh = 14; mediump.fBits = 10; shaderCaps->fFloatPrecisions[s][kLow_GrSLPrecision] = mediump; } shaderCaps->initSamplerPrecisionTable(); shaderCaps->fMaxVertexSamplers = shaderCaps->fMaxGeometrySamplers = shaderCaps->fMaxFragmentSamplers = SkTMin( SkTMin(properties.limits.maxPerStageDescriptorSampledImages, properties.limits.maxPerStageDescriptorSamplers), (uint32_t)INT_MAX); shaderCaps->fMaxCombinedSamplers = SkTMin( SkTMin(properties.limits.maxDescriptorSetSampledImages, properties.limits.maxDescriptorSetSamplers), (uint32_t)INT_MAX); }