Add SkCapabilities object

This describes the capabilities of a particular Skia rendering context
(GPU context, or the CPU backend). At the moment, it only contains the
supported SkSL version (with a new enum added to specify the current
value as "100" and a new ES3 value as "300".

SkCapabilities can not be retrieved from an SkCanvas - the client must
have a concrete way of knowing what their destination device that will
do the actual rendering is (GrCaps or SkSurface).

This CL doesn't make use of the SkCapabilities yet, that's coming in
follow-up CLs that alter the SkSL compiler and SkRuntimeEffect API.

Bug: skia:11209
Change-Id: I4e9fd21ff7ffd79f1926c5c2eb34e10b3af4bc9b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/537876
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Brian Osman 2022-04-25 16:05:37 -04:00 committed by SkCQ
parent f6e31bf1dc
commit 69fecd6c2d
31 changed files with 206 additions and 14 deletions

View File

@ -206,8 +206,8 @@ DEF_SIMPLE_GPU_GM_CAN_FAIL(runtime_intrinsics_trig_es3,
ctx, canvas, errorMsg,
columns_to_width(3),
rows_to_height(2)) {
if (!ctx->priv().caps()->shaderCaps()->supportsSkSLES3()) {
*errorMsg = "SkSL ES3 is not supported.";
if (ctx->priv().caps()->shaderCaps()->supportedSkSLVerion() < SkSL::Version::k300) {
*errorMsg = "SkSL 300 is not supported.";
return skiagm::DrawResult::kSkip;
}
@ -317,8 +317,8 @@ DEF_SIMPLE_GPU_GM_CAN_FAIL(runtime_intrinsics_common_es3,
ctx, canvas, errorMsg,
columns_to_width(6),
rows_to_height(5)) {
if (!ctx->priv().caps()->shaderCaps()->supportsSkSLES3()) {
*errorMsg = "SkSL ES3 is not supported.";
if (ctx->priv().caps()->shaderCaps()->supportedSkSLVerion() < SkSL::Version::k300) {
*errorMsg = "SkSL 300 is not supported.";
return skiagm::DrawResult::kSkip;
}

View File

@ -14,6 +14,7 @@ skia_core_public = [
"$_include/core/SkBlender.h",
"$_include/core/SkBlendMode.h",
"$_include/core/SkBlurTypes.h",
"$_include/core/SkCapabilities.h",
"$_include/core/SkCanvas.h",
"$_include/core/SkCanvasVirtualEnforcer.h",
"$_include/core/SkClipOp.h",
@ -148,6 +149,7 @@ skia_core_sources = [
"$_src/core/SkCanvas.cpp",
"$_src/core/SkCanvasPriv.cpp",
"$_src/core/SkCanvasPriv.h",
"$_src/core/SkCapabilities.cpp",
"$_src/core/SkChromeRemoteGlyphCache.cpp",
"$_src/core/SkClipStack.cpp",
"$_src/core/SkClipStack.h",

View File

@ -36,6 +36,7 @@ skia_sksl_sources = [
"$_include/sksl/SkSLErrorReporter.h",
"$_include/sksl/SkSLOperator.h",
"$_include/sksl/SkSLPosition.h",
"$_include/sksl/SkSLVersion.h",
"$_src/sksl/SkSLAnalysis.cpp",
"$_src/sksl/SkSLAnalysis.h",
"$_src/sksl/SkSLBuiltinMap.cpp",

View File

@ -970,3 +970,13 @@ generated_cc_atom(
":SkTypes_hdr",
],
)
generated_cc_atom(
name = "SkCapabilities_hdr",
hdrs = ["SkCapabilities.h"],
visibility = ["//:__subpackages__"],
deps = [
":SkRefCnt_hdr",
"//include/sksl:SkSLVersion_hdr",
],
)

View File

@ -0,0 +1,31 @@
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkCapabilities_DEFINED
#define SkCapabilities_DEFINED
#include "include/core/SkRefCnt.h"
#include "include/sksl/SkSLVersion.h"
namespace skgpu::graphite { class Caps; }
class SK_API SkCapabilities : public SkNVRefCnt<SkCapabilities> {
public:
static sk_sp<SkCapabilities> RasterBackend();
SkSL::Version skslVersion() const { return fSkSLVersion; }
private:
SkCapabilities() = default;
SkSL::Version fSkSLVersion = SkSL::Version::k100;
friend class GrCaps;
friend class skgpu::graphite::Caps;
};
#endif

View File

@ -26,6 +26,7 @@
#endif
class SkCanvas;
class SkCapabilities;
class SkDeferredDisplayList;
class SkPaint;
class SkSurfaceCharacterization;
@ -600,6 +601,12 @@ public:
*/
SkCanvas* getCanvas();
/** Returns SkCapabilities that describes the capabilities of the SkSurface's device.
@return SkCapabilities of SkSurface's device.
*/
sk_sp<SkCapabilities> capabilities();
/** Returns a compatible SkSurface, or nullptr. Returned SkSurface contains
the same raster, GPU, or null properties as the original. Returned SkSurface
does not share the same pixels.

View File

@ -30,6 +30,7 @@ class GrSurfaceProxy;
class GrTextBlobRedrawCoordinator;
class GrThreadSafeCache;
class SkArenaAlloc;
class SkCapabilities;
class SkJSONWriter;
namespace sktext::gpu {
@ -97,6 +98,8 @@ public:
return INHERITED::maxSurfaceSampleCountForColorType(colorType);
}
SK_API sk_sp<SkCapabilities> skCapabilities() const;
// Provides access to functions that aren't part of the public API.
GrRecordingContextPriv priv();
const GrRecordingContextPriv priv() const; // NOLINT(readability-const-return-type)

View File

@ -191,3 +191,9 @@ generated_cc_atom(
hdrs = ["SkSLOperator.h"],
visibility = ["//:__subpackages__"],
)
generated_cc_atom(
name = "SkSLVersion_hdr",
hdrs = ["SkSLVersion.h"],
visibility = ["//:__subpackages__"],
)

View File

@ -0,0 +1,27 @@
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkSLVersion_DEFINED
#define SkSLVersion_DEFINED
namespace SkSL {
enum class Version {
/**
* Desktop GLSL 1.10, GLSL ES 1.00, WebGL 1.0
*/
k100,
/**
* Desktop GLSL 3.30, GLSL ES 3.00, WebGL 2.0
*/
k300,
};
} // namespace SkSL
#endif

View File

@ -36,6 +36,7 @@ cc_library(
":SkCachedData_src",
":SkCanvasPriv_src",
":SkCanvas_src",
":SkCapabilities_src",
":SkChromeRemoteGlyphCache_src",
":SkClipStackDevice_src",
":SkClipStack_src",
@ -5771,3 +5772,10 @@ generated_cc_atom(
visibility = ["//:__subpackages__"],
deps = ["//include/core:SkTypes_hdr"],
)
generated_cc_atom(
name = "SkCapabilities_src",
srcs = ["SkCapabilities.cpp"],
visibility = ["//:__subpackages__"],
deps = ["//include/core:SkCapabilities_hdr"],
)

View File

@ -0,0 +1,18 @@
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkCapabilities.h"
sk_sp<SkCapabilities> SkCapabilities::RasterBackend() {
static SkCapabilities* sCaps = [](){
SkCapabilities* caps = new SkCapabilities;
caps->fSkSLVersion = SkSL::Version::k100;
return caps;
}();
return sk_ref_sp(sCaps);
}

View File

@ -741,6 +741,7 @@ generated_cc_atom(
":GrSamplerState_hdr",
":GrShaderCaps_hdr",
":GrSurfaceProxy_hdr",
"//include/core:SkCapabilities_hdr",
"//include/core:SkImageInfo_hdr",
"//include/core:SkRefCnt_hdr",
"//include/core:SkString_hdr",
@ -764,6 +765,7 @@ generated_cc_atom(
":GrSurface_hdr",
":GrTestUtils_hdr",
":GrWindowRectangles_hdr",
"//include/core:SkCapabilities_hdr",
"//include/gpu:GrBackendSurface_hdr",
"//include/gpu:GrContextOptions_hdr",
"//include/private/gpu/ganesh:GrTypesPriv_hdr",
@ -2205,6 +2207,7 @@ generated_cc_atom(
":GrRecordingContextPriv_hdr",
":SkGr_hdr",
":SurfaceContext_hdr",
"//include/core:SkCapabilities_hdr",
"//include/gpu:GrContextThreadSafeProxy_hdr",
"//include/gpu:GrRecordingContext_hdr",
"//src/core:SkArenaAlloc_hdr",

View File

@ -7,6 +7,7 @@
#include "src/gpu/ganesh/GrCaps.h"
#include "include/core/SkCapabilities.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContextOptions.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
@ -103,6 +104,9 @@ void GrCaps::finishInitialization(const GrContextOptions& options) {
// Our render targets are always created with textures as the color attachment, hence this min:
fMaxRenderTargetSize = std::min(fMaxRenderTargetSize, fMaxTextureSize);
fMaxPreferredRenderTargetSize = std::min(fMaxPreferredRenderTargetSize, fMaxRenderTargetSize);
fSkCaps.reset(new SkCapabilities);
fSkCaps->fSkSLVersion = this->shaderCaps()->supportedSkSLVerion();
}
void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
@ -480,3 +484,8 @@ std::tuple<GrColorType, GrBackendFormat> GrCaps::getFallbackColorTypeAndFormat(
} while (ct != GrColorType::kUnknown);
return {GrColorType::kUnknown, {}};
}
sk_sp<SkCapabilities> GrCaps::asSkCapabilities() const {
SkASSERTF(fSkCaps, "Calling asSkCapabilities before it's initialized");
return fSkCaps;
}

View File

@ -8,6 +8,7 @@
#ifndef GrCaps_DEFINED
#define GrCaps_DEFINED
#include "include/core/SkCapabilities.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkString.h"
@ -41,6 +42,7 @@ class GrCaps : public SkRefCnt {
public:
GrCaps(const GrContextOptions&);
sk_sp<SkCapabilities> asSkCapabilities() const;
void dumpJSON(SkJSONWriter*) const;
const GrShaderCaps* shaderCaps() const { return fShaderCaps.get(); }
@ -525,6 +527,7 @@ protected:
virtual bool onSupportsDynamicMSAA(const GrRenderTargetProxy*) const { return false; }
std::unique_ptr<GrShaderCaps> fShaderCaps;
sk_sp<SkCapabilities> fSkCaps;
bool fNPOTTextureTileSupport : 1;
bool fMipmapSupport : 1;

View File

@ -7,6 +7,7 @@
#include "include/gpu/GrRecordingContext.h"
#include "include/core/SkCapabilities.h"
#include "include/gpu/GrContextThreadSafeProxy.h"
#include "src/core/SkArenaAlloc.h"
#include "src/gpu/ganesh/GrAuditTrail.h"
@ -159,6 +160,10 @@ void GrRecordingContext::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlu
////////////////////////////////////////////////////////////////////////////////
sk_sp<SkCapabilities> GrRecordingContext::skCapabilities() const {
return this->caps()->asSkCapabilities();
}
int GrRecordingContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }
int GrRecordingContext::maxRenderTargetSize() const { return this->caps()->maxRenderTargetSize(); }

View File

@ -54,14 +54,6 @@ struct GrShaderCaps : SkSL::ShaderCaps {
// reduce the number of unique shaders generated.
bool reducedShaderMode() const { return fReducedShaderMode; }
/**
* SkSL ES3 requires support for derivatives, nonsquare matrices and bitwise integer operations.
*/
bool supportsSkSLES3() const {
return fShaderDerivativeSupport && fNonsquareMatrixSupport && fIntegerSupport &&
fGLSLGeneration >= SkSL::GLSLGeneration::k330;
}
// SkSL only.
bool colorSpaceMathNeedsFloat() const { return fColorSpaceMathNeedsFloat; }

View File

@ -44,6 +44,7 @@ generated_cc_atom(
visibility = ["//:__subpackages__"],
deps = [
":ResourceTypes_hdr",
"//include/core:SkCapabilities_hdr",
"//include/core:SkImageInfo_hdr",
"//include/core:SkRefCnt_hdr",
"//src/core:SkEnumBitMask_hdr",
@ -58,6 +59,7 @@ generated_cc_atom(
visibility = ["//:__subpackages__"],
deps = [
":Caps_hdr",
"//include/core:SkCapabilities_hdr",
"//include/gpu/graphite:TextureInfo_hdr",
"//src/sksl:SkSLUtil_hdr",
],
@ -673,9 +675,12 @@ generated_cc_atom(
srcs = ["Surface_Graphite.cpp"],
visibility = ["//:__subpackages__"],
deps = [
":Caps_hdr",
":Device_hdr",
":Image_Graphite_hdr",
":RecorderPriv_hdr",
":Surface_Graphite_hdr",
"//include/core:SkCapabilities_hdr",
"//include/gpu/graphite:Recorder_hdr",
"//include/gpu/graphite:SkStuff_hdr",
],

View File

@ -7,6 +7,7 @@
#include "src/gpu/graphite/Caps.h"
#include "include/core/SkCapabilities.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "src/sksl/SkSLUtil.h"
@ -52,4 +53,12 @@ skgpu::Swizzle Caps::getWriteSwizzle(SkColorType ct, const TextureInfo& info) co
return colorTypeInfo->fWriteSwizzle;
}
sk_sp<SkCapabilities> Caps::asSkCapabilities() const {
if (!fSkCaps) {
fSkCaps.reset(new SkCapabilities);
fSkCaps->fSkSLVersion = this->shaderCaps()->supportedSkSLVerion();
}
return fSkCaps;
}
} // namespace skgpu::graphite

View File

@ -8,6 +8,7 @@
#ifndef skgpu_graphite_Caps_DEFINED
#define skgpu_graphite_Caps_DEFINED
#include "include/core/SkCapabilities.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "src/core/SkEnumBitMask.h"
@ -30,6 +31,7 @@ class Caps : public SkRefCnt {
public:
~Caps() override;
sk_sp<SkCapabilities> asSkCapabilities() const;
const SkSL::ShaderCaps* shaderCaps() const { return fShaderCaps.get(); }
virtual TextureInfo getDefaultSampledTextureInfo(SkColorType,
@ -103,6 +105,7 @@ protected:
size_t fRequiredUniformBufferAlignment = 0;
std::unique_ptr<SkSL::ShaderCaps> fShaderCaps;
mutable sk_sp<SkCapabilities> fSkCaps;
bool fClampToBorderSupport = true;

View File

@ -7,10 +7,13 @@
#include "src/gpu/graphite/Surface_Graphite.h"
#include "include/core/SkCapabilities.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/SkStuff.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/Device.h"
#include "src/gpu/graphite/Image_Graphite.h"
#include "src/gpu/graphite/RecorderPriv.h"
namespace skgpu::graphite {
@ -56,4 +59,8 @@ bool Surface::onReadPixels(Context* context,
return fDevice->readPixels(context, recorder, dst, srcX, srcY);
}
sk_sp<SkCapabilities> Surface::onCapabilities() {
return fDevice->recorder()->priv().caps()->asSkCapabilities();
}
} // namespace skgpu::graphite

View File

@ -28,6 +28,7 @@ public:
void onWritePixels(const SkPixmap&, int x, int y) override;
bool onCopyOnWrite(ContentChangeMode) override;
bool onReadPixels(Context*, Recorder*, const SkPixmap& dst, int srcX, int srcY);
sk_sp<SkCapabilities> onCapabilities() override;
private:
sk_sp<Device> fDevice;

View File

@ -382,6 +382,7 @@ generated_cc_atom(
":SkSurface_Base_hdr",
":SkSurface_Gpu_hdr",
"//include/core:SkCanvas_hdr",
"//include/core:SkCapabilities_hdr",
"//include/core:SkDeferredDisplayList_hdr",
"//include/core:SkSurfaceCharacterization_hdr",
"//include/gpu:GrBackendSurface_hdr",
@ -408,6 +409,7 @@ generated_cc_atom(
deps = [
":SkSurface_Base_hdr",
"//include/core:SkCanvas_hdr",
"//include/core:SkCapabilities_hdr",
"//include/core:SkMallocPixelRef_hdr",
"//include/private:SkImageInfoPriv_hdr",
"//src/core:SkDevice_hdr",
@ -424,6 +426,7 @@ generated_cc_atom(
":SkRescaleAndReadPixels_hdr",
":SkSurface_Base_hdr",
"//include/core:SkCanvas_hdr",
"//include/core:SkCapabilities_hdr",
"//include/gpu:GrBackendSurface_hdr",
"//include/utils:SkNoDrawCanvas_hdr",
"//src/core:SkAutoPixmapStorage_hdr",

View File

@ -8,6 +8,7 @@
#include <atomic>
#include <cmath>
#include "include/core/SkCanvas.h"
#include "include/core/SkCapabilities.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkImagePriv.h"
#include "src/core/SkPaintPriv.h"
@ -205,6 +206,10 @@ SkCanvas* SkSurface::getCanvas() {
return asSB(this)->getCachedCanvas();
}
sk_sp<SkCapabilities> SkSurface::capabilities() {
return asSB(this)->onCapabilities();
}
sk_sp<SkImage> SkSurface::makeImageSnapshot() {
return asSB(this)->refCachedImage();
}
@ -410,6 +415,10 @@ protected:
void onWritePixels(const SkPixmap&, int x, int y) override {}
void onDraw(SkCanvas*, SkScalar, SkScalar, const SkSamplingOptions&, const SkPaint*) override {}
bool onCopyOnWrite(ContentChangeMode) override { return true; }
sk_sp<SkCapabilities> onCapabilities() override {
// Not really, but we have to return *something*
return SkCapabilities::RasterBackend();
}
};
sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) {

View File

@ -137,6 +137,8 @@ public:
return false;
}
virtual sk_sp<SkCapabilities> onCapabilities() = 0;
inline SkCanvas* getCachedCanvas();
inline sk_sp<SkImage> refCachedImage();

View File

@ -8,6 +8,7 @@
#include "src/image/SkSurface_Gpu.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkCapabilities.h"
#include "include/core/SkDeferredDisplayList.h"
#include "include/core/SkSurfaceCharacterization.h"
#include "include/gpu/GrBackendSurface.h"
@ -391,6 +392,10 @@ bool SkSurface_Gpu::onDraw(sk_sp<const SkDeferredDisplayList> ddl, SkIPoint offs
return true;
}
sk_sp<SkCapabilities> SkSurface_Gpu::onCapabilities() {
return fDevice->recordingContext()->skCapabilities();
}
///////////////////////////////////////////////////////////////////////////////
sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* rContext,

View File

@ -57,6 +57,7 @@ public:
const SkPaint* paint) override;
bool onDraw(sk_sp<const SkDeferredDisplayList>, SkIPoint offset) override;
sk_sp<SkCapabilities> onCapabilities() override;
skgpu::BaseDevice* getDevice();
private:

View File

@ -6,6 +6,7 @@
*/
#include "include/core/SkCanvas.h"
#include "include/core/SkCapabilities.h"
#include "include/core/SkMallocPixelRef.h"
#include "include/private/SkImageInfoPriv.h"
#include "src/core/SkDevice.h"
@ -26,6 +27,7 @@ public:
void onDraw(SkCanvas*, SkScalar, SkScalar, const SkSamplingOptions&, const SkPaint*) override;
bool onCopyOnWrite(ContentChangeMode) override;
void onRestoreBackingMutability() override;
sk_sp<SkCapabilities> onCapabilities() override;
private:
SkBitmap fBitmap;
@ -153,6 +155,10 @@ bool SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
return true;
}
sk_sp<SkCapabilities> SkSurface_Raster::onCapabilities() {
return SkCapabilities::RasterBackend();
}
///////////////////////////////////////////////////////////////////////////////
sk_sp<SkSurface> SkSurface::MakeRasterDirectReleaseProc(const SkImageInfo& info, void* pixels,

View File

@ -875,6 +875,7 @@ generated_cc_atom(
deps = [
":SkSLGLSL_hdr",
"//include/core:SkTypes_hdr",
"//include/sksl:SkSLVersion_hdr",
"//src/core:SkSLTypeShared_hdr",
],
)

View File

@ -8,6 +8,7 @@
#ifndef SKSL_UTIL
#define SKSL_UTIL
#include "include/sksl/SkSLVersion.h"
#include "src/core/SkSLTypeShared.h"
#include "src/sksl/SkSLGLSL.h"
@ -180,6 +181,17 @@ struct ShaderCaps {
return fSecondExternalTextureExtensionString;
}
/**
* SkSL 300 requires support for derivatives, nonsquare matrices and bitwise integer operations.
*/
SkSL::Version supportedSkSLVerion() const {
if (fShaderDerivativeSupport && fNonsquareMatrixSupport && fIntegerSupport &&
fGLSLGeneration >= SkSL::GLSLGeneration::k330) {
return SkSL::Version::k300;
}
return SkSL::Version::k100;
}
SkSL::GLSLGeneration generation() const { return fGLSLGeneration; }
SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330;

View File

@ -5965,6 +5965,7 @@ generated_cc_atom(
"//include/private:SkSLProgramElement_hdr",
"//include/private:SkSLProgramKind_hdr",
"//include/sksl:DSLCore_hdr",
"//include/sksl:SkSLVersion_hdr",
"//src/core:SkRuntimeEffectPriv_hdr",
"//src/gpu/ganesh:GrCaps_hdr",
"//src/gpu/ganesh:GrDirectContextPriv_hdr",

View File

@ -24,6 +24,7 @@
#include "include/private/SkSLProgramElement.h"
#include "include/private/SkSLProgramKind.h"
#include "include/sksl/DSLCore.h"
#include "include/sksl/SkSLVersion.h"
#include "src/core/SkRuntimeEffectPriv.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
@ -232,8 +233,9 @@ static void test_cpu(skiatest::Reporter* r, const char* testFile, int flags) {
static void test_gpu(skiatest::Reporter* r, GrDirectContext* ctx, const char* testFile, int flags) {
// If this is an ES3-only test on a GPU which doesn't support SkSL ES3, return immediately.
bool shouldRunGPU = (flags & SkSLTestFlags::GPU);
bool shouldRunGPU_ES3 = (flags & SkSLTestFlags::GPU_ES3) &&
ctx->priv().caps()->shaderCaps()->supportsSkSLES3();
bool shouldRunGPU_ES3 =
(flags & SkSLTestFlags::GPU_ES3) &&
(ctx->priv().caps()->shaderCaps()->supportedSkSLVerion() >= SkSL::Version::k300);
if (!shouldRunGPU && !shouldRunGPU_ES3) {
return;
}