Move GrShaderCaps from Program::Settings to Compiler
This ties the caps to the compiler instance, paving the way for
pre-optimizing the shared code. Most of the time, the compiler is
created and owned the GPU instance, so this is fine. For runtime
effects, we now use the shared (device-agnostic) compiler instance
for the first compile, even on GPU. It's configured with caps that
apply no workarounds. We pass the user's SkSL to the backend as
cleanly as possible, and then apply any workarounds once it's part
of the full program.
Bug: skia:10905
Bug: skia:10868
Change-Id: Ifcf8d7ebda5d43ad8e180f06700a261811da83de
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/331493
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index 9873564..c679dcc 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -23,6 +23,7 @@
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLByteCode.h"
#include "src/sksl/SkSLCompiler.h"
+#include "src/sksl/SkSLUtil.h"
#include "src/sksl/ir/SkSLFunctionDefinition.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
@@ -40,16 +41,18 @@
class SharedCompiler {
public:
SharedCompiler() : fLock(compiler_mutex()) {
- if (!gCompiler) {
- gCompiler = new SkSL::Compiler{};
- gInlineThreshold = SkSL::Program::Settings().fInlineThreshold;
+ if (!gImpl) {
+ gImpl = new Impl();
}
}
- SkSL::Compiler* operator->() const { return gCompiler; }
+ SkSL::Compiler* operator->() const { return gImpl->fCompiler; }
- int getInlineThreshold() const { return gInlineThreshold; }
- void setInlineThreshold(int threshold) { gInlineThreshold = threshold; }
+ // The inline threshold is exposed just for fuzzing, so we can test programs with it enabled
+ // and disabled. That lets us stress different code paths in the SkSL compiler. It's stashed
+ // along-side the compiler, but just so it can be guarded by the same mutex.
+ int getInlineThreshold() const { return gImpl->fInlineThreshold; }
+ void setInlineThreshold(int threshold) { gImpl->fInlineThreshold = threshold; }
private:
SkAutoMutexExclusive fLock;
@@ -59,11 +62,44 @@
return mutex;
}
- static SkSL::Compiler* gCompiler;
- static int gInlineThreshold;
+ struct Impl {
+ Impl() {
+ // These caps are configured to apply *no* workarounds. This avoids changes that are
+ // unnecessary (GLSL intrinsic rewrites), or possibly incorrect (adding do-while loops).
+ // We may apply other "neutral" transformations to the user's SkSL, including inlining.
+ // Anything determined by the device caps is deferred to the GPU backend. The processor
+ // set produces the final program (including our re-emitted SkSL), and the backend's
+ // compiler resolves any necessary workarounds.
+ fCaps = ShaderCapsFactory::Standalone();
+ fCaps->fBuiltinFMASupport = true;
+ fCaps->fBuiltinDeterminantSupport = true;
+ // Don't inline if it would require a do loop, some devices don't support them.
+ fCaps->fCanUseDoLoops = false;
+
+ fCompiler = new SkSL::Compiler(fCaps.get());
+
+ // Using an inline threshold of zero would stop all inlining, and cause us to re-emit
+ // SkSL that is nearly identical to what was ingested. That would be in the spirit of
+ // applying no workarounds, but causes problems (today). On the CPU backend, we only
+ // compile the user SkSL once, then emit directly to ByteCode. The CPU backend doesn't
+ // support function calls, so some tests only work because of inlining. This needs to
+ // be addressed robustly - by adding function call support and/or forcing inlining,
+ // but for now, we use defaults that let the majority of our test cases work on all
+ // backends. (Note that there are other control flow constructs that don't work on the
+ // CPU backend, this is a special case of a more general problem.) skbug.com/10680
+ fInlineThreshold = SkSL::Program::Settings().fInlineThreshold;
+ }
+
+ SkSL::ShaderCapsPointer fCaps;
+ SkSL::Compiler* fCompiler;
+ int fInlineThreshold;
+ };
+
+ static Impl* gImpl;
};
-SkSL::Compiler* SharedCompiler::gCompiler = nullptr;
-int SharedCompiler::gInlineThreshold = 0;
+
+SharedCompiler::Impl* SharedCompiler::gImpl = nullptr;
+
} // namespace SkSL
void SkRuntimeEffect_SetInlineThreshold(int threshold) {
@@ -296,27 +332,11 @@
}
#if SK_SUPPORT_GPU
-bool SkRuntimeEffect::toPipelineStage(const GrShaderCaps* shaderCaps,
- GrContextOptions::ShaderErrorHandler* errorHandler,
+bool SkRuntimeEffect::toPipelineStage(GrContextOptions::ShaderErrorHandler* errorHandler,
SkSL::PipelineStageArgs* outArgs) {
SkSL::SharedCompiler compiler;
- // This function is used by the GPU backend, and can't reuse our previously built fBaseProgram.
- // If the supplied shaderCaps have any non-default values, we have baked in the wrong settings.
- SkSL::Program::Settings settings;
- settings.fCaps = shaderCaps;
- settings.fInlineThreshold = compiler.getInlineThreshold();
- settings.fAllowNarrowingConversions = true;
-
- auto program = compiler->convertProgram(SkSL::Program::kPipelineStage_Kind,
- SkSL::String(fSkSL.c_str(), fSkSL.size()),
- settings);
- if (!program) {
- errorHandler->compileError(fSkSL.c_str(), compiler->errorText().c_str());
- return false;
- }
-
- if (!compiler->toPipelineStage(*program, outArgs)) {
+ if (!compiler->toPipelineStage(*fBaseProgram, outArgs)) {
errorHandler->compileError(fSkSL.c_str(), compiler->errorText().c_str());
return false;
}
diff --git a/src/gpu/GrShaderCaps.h b/src/gpu/GrShaderCaps.h
index a131db4..365d71c 100644
--- a/src/gpu/GrShaderCaps.h
+++ b/src/gpu/GrShaderCaps.h
@@ -15,6 +15,7 @@
namespace SkSL {
class ShaderCapsFactory;
+class SharedCompiler;
} // namespace SkSL
struct GrContextOptions;
@@ -338,6 +339,7 @@
friend class GrMtlCaps;
friend class GrVkCaps;
friend class SkSL::ShaderCapsFactory;
+ friend class SkSL::SharedCompiler;
};
#endif
diff --git a/src/gpu/d3d/GrD3DGpu.cpp b/src/gpu/d3d/GrD3DGpu.cpp
index ad07cfb..1dc7078 100644
--- a/src/gpu/d3d/GrD3DGpu.cpp
+++ b/src/gpu/d3d/GrD3DGpu.cpp
@@ -64,11 +64,11 @@
, fResourceProvider(this)
, fStagingBufferManager(this)
, fConstantsRingBuffer(this, 128 * 1024, kConstantAlignment, GrGpuBufferType::kVertex)
- , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt)
- , fCompiler(new SkSL::Compiler()) {
+ , fOutstandingCommandLists(sizeof(OutstandingCommandList), kDefaultOutstandingAllocCnt) {
fCaps.reset(new GrD3DCaps(contextOptions,
backendContext.fAdapter.get(),
backendContext.fDevice.get()));
+ fCompiler.reset(new SkSL::Compiler(fCaps->shaderCaps()));
fCurrentDirectCommandList = fResourceProvider.findOrCreateDirectCommandList();
SkASSERT(fCurrentDirectCommandList);
diff --git a/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp b/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
index 3ec51be..1e22c2b 100644
--- a/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
+++ b/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
@@ -550,7 +550,6 @@
this->finalizeShaders();
SkSL::Program::Settings settings;
- settings.fCaps = this->caps()->shaderCaps();
settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
settings.fSharpenTextures =
this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp
index 79b5fc9..5cb40e2 100644
--- a/src/gpu/dawn/GrDawnGpu.cpp
+++ b/src/gpu/dawn/GrDawnGpu.cpp
@@ -126,12 +126,12 @@
: INHERITED(direct)
, fDevice(device)
, fQueue(device.GetDefaultQueue())
- , fCompiler(new SkSL::Compiler())
, fUniformRingBuffer(this, wgpu::BufferUsage::Uniform)
, fStagingBufferManager(this)
, fRenderPipelineCache(kMaxRenderPipelineEntries)
, fFinishCallbacks(this) {
fCaps.reset(new GrDawnCaps(options));
+ fCompiler.reset(new SkSL::Compiler(fCaps->shaderCaps()));
}
GrDawnGpu::~GrDawnGpu() {
@@ -931,7 +931,6 @@
SkSL::String GrDawnGpu::SkSLToSPIRV(const char* shaderString, SkSL::Program::Kind kind, bool flipY,
uint32_t rtHeightOffset, SkSL::Program::Inputs* inputs) {
SkSL::Program::Settings settings;
- settings.fCaps = this->caps()->shaderCaps();
settings.fFlipY = flipY;
settings.fRTHeightOffset = rtHeightOffset;
settings.fRTHeightBinding = 0;
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index d9856af..9b392a9 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -157,15 +157,13 @@
if (uniforms->size() != effect->uniformSize()) {
return nullptr;
}
- return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(
- context->priv().caps()->refShaderCaps(), context->priv().getShaderErrorHandler(),
- std::move(effect), name, std::move(uniforms)));
+ return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().getShaderErrorHandler(),
+ std::move(effect), name, std::move(uniforms)));
}
-GrSkSLFP::GrSkSLFP(sk_sp<const GrShaderCaps> shaderCaps, ShaderErrorHandler* shaderErrorHandler,
- sk_sp<SkRuntimeEffect> effect, const char* name, sk_sp<SkData> uniforms)
+GrSkSLFP::GrSkSLFP(ShaderErrorHandler* shaderErrorHandler, sk_sp<SkRuntimeEffect> effect,
+ const char* name, sk_sp<SkData> uniforms)
: INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
- , fShaderCaps(std::move(shaderCaps))
, fShaderErrorHandler(shaderErrorHandler)
, fEffect(std::move(effect))
, fName(name)
@@ -177,7 +175,6 @@
GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
: INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
- , fShaderCaps(other.fShaderCaps)
, fShaderErrorHandler(other.fShaderErrorHandler)
, fEffect(other.fEffect)
, fName(other.fName)
@@ -202,7 +199,7 @@
GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
// Note: This is actually SkSL (again) but with inline format specifiers.
SkSL::PipelineStageArgs args;
- SkAssertResult(fEffect->toPipelineStage(fShaderCaps.get(), fShaderErrorHandler, &args));
+ SkAssertResult(fEffect->toPipelineStage(fShaderErrorHandler, &args));
return new GrGLSLSkSLFP(std::move(args));
}
diff --git a/src/gpu/effects/GrSkSLFP.h b/src/gpu/effects/GrSkSLFP.h
index 6ca07d2..541acec 100644
--- a/src/gpu/effects/GrSkSLFP.h
+++ b/src/gpu/effects/GrSkSLFP.h
@@ -10,7 +10,6 @@
#include "include/core/SkRefCnt.h"
#include "include/gpu/GrContextOptions.h"
-#include "src/gpu/GrCaps.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
@@ -50,8 +49,8 @@
private:
using ShaderErrorHandler = GrContextOptions::ShaderErrorHandler;
- GrSkSLFP(sk_sp<const GrShaderCaps> shaderCaps, ShaderErrorHandler* shaderErrorHandler,
- sk_sp<SkRuntimeEffect> effect, const char* name, sk_sp<SkData> uniforms);
+ GrSkSLFP(ShaderErrorHandler* shaderErrorHandler, sk_sp<SkRuntimeEffect> effect,
+ const char* name, sk_sp<SkData> uniforms);
GrSkSLFP(const GrSkSLFP& other);
@@ -61,7 +60,6 @@
bool onIsEqual(const GrFragmentProcessor&) const override;
- sk_sp<const GrShaderCaps> fShaderCaps;
ShaderErrorHandler* fShaderErrorHandler;
sk_sp<SkRuntimeEffect> fEffect;
diff --git a/src/gpu/gl/GrGLContext.cpp b/src/gpu/gl/GrGLContext.cpp
index c7f3584..07dd68d 100644
--- a/src/gpu/gl/GrGLContext.cpp
+++ b/src/gpu/gl/GrGLContext.cpp
@@ -96,7 +96,7 @@
SkSL::Compiler* GrGLContext::compiler() const {
if (!fCompiler) {
- fCompiler = new SkSL::Compiler();
+ fCompiler = new SkSL::Compiler(fGLCaps->shaderCaps());
}
return fCompiler;
}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 7b8eb91..0288899 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3046,7 +3046,6 @@
auto errorHandler = this->getContext()->priv().getShaderErrorHandler();
SkSL::String sksl(vshaderTxt.c_str(), vshaderTxt.size());
SkSL::Program::Settings settings;
- settings.fCaps = shaderCaps;
SkSL::String glsl;
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kVertex_Kind,
sksl, settings, &glsl, errorHandler);
@@ -3200,7 +3199,6 @@
auto errorHandler = this->getContext()->priv().getShaderErrorHandler();
SkSL::String sksl(vshaderTxt.c_str(), vshaderTxt.size());
SkSL::Program::Settings settings;
- settings.fCaps = shaderCaps;
SkSL::String glsl;
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(*fGLContext, SkSL::Program::kVertex_Kind,
sksl, settings, &glsl, errorHandler);
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index e490a11..1320403 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -230,7 +230,6 @@
auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler();
const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
SkSL::Program::Settings settings;
- settings.fCaps = this->gpu()->glCaps().shaderCaps();
settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
settings.fSharpenTextures =
this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
@@ -582,8 +581,6 @@
auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
SkSL::Program::Settings settings;
- const GrGLCaps& caps = gpu->glCaps();
- settings.fCaps = caps.shaderCaps();
settings.fSharpenTextures = gpu->getContext()->priv().options().fSharpenMipmappedTextures;
GrPersistentCacheUtils::ShaderMetadata meta;
meta.fSettings = &settings;
@@ -637,6 +634,7 @@
meta.fAttributeNames[i].c_str()));
}
+ const GrGLCaps& caps = gpu->glCaps();
if (meta.fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
GR_GL_CALL(gpu->glInterface(), BindFragDataLocation(programID, 0,
GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index b5b7cf4..4b20c20 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -136,12 +136,12 @@
, fDevice(device)
, fQueue(queue)
, fOutstandingCommandBuffers(sizeof(OutstandingCommandBuffer), kDefaultOutstandingAllocCnt)
- , fCompiler(new SkSL::Compiler())
, fResourceProvider(this)
, fStagingBufferManager(this)
, fDisconnected(false) {
fMtlCaps.reset(new GrMtlCaps(options, fDevice, featureSet));
fCaps = fMtlCaps;
+ fCompiler.reset(new SkSL::Compiler(fMtlCaps->shaderCaps()));
fCurrentCmdBuffer = GrMtlCommandBuffer::Make(fQueue);
}
diff --git a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
index 101b140..b7e9916 100644
--- a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
+++ b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
@@ -393,7 +393,6 @@
this->finalizeShaders();
SkSL::Program::Settings settings;
- settings.fCaps = this->caps()->shaderCaps();
settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures;
SkASSERT(!this->fragColorIsInOut());
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 5e3ce93..6b397f4 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -230,7 +230,7 @@
SkASSERT(!backendContext.fOwnsInstanceAndDevice);
SkASSERT(fMemoryAllocator);
- fCompiler = new SkSL::Compiler();
+ fCompiler = new SkSL::Compiler(fVkCaps->shaderCaps());
fCaps.reset(SkRef(fVkCaps.get()));
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index ea1e4f3..b295cf2 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -215,7 +215,6 @@
VkPipelineShaderStageCreateInfo shaderStageInfo[3];
SkSL::Program::Settings settings;
- settings.fCaps = this->caps()->shaderCaps();
settings.fRTHeightBinding = this->gpu()->vkCaps().getFragmentUniformBinding();
settings.fRTHeightSet = this->gpu()->vkCaps().getFragmentUniformSet();
settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 2529229..0025c95 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -83,8 +83,9 @@
const String* fOldSource;
};
-Compiler::Compiler(Flags flags)
-: fFlags(flags)
+Compiler::Compiler(const ShaderCapsClass* caps, Flags flags)
+: fCaps(caps)
+, fFlags(flags)
, fContext(std::make_shared<Context>())
, fErrorCount(0) {
fRootSymbolTable = std::make_shared<SymbolTable>(this, /*builtin=*/true);
@@ -322,10 +323,11 @@
SkASSERT(fIRGenerator->fCanInline);
fIRGenerator->fCanInline = false;
ParsedModule baseModule = {base, /*fIntrinsics=*/nullptr};
- IRGenerator::IRBundle ir = fIRGenerator->convertProgram(
- kind, &settings, baseModule, /*isBuiltinCode=*/true, source->c_str(), source->length(),
- /*externalValues=*/nullptr);
- LoadedModule module = { std::move(ir.fSymbolTable), std::move(ir.fElements) };
+ IRGenerator::IRBundle ir =
+ fIRGenerator->convertProgram(kind, &settings, &standaloneCaps, baseModule,
+ /*isBuiltinCode=*/true, source->c_str(), source->length(),
+ /*externalValues=*/nullptr);
+ LoadedModule module = {std::move(ir.fSymbolTable), std::move(ir.fElements)};
fIRGenerator->fCanInline = true;
if (this->fErrorCount) {
printf("Unexpected errors: %s\n", this->fErrorText.c_str());
@@ -1575,7 +1577,7 @@
fErrorText = "";
fErrorCount = 0;
- fInliner.reset(fContext.get(), fIRGenerator->fModifiers.get(), &settings);
+ fInliner.reset(fContext.get(), fIRGenerator->fModifiers.get(), &settings, fCaps);
// Not using AutoSource, because caller is likely to call errorText() if we fail to compile
std::unique_ptr<String> textPtr(new String(std::move(text)));
@@ -1587,12 +1589,13 @@
// The Program will take ownership of the pool.
std::unique_ptr<Pool> pool = Pool::Create();
pool->attachToThread();
- IRGenerator::IRBundle ir =
- fIRGenerator->convertProgram(kind, &settings, baseModule, /*isBuiltinCode=*/false,
- textPtr->c_str(), textPtr->size(), externalValues);
+ IRGenerator::IRBundle ir = fIRGenerator->convertProgram(
+ kind, &settings, fCaps, baseModule, /*isBuiltinCode=*/false, textPtr->c_str(),
+ textPtr->size(), externalValues);
auto program = std::make_unique<Program>(kind,
std::move(textPtr),
settings,
+ fCaps,
fContext,
std::move(ir.fElements),
std::move(ir.fModifiers),
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index af145366..56b4d23 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -133,7 +133,7 @@
};
#endif
- Compiler(Flags flags = kNone_Flags);
+ Compiler(const ShaderCapsClass* caps, Flags flags = kNone_Flags);
~Compiler() override;
@@ -263,6 +263,8 @@
Position position(int offset);
+ const ShaderCapsClass* fCaps = nullptr;
+
std::shared_ptr<SymbolTable> fRootSymbolTable;
ParsedModule fRootModule;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index e890fca..0b1242e 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -78,7 +78,7 @@
}
bool GLSLCodeGenerator::usesPrecisionModifiers() const {
- return fProgram.fSettings.fCaps->usesPrecisionModifiers();
+ return fProgram.fCaps->usesPrecisionModifiers();
}
String GLSLCodeGenerator::getTypeName(const Type& type) {
@@ -248,7 +248,7 @@
// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
// Tegra3 compiler bug.
void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
- SkASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
+ SkASSERT(!fProgram.fCaps->canUseMinAndAbsTogether());
String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
this->fFunctionHeader += String(" ") + this->getTypePrecision(absExpr.type()) +
@@ -489,7 +489,7 @@
if (found != fFunctionClasses->end()) {
switch (found->second) {
case FunctionClass::kAbs: {
- if (!fProgram.fSettings.fCaps->emulateAbsIntFunction())
+ if (!fProgram.fCaps->emulateAbsIntFunction())
break;
SkASSERT(arguments.size() == 1);
if (arguments[0]->type() != *fContext.fInt_Type) {
@@ -510,7 +510,7 @@
break;
}
case FunctionClass::kAtan:
- if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
+ if (fProgram.fCaps->mustForceNegatedAtanParamToFloat() &&
arguments.size() == 2 &&
arguments[1]->kind() == Expression::Kind::kPrefix) {
const PrefixExpression& p = (PrefixExpression&) *arguments[1];
@@ -534,22 +534,21 @@
case FunctionClass::kDFdx:
case FunctionClass::kFwidth:
if (!fFoundDerivatives &&
- fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) {
- SkASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport());
- this->writeExtension(
- fProgram.fSettings.fCaps->shaderDerivativeExtensionString());
+ fProgram.fCaps->shaderDerivativeExtensionString()) {
+ SkASSERT(fProgram.fCaps->shaderDerivativeSupport());
+ this->writeExtension(fProgram.fCaps->shaderDerivativeExtensionString());
fFoundDerivatives = true;
}
break;
case FunctionClass::kDeterminant:
- if (!fProgram.fSettings.fCaps->builtinDeterminantSupport()) {
+ if (!fProgram.fCaps->builtinDeterminantSupport()) {
SkASSERT(arguments.size() == 1);
this->writeDeterminantHack(*arguments[0]);
return;
}
break;
case FunctionClass::kFMA:
- if (!fProgram.fSettings.fCaps->builtinFMASupport()) {
+ if (!fProgram.fCaps->builtinFMASupport()) {
SkASSERT(arguments.size() == 3);
this->write("((");
this->writeExpression(*arguments[0], kSequence_Precedence);
@@ -562,7 +561,7 @@
}
break;
case FunctionClass::kFract:
- if (!fProgram.fSettings.fCaps->canUseFractForNegativeValues()) {
+ if (!fProgram.fCaps->canUseFractForNegativeValues()) {
SkASSERT(arguments.size() == 1);
this->write("(0.5 - sign(");
this->writeExpression(*arguments[0], kSequence_Precedence);
@@ -573,21 +572,21 @@
}
break;
case FunctionClass::kInverse:
- if (fProgram.fSettings.fCaps->generation() < k140_GrGLSLGeneration) {
+ if (fProgram.fCaps->generation() < k140_GrGLSLGeneration) {
SkASSERT(arguments.size() == 1);
this->writeInverseHack(*arguments[0]);
return;
}
break;
case FunctionClass::kInverseSqrt:
- if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
+ if (fProgram.fCaps->generation() < k130_GrGLSLGeneration) {
SkASSERT(arguments.size() == 1);
this->writeInverseSqrtHack(*arguments[0]);
return;
}
break;
case FunctionClass::kMin:
- if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()) {
+ if (!fProgram.fCaps->canUseMinAndAbsTogether()) {
SkASSERT(arguments.size() == 2);
if (is_abs(*arguments[0])) {
this->writeMinAbsHack(*arguments[0], *arguments[1]);
@@ -602,7 +601,7 @@
}
break;
case FunctionClass::kPow:
- if (!fProgram.fSettings.fCaps->removePowWithConstantExponent()) {
+ if (!fProgram.fCaps->removePowWithConstantExponent()) {
break;
}
// pow(x, y) on some NVIDIA drivers causes crashes if y is a
@@ -684,7 +683,7 @@
this->write(fTextureFunctionOverride.c_str());
} else {
this->write("texture");
- if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
+ if (fProgram.fCaps->generation() < k130_GrGLSLGeneration) {
this->write(dim);
}
if (proj) {
@@ -695,7 +694,7 @@
break;
}
case FunctionClass::kTranspose:
- if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
+ if (fProgram.fCaps->generation() < k130_GrGLSLGeneration) {
SkASSERT(arguments.size() == 1);
this->writeTransposeHack(*arguments[0]);
return;
@@ -742,7 +741,7 @@
}
void GLSLCodeGenerator::writeFragCoord() {
- if (!fProgram.fSettings.fCaps->canUseFragCoord()) {
+ if (!fProgram.fCaps->canUseFragCoord()) {
if (!fSetupFragCoordWorkaround) {
const char* precision = usesPrecisionModifiers() ? "highp " : "";
fFunctionHeader += precision;
@@ -764,10 +763,9 @@
// declaration varies in earlier GLSL specs. So it is simpler to omit it.
if (!fProgram.fSettings.fFlipY) {
this->write("gl_FragCoord");
- } else if (const char* extension =
- fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) {
+ } else if (const char* extension = fProgram.fCaps->fragCoordConventionsExtensionString()) {
if (!fSetupFragPositionGlobal) {
- if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
+ if (fProgram.fCaps->generation() < k150_GrGLSLGeneration) {
this->writeExtension(extension);
}
fGlobals.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n");
@@ -788,7 +786,7 @@
void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
switch (ref.variable()->modifiers().fLayout.fBuiltin) {
case SK_FRAGCOLOR_BUILTIN:
- if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
+ if (fProgram.fCaps->mustDeclareFragmentShaderOutput()) {
this->write("sk_FragColor");
} else {
this->write("gl_FragColor");
@@ -807,7 +805,7 @@
this->write(fProgram.fSettings.fFlipY ? "(!gl_FrontFacing)" : "gl_FrontFacing");
break;
case SK_SAMPLEMASK_BUILTIN:
- SkASSERT(fProgram.fSettings.fCaps->sampleMaskSupport());
+ SkASSERT(fProgram.fCaps->sampleMaskSupport());
this->write("gl_SampleMask");
break;
case SK_VERTEXID_BUILTIN:
@@ -823,7 +821,7 @@
this->write("gl_InvocationID");
break;
case SK_LASTFRAGCOLOR_BUILTIN:
- this->write(fProgram.fSettings.fCaps->fbFetchColorName());
+ this->write(fProgram.fCaps->fbFetchColorName());
break;
default:
this->write(ref.variable()->name());
@@ -911,7 +909,7 @@
const Expression& left = *b.left();
const Expression& right = *b.right();
Token::Kind op = b.getOperator();
- if (fProgram.fSettings.fCaps->unfoldShortCircuitAsTernary() &&
+ if (fProgram.fCaps->unfoldShortCircuitAsTernary() &&
(op == Token::Kind::TK_LOGICALAND || op == Token::Kind::TK_LOGICALOR)) {
this->writeShortCircuitWorkaroundExpression(b, parentPrecedence);
return;
@@ -926,7 +924,7 @@
left.kind() == Expression::Kind::kFieldAccess &&
is_sk_position((FieldAccess&) left) &&
!right.containsRTAdjust() &&
- !fProgram.fSettings.fCaps->canUseFragCoord();
+ !fProgram.fCaps->canUseFragCoord();
if (positionWorkaround) {
this->write("sk_FragCoord_Workaround = (");
}
@@ -1133,7 +1131,7 @@
this->write("inout ");
} else if (modifiers.fFlags & Modifiers::kIn_Flag) {
if (globalContext &&
- fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
+ fProgram.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
: "varying ");
} else {
@@ -1141,7 +1139,7 @@
}
} else if (modifiers.fFlags & Modifiers::kOut_Flag) {
if (globalContext &&
- fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
+ fProgram.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
this->write("varying ");
} else {
this->write("out ");
@@ -1228,7 +1226,7 @@
if (type == *fContext.fShort_Type || type == *fContext.fUShort_Type ||
type == *fContext.fByte_Type || type == *fContext.fUByte_Type) {
if (fProgram.fSettings.fForceHighPrecision ||
- fProgram.fSettings.fCaps->incompleteShortIntPrecision()) {
+ fProgram.fCaps->incompleteShortIntPrecision()) {
return "highp ";
}
return "mediump ";
@@ -1273,11 +1271,11 @@
this->writeVarInitializer(var.var(), *var.value());
}
if (!fFoundExternalSamplerDecl && var.var().type() == *fContext.fSamplerExternalOES_Type) {
- if (fProgram.fSettings.fCaps->externalTextureExtensionString()) {
- this->writeExtension(fProgram.fSettings.fCaps->externalTextureExtensionString());
+ if (fProgram.fCaps->externalTextureExtensionString()) {
+ this->writeExtension(fProgram.fCaps->externalTextureExtensionString());
}
- if (fProgram.fSettings.fCaps->secondExternalTextureExtensionString()) {
- this->writeExtension(fProgram.fSettings.fCaps->secondExternalTextureExtensionString());
+ if (fProgram.fCaps->secondExternalTextureExtensionString()) {
+ this->writeExtension(fProgram.fCaps->secondExternalTextureExtensionString());
}
fFoundExternalSamplerDecl = true;
}
@@ -1375,7 +1373,7 @@
this->write("; ");
}
if (f.test()) {
- if (fProgram.fSettings.fCaps->addAndTrueToLoopCondition()) {
+ if (fProgram.fCaps->addAndTrueToLoopCondition()) {
std::unique_ptr<Expression> and_true(new BinaryExpression(
-1, f.test()->clone(), Token::Kind::TK_LOGICALAND,
std::make_unique<BoolLiteral>(fContext, -1, true),
@@ -1401,7 +1399,7 @@
}
void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
- if (!fProgram.fSettings.fCaps->rewriteDoWhileLoops()) {
+ if (!fProgram.fCaps->rewriteDoWhileLoops()) {
this->write("do ");
this->writeStatement(*d.statement());
this->write(" while (");
@@ -1487,7 +1485,7 @@
}
void GLSLCodeGenerator::writeHeader() {
- this->write(fProgram.fSettings.fCaps->versionDeclString());
+ this->write(fProgram.fCaps->versionDeclString());
this->writeLine();
}
@@ -1505,7 +1503,7 @@
this->writeVarDeclaration(decl, true);
this->writeLine();
} else if (builtin == SK_FRAGCOLOR_BUILTIN &&
- fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
+ fProgram.fCaps->mustDeclareFragmentShaderOutput()) {
if (fProgram.fSettings.fFragColorIsInOut) {
this->write("inout ");
} else {
@@ -1530,8 +1528,8 @@
case ProgramElement::Kind::kModifiers: {
const Modifiers& modifiers = e.as<ModifiersDeclaration>().modifiers();
if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) {
- if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) {
- this->writeExtension(fProgram.fSettings.fCaps->gsInvocationsExtensionString());
+ if (fProgram.fCaps->gsInvocationsExtensionString()) {
+ this->writeExtension(fProgram.fCaps->gsInvocationsExtensionString());
}
fFoundGSInvocations = true;
}
@@ -1565,8 +1563,8 @@
bool GLSLCodeGenerator::generateCode() {
this->writeHeader();
if (Program::kGeometry_Kind == fProgramKind &&
- fProgram.fSettings.fCaps->geometryShaderExtensionString()) {
- this->writeExtension(fProgram.fSettings.fCaps->geometryShaderExtensionString());
+ fProgram.fCaps->geometryShaderExtensionString()) {
+ this->writeExtension(fProgram.fCaps->geometryShaderExtensionString());
}
OutputStream* rawOut = fOut;
StringStream body;
@@ -1580,7 +1578,7 @@
this->writeInputVars();
write_stringstream(fGlobals, *rawOut);
- if (!fProgram.fSettings.fCaps->canUseFragCoord()) {
+ if (!fProgram.fCaps->canUseFragCoord()) {
Layout layout;
switch (fProgram.fKind) {
case Program::kVertex_Kind: {
@@ -1610,7 +1608,7 @@
this->writeLine("precision mediump float;");
this->writeLine("precision mediump sampler2D;");
if (fFoundExternalSamplerDecl &&
- !fProgram.fSettings.fCaps->noDefaultPrecisionForExternalSamplers()) {
+ !fProgram.fCaps->noDefaultPrecisionForExternalSamplers()) {
this->writeLine("precision mediump samplerExternalOES;");
}
if (fFoundRectSamplerDecl) {
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index a2c07d5..10c5077 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -462,15 +462,15 @@
return nullptr;
}
fInvocations = modifiers.fLayout.fInvocations;
- if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
+ if (fCaps && !fCaps->gsInvocationsSupport()) {
modifiers.fLayout.fInvocations = -1;
if (modifiers.fLayout.description() == "") {
return nullptr;
}
}
}
- if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
- !fSettings->fCaps->gsInvocationsSupport()) {
+ if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fCaps &&
+ !fCaps->gsInvocationsSupport()) {
modifiers.fLayout.fMaxVertices *= fInvocations;
}
return std::make_unique<ModifiersDeclaration>(fModifiers->handle(modifiers));
@@ -1065,8 +1065,7 @@
fSymbolTable->addWithoutOwnership(param);
}
bool needInvocationIDWorkaround = fInvocations != -1 && funcData.fName == "main" &&
- fSettings->fCaps &&
- !fSettings->fCaps->gsInvocationsSupport();
+ fCaps && !fCaps->gsInvocationsSupport();
std::unique_ptr<Block> body = this->convertBlock(*iter);
fCurrentFunction = nullptr;
if (!body) {
@@ -1372,8 +1371,7 @@
case SK_FRAGCOORD_BUILTIN:
fInputs.fFlipY = true;
if (fSettings->fFlipY &&
- (!fSettings->fCaps ||
- !fSettings->fCaps->fragCoordConventionsExtensionString())) {
+ (!fCaps || !fCaps->fragCoordConventionsExtensionString())) {
fInputs.fRTHeight = true;
}
#endif
@@ -2930,6 +2928,7 @@
IRGenerator::IRBundle IRGenerator::convertProgram(
Program::Kind kind,
const Program::Settings* settings,
+ const ShaderCapsClass* caps,
const ParsedModule& base,
bool isBuiltinCode,
const char* text,
@@ -2937,6 +2936,7 @@
const std::vector<std::unique_ptr<ExternalValue>>* externalValues) {
fKind = kind;
fSettings = settings;
+ fCaps = caps;
fSymbolTable = base.fSymbols;
fIntrinsics = base.fIntrinsics.get();
if (fIntrinsics) {
@@ -2953,8 +2953,8 @@
fRTAdjustInterfaceBlock = nullptr;
fCapsMap.clear();
- if (settings->fCaps) {
- fill_caps(*settings->fCaps, &fCapsMap);
+ if (fCaps) {
+ fill_caps(*fCaps, &fCapsMap);
} else {
fCapsMap.insert({String("integerSupport"), Program::Settings::Value(true)});
}
@@ -2964,7 +2964,7 @@
if (kind == Program::kGeometry_Kind && !fIsBuiltinCode) {
// Declare sk_InvocationID programmatically. With invocations support, it's an 'in' builtin.
// If we're applying the workaround, then it's a plain global.
- bool workaround = fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport();
+ bool workaround = fCaps && !fCaps->gsInvocationsSupport();
Modifiers m;
if (!workaround) {
m.fFlags = Modifiers::kIn_Flag;
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 38e254a..50bd236 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -111,6 +111,7 @@
*/
IRBundle convertProgram(Program::Kind kind,
const Program::Settings* settings,
+ const ShaderCapsClass* caps,
const ParsedModule& base,
bool isBuiltinCode,
const char* text,
@@ -217,6 +218,7 @@
Program::Inputs fInputs;
const Program::Settings* fSettings = nullptr;
+ const ShaderCapsClass* fCaps = nullptr;
Program::Kind fKind;
Inliner* fInliner = nullptr;
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index 6f80c20..c64bae1 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -304,10 +304,11 @@
}
void Inliner::reset(const Context* context, ModifiersPool* modifiers,
- const Program::Settings* settings) {
+ const Program::Settings* settings, const ShaderCapsClass* caps) {
fContext = context;
fModifiers = modifiers;
fSettings = settings;
+ fCaps = caps;
fInlineVarCounter = 0;
}
@@ -764,7 +765,7 @@
return false;
}
- if (!fSettings->fCaps || !fSettings->fCaps->canUseDoLoops()) {
+ if (!fCaps || !fCaps->canUseDoLoops()) {
// We don't have do-while loops. We use do-while loops to simulate early returns, so we
// can't inline functions that have an early return.
bool hasEarlyReturn = has_early_return(*functionDef);
diff --git a/src/sksl/SkSLInliner.h b/src/sksl/SkSLInliner.h
index ed6505e..b12a470 100644
--- a/src/sksl/SkSLInliner.h
+++ b/src/sksl/SkSLInliner.h
@@ -38,7 +38,10 @@
public:
Inliner() {}
- void reset(const Context*, ModifiersPool* modifiers, const Program::Settings*);
+ void reset(const Context*,
+ ModifiersPool* modifiers,
+ const Program::Settings*,
+ const ShaderCapsClass* caps);
/**
* Processes the passed-in FunctionCall expression. The FunctionCall expression should be
@@ -90,6 +93,7 @@
const Context* fContext = nullptr;
ModifiersPool* fModifiers = nullptr;
const Program::Settings* fSettings = nullptr;
+ const ShaderCapsClass* fCaps = nullptr;
int fInlineVarCounter = 0;
};
diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp
index 257c059..90bcc12 100644
--- a/src/sksl/SkSLMain.cpp
+++ b/src/sksl/SkSLMain.cpp
@@ -53,7 +53,9 @@
// Given a string containing an SkSL program, searches for a #pragma settings comment, like so:
// /*#pragma settings Default Sharpen*/
// The passed-in Settings object will be updated accordingly. Any number of options can be provided.
-static void detect_shader_settings(const SkSL::String& text, SkSL::Program::Settings* settings) {
+static void detect_shader_settings(const SkSL::String& text,
+ SkSL::Program::Settings* settings,
+ const SkSL::ShaderCapsClass** caps) {
using Factory = SkSL::ShaderCapsFactory;
// Find a matching comment and isolate the name portion.
@@ -75,95 +77,95 @@
if (settingsText.consumeSuffix(" AddAndTrueToLoopCondition")) {
static auto s_addAndTrueCaps = Factory::AddAndTrueToLoopCondition();
- settings->fCaps = s_addAndTrueCaps.get();
+ *caps = s_addAndTrueCaps.get();
}
if (settingsText.consumeSuffix(" BlendModesFailRandomlyForAllZeroVec")) {
static auto s_blendZeroCaps = Factory::BlendModesFailRandomlyForAllZeroVec();
- settings->fCaps = s_blendZeroCaps.get();
+ *caps = s_blendZeroCaps.get();
}
if (settingsText.consumeSuffix(" CannotUseFractForNegativeValues")) {
static auto s_negativeFractCaps = Factory::CannotUseFractForNegativeValues();
- settings->fCaps = s_negativeFractCaps.get();
+ *caps = s_negativeFractCaps.get();
}
if (settingsText.consumeSuffix(" CannotUseFragCoord")) {
static auto s_noFragCoordCaps = Factory::CannotUseFragCoord();
- settings->fCaps = s_noFragCoordCaps.get();
+ *caps = s_noFragCoordCaps.get();
}
if (settingsText.consumeSuffix(" CannotUseMinAndAbsTogether")) {
static auto s_minAbsCaps = Factory::CannotUseMinAndAbsTogether();
- settings->fCaps = s_minAbsCaps.get();
+ *caps = s_minAbsCaps.get();
}
if (settingsText.consumeSuffix(" Default")) {
static auto s_defaultCaps = Factory::Default();
- settings->fCaps = s_defaultCaps.get();
+ *caps = s_defaultCaps.get();
}
if (settingsText.consumeSuffix(" EmulateAbsIntFunction")) {
static auto s_emulateAbsIntCaps = Factory::EmulateAbsIntFunction();
- settings->fCaps = s_emulateAbsIntCaps.get();
+ *caps = s_emulateAbsIntCaps.get();
}
if (settingsText.consumeSuffix(" FragCoordsOld")) {
static auto s_fragCoordsOld = Factory::FragCoordsOld();
- settings->fCaps = s_fragCoordsOld.get();
+ *caps = s_fragCoordsOld.get();
}
if (settingsText.consumeSuffix(" FragCoordsNew")) {
static auto s_fragCoordsNew = Factory::FragCoordsNew();
- settings->fCaps = s_fragCoordsNew.get();
+ *caps = s_fragCoordsNew.get();
}
if (settingsText.consumeSuffix(" GeometryShaderExtensionString")) {
static auto s_geometryExtCaps = Factory::GeometryShaderExtensionString();
- settings->fCaps = s_geometryExtCaps.get();
+ *caps = s_geometryExtCaps.get();
}
if (settingsText.consumeSuffix(" GeometryShaderSupport")) {
static auto s_geometryShaderCaps = Factory::GeometryShaderSupport();
- settings->fCaps = s_geometryShaderCaps.get();
+ *caps = s_geometryShaderCaps.get();
}
if (settingsText.consumeSuffix(" GSInvocationsExtensionString")) {
static auto s_gsInvocationCaps = Factory::GSInvocationsExtensionString();
- settings->fCaps = s_gsInvocationCaps.get();
+ *caps = s_gsInvocationCaps.get();
}
if (settingsText.consumeSuffix(" IncompleteShortIntPrecision")) {
static auto s_incompleteShortIntCaps = Factory::IncompleteShortIntPrecision();
- settings->fCaps = s_incompleteShortIntCaps.get();
+ *caps = s_incompleteShortIntCaps.get();
}
if (settingsText.consumeSuffix(" MustGuardDivisionEvenAfterExplicitZeroCheck")) {
static auto s_div0Caps = Factory::MustGuardDivisionEvenAfterExplicitZeroCheck();
- settings->fCaps = s_div0Caps.get();
+ *caps = s_div0Caps.get();
}
if (settingsText.consumeSuffix(" MustForceNegatedAtanParamToFloat")) {
static auto s_negativeAtanCaps = Factory::MustForceNegatedAtanParamToFloat();
- settings->fCaps = s_negativeAtanCaps.get();
+ *caps = s_negativeAtanCaps.get();
}
if (settingsText.consumeSuffix(" NoGSInvocationsSupport")) {
static auto s_noGSInvocations = Factory::NoGSInvocationsSupport();
- settings->fCaps = s_noGSInvocations.get();
+ *caps = s_noGSInvocations.get();
}
if (settingsText.consumeSuffix(" RemovePowWithConstantExponent")) {
static auto s_powCaps = Factory::RemovePowWithConstantExponent();
- settings->fCaps = s_powCaps.get();
+ *caps = s_powCaps.get();
}
if (settingsText.consumeSuffix(" RewriteDoWhileLoops")) {
static auto s_rewriteLoopCaps = Factory::RewriteDoWhileLoops();
- settings->fCaps = s_rewriteLoopCaps.get();
+ *caps = s_rewriteLoopCaps.get();
}
if (settingsText.consumeSuffix(" ShaderDerivativeExtensionString")) {
static auto s_derivativeCaps = Factory::ShaderDerivativeExtensionString();
- settings->fCaps = s_derivativeCaps.get();
+ *caps = s_derivativeCaps.get();
}
if (settingsText.consumeSuffix(" UnfoldShortCircuitAsTernary")) {
static auto s_ternaryCaps = Factory::UnfoldShortCircuitAsTernary();
- settings->fCaps = s_ternaryCaps.get();
+ *caps = s_ternaryCaps.get();
}
if (settingsText.consumeSuffix(" UsesPrecisionModifiers")) {
static auto s_precisionCaps = Factory::UsesPrecisionModifiers();
- settings->fCaps = s_precisionCaps.get();
+ *caps = s_precisionCaps.get();
}
if (settingsText.consumeSuffix(" Version110")) {
static auto s_version110Caps = Factory::Version110();
- settings->fCaps = s_version110Caps.get();
+ *caps = s_version110Caps.get();
}
if (settingsText.consumeSuffix(" Version450Core")) {
static auto s_version450CoreCaps = Factory::Version450Core();
- settings->fCaps = s_version450CoreCaps.get();
+ *caps = s_version450CoreCaps.get();
}
if (settingsText.consumeSuffix(" FlipY")) {
settings->fFlipY = true;
@@ -240,13 +242,14 @@
}
SkSL::Program::Settings settings;
+ const SkSL::ShaderCapsClass* caps = &SkSL::standaloneCaps;
if (honorSettings) {
- detect_shader_settings(text, &settings);
+ detect_shader_settings(text, &settings, &caps);
}
SkSL::String name(argv[2]);
if (name.endsWith(".spirv")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler;
+ SkSL::Compiler compiler(caps);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
@@ -262,7 +265,7 @@
}
} else if (name.endsWith(".glsl")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler;
+ SkSL::Compiler compiler(caps);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
@@ -278,7 +281,7 @@
}
} else if (name.endsWith(".metal")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler;
+ SkSL::Compiler compiler(caps);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
@@ -294,7 +297,7 @@
}
} else if (name.endsWith(".h")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag);
+ SkSL::Compiler compiler(caps, SkSL::Compiler::kPermitInvalidStaticTests_Flag);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
@@ -311,7 +314,7 @@
}
} else if (name.endsWith(".cpp")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag);
+ SkSL::Compiler compiler(caps, SkSL::Compiler::kPermitInvalidStaticTests_Flag);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
@@ -328,7 +331,7 @@
}
} else if (name.endsWith(".dehydrated.sksl")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler;
+ SkSL::Compiler compiler(caps);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index 879ddba..e6798c6 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -111,11 +111,6 @@
};
};
-#if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU
- const StandaloneShaderCaps* fCaps = &standaloneCaps;
-#else
- const GrShaderCaps* fCaps = nullptr;
-#endif
// if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
// must be flipped.
bool fFlipY = false;
@@ -185,6 +180,7 @@
Program(Kind kind,
std::unique_ptr<String> source,
Settings settings,
+ const ShaderCapsClass* caps,
std::shared_ptr<Context> context,
std::vector<std::unique_ptr<ProgramElement>> elements,
std::unique_ptr<ModifiersPool> modifiers,
@@ -194,6 +190,7 @@
: fKind(kind)
, fSource(std::move(source))
, fSettings(settings)
+ , fCaps(caps)
, fContext(context)
, fSymbols(symbols)
, fPool(std::move(pool))
@@ -220,6 +217,7 @@
Kind fKind;
std::unique_ptr<String> fSource;
Settings fSettings;
+ const ShaderCapsClass* fCaps;
std::shared_ptr<Context> fContext;
// it's important to keep fElements defined after (and thus destroyed before) fSymbols,
// because destroying elements can modify reference counts in symbols