remove 'in uniform' support from GrSkSLFP, make rules more clear
Bug: skia: Change-Id: Iaa4d33c1bfb295d87343411ba6aacc8fae68ef9c Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244300 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
403f2955e7
commit
ac18a5ca60
@ -26,7 +26,7 @@ class GrContext;
|
||||
class GrRenderTargetContext;
|
||||
|
||||
const char* SKSL_TEST_SRC = R"(
|
||||
layout(ctype=float) in uniform half b;
|
||||
layout(ctype=float) uniform half b;
|
||||
|
||||
void main(inout half4 color) {
|
||||
color.a = color.r*0.3 + color.g*0.6 + color.b*0.1;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
static const char* RUNTIME_FUNCTIONS_SRC = R"(
|
||||
layout(ctype=SkRect) in uniform half4 gColor;
|
||||
layout(ctype=SkRect) uniform half4 gColor;
|
||||
|
||||
half scale(float x) {
|
||||
return half(x) / 255;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
const char* gProg = R"(
|
||||
layout(ctype=SkRect) in uniform half4 gColor;
|
||||
layout(ctype=SkRect) uniform half4 gColor;
|
||||
|
||||
void main(float x, float y, inout half4 color) {
|
||||
color = half4(half(x)*(1.0/255), half(y)*(1.0/255), gColor.b, 1);
|
||||
|
@ -59,7 +59,7 @@ struct Effect {
|
||||
uint flags;
|
||||
};
|
||||
|
||||
in uniform float dt;
|
||||
uniform float dt;
|
||||
)";
|
||||
|
||||
static const char* kParticleHeader =
|
||||
@ -77,7 +77,7 @@ struct Particle {
|
||||
uint flags;
|
||||
};
|
||||
|
||||
in uniform Effect effect;
|
||||
uniform Effect effect;
|
||||
)";
|
||||
|
||||
static const char* kDefaultEffectCode =
|
||||
|
@ -15,12 +15,12 @@
|
||||
#include "src/gpu/effects/GrSkSLFP.h"
|
||||
|
||||
GR_FP_SRC_STRING SKSL_OVERDRAW_SRC = R"(
|
||||
layout(ctype=SkPMColor) in uniform half4 color0;
|
||||
layout(ctype=SkPMColor) in uniform half4 color1;
|
||||
layout(ctype=SkPMColor) in uniform half4 color2;
|
||||
layout(ctype=SkPMColor) in uniform half4 color3;
|
||||
layout(ctype=SkPMColor) in uniform half4 color4;
|
||||
layout(ctype=SkPMColor) in uniform half4 color5;
|
||||
layout(ctype=SkPMColor) uniform half4 color0;
|
||||
layout(ctype=SkPMColor) uniform half4 color1;
|
||||
layout(ctype=SkPMColor) uniform half4 color2;
|
||||
layout(ctype=SkPMColor) uniform half4 color3;
|
||||
layout(ctype=SkPMColor) uniform half4 color4;
|
||||
layout(ctype=SkPMColor) uniform half4 color5;
|
||||
|
||||
void main(inout half4 color) {
|
||||
half alpha = 255.0 * color.a;
|
||||
|
@ -32,14 +32,14 @@
|
||||
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
|
||||
|
||||
GR_FP_SRC_STRING SKSL_ARITHMETIC_SRC = R"(
|
||||
in uniform float4 k;
|
||||
layout(key) const in bool enforcePMColor;
|
||||
uniform float4 k;
|
||||
in bool enforcePMColor;
|
||||
in fragmentProcessor child;
|
||||
|
||||
void main(inout half4 color) {
|
||||
half4 dst = sample(child);
|
||||
color = saturate(half(k.x) * color * dst + half(k.y) * color + half(k.z) * dst + half(k.w));
|
||||
if (enforcePMColor) {
|
||||
@if (enforcePMColor) {
|
||||
color.rgb = min(color.rgb, color.a);
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
GR_FP_SRC_STRING SKSL_DITHER_SRC = R"(
|
||||
// This controls the range of values added to color channels
|
||||
layout(key) in int rangeType;
|
||||
in int rangeType;
|
||||
|
||||
void main(float x, float y, inout half4 color) {
|
||||
half value;
|
||||
|
@ -34,9 +34,16 @@ GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCap
|
||||
SkSL::VarDeclarations& v = (SkSL::VarDeclarations&) e;
|
||||
for (const auto& varStatement : v.fVars) {
|
||||
const SkSL::Variable& var = *((SkSL::VarDeclaration&) *varStatement).fVar;
|
||||
if (var.fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
|
||||
fInputVars.push_back(&var);
|
||||
if ((var.fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) ||
|
||||
(var.fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag)) {
|
||||
fInAndUniformVars.push_back(&var);
|
||||
}
|
||||
// "in uniform" doesn't make sense outside of .fp files
|
||||
SkASSERT((var.fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) == 0 ||
|
||||
(var.fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) == 0);
|
||||
// "layout(key)" doesn't make sense outside of .fp files; all 'in' variables are
|
||||
// part of the key
|
||||
SkASSERT(!var.fModifiers.fLayout.fKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,7 +58,7 @@ const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key,
|
||||
|
||||
std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap;
|
||||
size_t offset = 0;
|
||||
for (const auto& v : fInputVars) {
|
||||
for (const auto& v : fInAndUniformVars) {
|
||||
SkSL::String name(v->fName);
|
||||
if (&v->fType == fCompiler.context().fInt_Type.get() ||
|
||||
&v->fType == fCompiler.context().fShort_Type.get()) {
|
||||
@ -113,11 +120,12 @@ static SkSL::Layout::CType get_ctype(const SkSL::Context& context, const SkSL::V
|
||||
|
||||
class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLSkSLFP(const SkSL::Context* context, const std::vector<const SkSL::Variable*>* inputVars,
|
||||
GrGLSLSkSLFP(const SkSL::Context* context,
|
||||
const std::vector<const SkSL::Variable*>* inAndUniformVars,
|
||||
SkSL::String glsl, std::vector<SkSL::Compiler::FormatArg> formatArgs,
|
||||
std::vector<SkSL::Compiler::GLSLFunction> functions)
|
||||
: fContext(*context)
|
||||
, fInputVars(*inputVars)
|
||||
, fInAndUniformVars(*inAndUniformVars)
|
||||
, fGLSL(glsl)
|
||||
, fFormatArgs(std::move(formatArgs))
|
||||
, fFunctions(std::move(functions)) {}
|
||||
@ -149,7 +157,7 @@ public:
|
||||
}
|
||||
|
||||
void emitCode(EmitArgs& args) override {
|
||||
for (const auto& v : fInputVars) {
|
||||
for (const auto& v : fInAndUniformVars) {
|
||||
if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag && v->fType !=
|
||||
*fContext.fFragmentProcessor_Type) {
|
||||
fUniformHandles.push_back(args.fUniformHandler->addUniform(
|
||||
@ -230,7 +238,7 @@ public:
|
||||
size_t offset = 0;
|
||||
const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
|
||||
char* inputs = (char*) outer.fInputs.get();
|
||||
for (const auto& v : outer.fFactory->fInputVars) {
|
||||
for (const auto& v : outer.fFactory->fInAndUniformVars) {
|
||||
switch (get_ctype(fContext, *v)) {
|
||||
case SkSL::Layout::CType::kSkPMColor: {
|
||||
float f1 = ((uint8_t*) inputs)[offset++] / 255.0;
|
||||
@ -285,7 +293,7 @@ public:
|
||||
}
|
||||
|
||||
const SkSL::Context& fContext;
|
||||
const std::vector<const SkSL::Variable*>& fInputVars;
|
||||
const std::vector<const SkSL::Variable*>& fInAndUniformVars;
|
||||
// nearly-finished GLSL; still contains printf-style "%s" format tokens
|
||||
const SkSL::String fGLSL;
|
||||
std::vector<SkSL::Compiler::FormatArg> fFormatArgs;
|
||||
@ -386,8 +394,8 @@ GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
|
||||
printf("%s\n", fFactory->fCompiler.errorText().c_str());
|
||||
SkASSERT(false);
|
||||
}
|
||||
return new GrGLSLSkSLFP(specialized->fContext.get(), &fFactory->fInputVars, glsl, formatArgs,
|
||||
functions);
|
||||
return new GrGLSLSkSLFP(specialized->fContext.get(), &fFactory->fInAndUniformVars, glsl,
|
||||
formatArgs, functions);
|
||||
}
|
||||
|
||||
void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
@ -397,13 +405,13 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
size_t offset = 0;
|
||||
char* inputs = (char*) fInputs.get();
|
||||
const SkSL::Context& context = fFactory->fCompiler.context();
|
||||
for (const auto& v : fFactory->fInputVars) {
|
||||
for (const auto& v : fFactory->fInAndUniformVars) {
|
||||
if (&v->fType == context.fFragmentProcessor_Type.get()) {
|
||||
continue;
|
||||
}
|
||||
switch (get_ctype(context, *v)) {
|
||||
case SkSL::Layout::CType::kBool:
|
||||
if (v->fModifiers.fLayout.fKey) {
|
||||
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
|
||||
fKey += inputs[offset];
|
||||
b->add32(inputs[offset]);
|
||||
}
|
||||
@ -411,7 +419,7 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
break;
|
||||
case SkSL::Layout::CType::kInt32: {
|
||||
offset = SkAlign4(offset);
|
||||
if (v->fModifiers.fLayout.fKey) {
|
||||
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
|
||||
fKey += inputs[offset + 0];
|
||||
fKey += inputs[offset + 1];
|
||||
fKey += inputs[offset + 2];
|
||||
@ -423,7 +431,7 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
}
|
||||
case SkSL::Layout::CType::kFloat: {
|
||||
offset = SkAlign4(offset);
|
||||
if (v->fModifiers.fLayout.fKey) {
|
||||
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
|
||||
fKey += inputs[offset + 0];
|
||||
fKey += inputs[offset + 1];
|
||||
fKey += inputs[offset + 2];
|
||||
@ -436,7 +444,7 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
case SkSL::Layout::CType::kSkPMColor:
|
||||
case SkSL::Layout::CType::kSkPMColor4f:
|
||||
case SkSL::Layout::CType::kSkRect:
|
||||
if (v->fModifiers.fLayout.fKey) {
|
||||
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
|
||||
for (size_t i = 0; i < sizeof(float) * 4; ++i) {
|
||||
fKey += inputs[offset + i];
|
||||
}
|
||||
|
@ -40,12 +40,12 @@ public:
|
||||
|
||||
/**
|
||||
* Creates a new fragment processor from an SkSL source string and a struct of inputs to the
|
||||
* program. The input struct's type is derived from the 'in' variables in the SkSL source, so
|
||||
* e.g. the shader:
|
||||
* program. The input struct's type is derived from the 'in' and 'uniform' variables in the SkSL
|
||||
* source, so e.g. the shader:
|
||||
*
|
||||
* in bool dither;
|
||||
* in float x;
|
||||
* in float y;
|
||||
* uniform float x;
|
||||
* uniform float y;
|
||||
* ....
|
||||
*
|
||||
* would expect a pointer to a struct set up like:
|
||||
@ -56,6 +56,24 @@ public:
|
||||
* float y;
|
||||
* };
|
||||
*
|
||||
* While both 'in' and 'uniform' variables go into this struct, the difference between them is
|
||||
* that 'in' variables are statically "baked in" to the generated code, becoming literals,
|
||||
* whereas uniform variables may be changed from invocation to invocation without having to
|
||||
* recompile the shader.
|
||||
*
|
||||
* As the decision of whether to create a new shader or just upload new uniforms all happens
|
||||
* behind the scenes, the difference between the two from an end-user perspective is primarily
|
||||
* in performance: on the one hand, changing the value of an 'in' variable is very expensive
|
||||
* (requiring the compiler to regenerate the code, upload a new shader to the GPU, and so
|
||||
* forth), but on the other hand the compiler can optimize around its value because it is known
|
||||
* at compile time. 'in' variables are therefore suitable for things like flags, where there are
|
||||
* only a few possible values and a known-in-advance value can cause entire chunks of code to
|
||||
* become dead (think static @ifs), while 'uniform's are used for continuous values like colors
|
||||
* and coordinates, where it would be silly to create a separate shader for each possible set of
|
||||
* values. Other than the (significant) performance implications, the only difference between
|
||||
* the two is that 'in' variables can be used in static @if / @switch tests. When in doubt, use
|
||||
* 'uniform'.
|
||||
*
|
||||
* As turning SkSL into GLSL / SPIR-V / etc. is fairly expensive, and the output may differ
|
||||
* based on the inputs, internally the process is divided into two steps: we first parse and
|
||||
* semantically analyze the SkSL into an internal representation, and then "specialize" this
|
||||
@ -174,7 +192,7 @@ public:
|
||||
|
||||
std::shared_ptr<SkSL::Program> fBaseProgram;
|
||||
|
||||
std::vector<const SkSL::Variable*> fInputVars;
|
||||
std::vector<const SkSL::Variable*> fInAndUniformVars;
|
||||
|
||||
std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations;
|
||||
|
||||
|
@ -66,7 +66,12 @@ bool ByteCodeGenerator::generateCode() {
|
||||
if (declVar->fModifiers.fLayout.fBuiltin >= 0) {
|
||||
continue;
|
||||
}
|
||||
if (declVar->fModifiers.fFlags & Modifiers::kIn_Flag) {
|
||||
// if you trip this assert, it means the program has raw 'in' variables. You
|
||||
// should either specialize the program (Compiler::specialize) to bake in the
|
||||
// final values of the 'in' variables, or not use 'in' variables (maybe you
|
||||
// meant to use 'uniform' instead?).
|
||||
SkASSERT(!(declVar->fModifiers.fFlags & Modifiers::kIn_Flag));
|
||||
if (declVar->fModifiers.fFlags & Modifiers::kUniform_Flag) {
|
||||
for (int i = SlotCount(declVar->fType); i > 0; --i) {
|
||||
fOutput->fInputSlots.push_back(fOutput->fGlobalCount++);
|
||||
}
|
||||
|
@ -589,7 +589,7 @@ DEF_TEST(SkSLInterpreterCompound, r) {
|
||||
"}\n"
|
||||
|
||||
// Uniforms, array-of-structs, dynamic indices
|
||||
"in uniform Rect gRects[4];\n"
|
||||
"uniform Rect gRects[4];\n"
|
||||
"Rect get_rect(int i) { return gRects[i]; }\n"
|
||||
|
||||
// Kitchen sink (swizzles, inout, SoAoS)
|
||||
|
Loading…
Reference in New Issue
Block a user