From c937bc50250d7723843471cc0d0dc409fb570229 Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Mon, 9 Dec 2019 12:07:09 -0500 Subject: [PATCH] Improvements to uniform handling in runtime SkSL - Support array uniforms - Fix cases where the read head wasn't aligned in onSetData - Default to float as the CType for half. (half4 was using PMColor, and other half types required a layout(ctype...) Change-Id: I63cb1706071668de0ab80f3d812cd9ad29ff9651 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/258808 Reviewed-by: Brian Salomon Commit-Queue: Brian Osman --- gm/runtimeshader.cpp | 2 +- src/gpu/effects/GrSkSLFP.cpp | 257 ++++++++++++++++++----------------- 2 files changed, 137 insertions(+), 122 deletions(-) diff --git a/gm/runtimeshader.cpp b/gm/runtimeshader.cpp index d0e8dc2389..e658da4a0f 100644 --- a/gm/runtimeshader.cpp +++ b/gm/runtimeshader.cpp @@ -23,7 +23,7 @@ #include const char* gProg = R"( - layout(ctype=SkRect) uniform half4 gColor; + 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); diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp index b856fa48a5..9d382819ba 100644 --- a/src/gpu/effects/GrSkSLFP.cpp +++ b/src/gpu/effects/GrSkSLFP.cpp @@ -50,6 +50,15 @@ GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCap } } +static std::tuple strip_array(const SkSL::Type* type) { + int arrayCount = 0; + if (type->kind() == SkSL::Type::kArray_Kind) { + arrayCount = type->columns(); + type = &type->componentType(); + } + return std::make_tuple(type, arrayCount); +} + const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs, size_t inputSize) { const auto& found = fSpecializations.find(key); @@ -60,33 +69,41 @@ const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, std::unordered_map inputMap; size_t offset = 0; for (const auto& v : fInAndUniformVars) { + auto [type, arrayCount] = strip_array(&v->fType); + arrayCount = SkTMax(1, arrayCount); SkSL::String name(v->fName); - if (&v->fType == fCompiler.context().fInt_Type.get() || - &v->fType == fCompiler.context().fShort_Type.get()) { + if (type == fCompiler.context().fInt_Type.get() || + type == fCompiler.context().fShort_Type.get()) { offset = SkAlign4(offset); - int32_t v = *(int32_t*) (((uint8_t*) inputs) + offset); - inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); - offset += sizeof(int32_t); - } else if (&v->fType == fCompiler.context().fFloat_Type.get() || - &v->fType == fCompiler.context().fHalf_Type.get()) { + if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { + int32_t v = *(int32_t*)(((uint8_t*)inputs) + offset); + inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); + } + offset += sizeof(int32_t) * arrayCount; + } else if (type == fCompiler.context().fFloat_Type.get() || + type == fCompiler.context().fHalf_Type.get()) { offset = SkAlign4(offset); - float v = *(float*) (((uint8_t*) inputs) + offset); - inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); - offset += sizeof(float); - } else if (&v->fType == fCompiler.context().fBool_Type.get()) { - bool v = *(((bool*) inputs) + offset); - inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); - offset += sizeof(bool); - } else if (&v->fType == fCompiler.context().fFloat2_Type.get() || - &v->fType == fCompiler.context().fHalf2_Type.get()) { - offset = SkAlign4(offset) + sizeof(float) * 2; - } else if (&v->fType == fCompiler.context().fFloat3_Type.get() || - &v->fType == fCompiler.context().fHalf3_Type.get()) { - offset = SkAlign4(offset) + sizeof(float) * 3; - } else if (&v->fType == fCompiler.context().fFloat4_Type.get() || - &v->fType == fCompiler.context().fHalf4_Type.get()) { - offset = SkAlign4(offset) + sizeof(float) * 4; - } else if (&v->fType == fCompiler.context().fFragmentProcessor_Type.get()) { + if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { + float v = *(float*)(((uint8_t*)inputs) + offset); + inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); + } + offset += sizeof(float) * arrayCount; + } else if (type == fCompiler.context().fBool_Type.get()) { + if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { + bool v = *(((bool*)inputs) + offset); + inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); + } + offset += sizeof(bool) * arrayCount; + } else if (type == fCompiler.context().fFloat2_Type.get() || + type == fCompiler.context().fHalf2_Type.get()) { + offset = SkAlign4(offset) + sizeof(float) * 2 * arrayCount; + } else if (type == fCompiler.context().fFloat3_Type.get() || + type == fCompiler.context().fHalf3_Type.get()) { + offset = SkAlign4(offset) + sizeof(float) * 3 * arrayCount; + } else if (type == fCompiler.context().fFloat4_Type.get() || + type == fCompiler.context().fHalf4_Type.get()) { + offset = SkAlign4(offset) + sizeof(float) * 4 * arrayCount; + } else if (type == fCompiler.context().fFragmentProcessor_Type.get()) { // do nothing } else { printf("can't handle input var: %s\n", SkSL::String(v->fType.fName).c_str()); @@ -105,28 +122,28 @@ const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, return result; } -static SkSL::Layout::CType get_ctype(const SkSL::Context& context, const SkSL::Variable& v) { - SkSL::Layout::CType result = v.fModifiers.fLayout.fCType; - if (result == SkSL::Layout::CType::kDefault) { - if (&v.fType == context.fFloat_Type.get()) { +static std::tuple get_ctype(const SkSL::Context& context, + const SkSL::Variable& v) { + auto [type, arrayCount] = strip_array(&v.fType); + SkSL::Layout::CType result = v.fModifiers.fLayout.fCType; + if (result == SkSL::Layout::CType::kDefault) { + if (type == context.fFloat_Type.get() || type == context.fHalf_Type.get()) { result = SkSL::Layout::CType::kFloat; - } else if (&v.fType == context.fFloat2_Type.get()) { + } else if (type == context.fFloat2_Type.get() || type == context.fHalf2_Type.get()) { result = SkSL::Layout::CType::kFloat2; - } else if (&v.fType == context.fFloat3_Type.get()) { + } else if (type == context.fFloat3_Type.get() || type == context.fHalf3_Type.get()) { result = SkSL::Layout::CType::kFloat3; - } else if (&v.fType == context.fFloat4_Type.get()) { - result = SkSL::Layout::CType::kSkRect; - } else if (&v.fType == context.fHalf4_Type.get()) { - result = SkSL::Layout::CType::kSkPMColor; - } else if (&v.fType == context.fInt_Type.get()) { + } else if (type == context.fFloat4_Type.get() || type == context.fHalf4_Type.get()) { + result = SkSL::Layout::CType::kSkRect; + } else if (type == context.fInt_Type.get()) { result = SkSL::Layout::CType::kInt32; - } else if (&v.fType == context.fBool_Type.get()) { + } else if (type == context.fBool_Type.get()) { result = SkSL::Layout::CType::kBool; } else { - return SkSL::Layout::CType::kDefault; + return std::make_tuple(SkSL::Layout::CType::kDefault, arrayCount); } } - return result; + return std::make_tuple(result, arrayCount); } class GrGLSLSkSLFP : public GrGLSLFragmentProcessor { @@ -241,10 +258,12 @@ public: for (const auto& v : fInAndUniformVars) { if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag && v->fType != *fContext.fFragmentProcessor_Type) { - fUniformHandles.push_back(args.fUniformHandler->addUniform( + auto [type, arrayCount] = strip_array(&v->fType); + fUniformHandles.push_back(args.fUniformHandler->addUniformArray( kFragment_GrShaderFlag, - this->uniformType(v->fType), - SkSL::String(v->fName).c_str())); + this->uniformType(*type), + SkSL::String(v->fName).c_str(), + arrayCount)); } } GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; @@ -278,70 +297,63 @@ public: const GrSkSLFP& outer = _proc.cast(); char* inputs = (char*) outer.fInputs.get(); for (const auto& v : outer.fFactory->fInAndUniformVars) { - switch (get_ctype(fContext, *v)) { + auto [ctype, arrayCount] = get_ctype(fContext, *v); + arrayCount = SkTMax(1, arrayCount); + switch (ctype) { case SkSL::Layout::CType::kSkPMColor: { - float f1 = ((uint8_t*) inputs)[offset++] / 255.0; - float f2 = ((uint8_t*) inputs)[offset++] / 255.0; - float f3 = ((uint8_t*) inputs)[offset++] / 255.0; - float f4 = ((uint8_t*) inputs)[offset++] / 255.0; + offset = SkAlign4(offset); + SkSTArray<4, float, true> f; + for (int i = 0; i < arrayCount * 4; ++i) { + f.push_back(((uint8_t*)inputs)[offset++] / 255.0); + } if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { - pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4); + pdman.set4fv(fUniformHandles[uniformIndex++], arrayCount, f.begin()); } break; } case SkSL::Layout::CType::kFloat2: { offset = SkAlign4(offset); - float f1 = *(float*) (inputs + offset); - offset += sizeof(float); - float f2 = *(float*) (inputs + offset); - offset += sizeof(float); + const float* f = (float*)(inputs + offset); + offset += sizeof(float) * 2 * arrayCount; if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { - pdman.set2f(fUniformHandles[uniformIndex++], f1, f2); + pdman.set2fv(fUniformHandles[uniformIndex++], arrayCount, f); } break; } case SkSL::Layout::CType::kFloat3: { offset = SkAlign4(offset); - float f1 = *(float*) (inputs + offset); - offset += sizeof(float); - float f2 = *(float*) (inputs + offset); - offset += sizeof(float); - float f3 = *(float*) (inputs + offset); - offset += sizeof(float); + const float* f = (float*)(inputs + offset); + offset += sizeof(float) * 3 * arrayCount; if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { - pdman.set3f(fUniformHandles[uniformIndex++], f1, f2, f3); + pdman.set3fv(fUniformHandles[uniformIndex++], arrayCount, f); } break; } case SkSL::Layout::CType::kSkPMColor4f: case SkSL::Layout::CType::kSkRect: { offset = SkAlign4(offset); - float f1 = *(float*) (inputs + offset); - offset += sizeof(float); - float f2 = *(float*) (inputs + offset); - offset += sizeof(float); - float f3 = *(float*) (inputs + offset); - offset += sizeof(float); - float f4 = *(float*) (inputs + offset); - offset += sizeof(float); + const float* f = (float*)(inputs + offset); + offset += sizeof(float) * 4 * arrayCount; if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { - pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4); + pdman.set4fv(fUniformHandles[uniformIndex++], arrayCount, f); } break; } case SkSL::Layout::CType::kInt32: { - int32_t i = *(int32_t*) (inputs + offset); - offset += sizeof(int32_t); + offset = SkAlign4(offset); + int32_t* i = (int32_t*)(inputs + offset); + offset += sizeof(int32_t) * arrayCount; if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { - pdman.set1i(fUniformHandles[uniformIndex++], i); + pdman.set1iv(fUniformHandles[uniformIndex++], arrayCount, i); } break; } case SkSL::Layout::CType::kFloat: { - float f = *(float*) (inputs + offset); - offset += sizeof(float); + offset = SkAlign4(offset); + float* f = (float*)(inputs + offset); + offset += sizeof(float) * arrayCount; if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { - pdman.set1f(fUniformHandles[uniformIndex++], f); + pdman.set1fv(fUniformHandles[uniformIndex++], arrayCount, f); } break; } @@ -476,56 +488,59 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, if (&v->fType == context.fFragmentProcessor_Type.get()) { continue; } - switch (get_ctype(context, *v)) { - case SkSL::Layout::CType::kBool: - if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { - fKey += inputs[offset]; - b->add32(inputs[offset]); + auto [ctype, arrayCount] = get_ctype(context, *v); + for (int idx = 0; idx < SkTMax(1, arrayCount); ++idx) { + switch (ctype) { + case SkSL::Layout::CType::kBool: + if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { + fKey += inputs[offset]; + b->add32(inputs[offset]); + } + ++offset; + break; + case SkSL::Layout::CType::kInt32: { + offset = SkAlign4(offset); + if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { + fKey += inputs[offset + 0]; + fKey += inputs[offset + 1]; + fKey += inputs[offset + 2]; + fKey += inputs[offset + 3]; + b->add32(*(int32_t*)(inputs + offset)); + } + offset += sizeof(int32_t); + break; } - ++offset; - break; - case SkSL::Layout::CType::kInt32: { - offset = SkAlign4(offset); - if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { - fKey += inputs[offset + 0]; - fKey += inputs[offset + 1]; - fKey += inputs[offset + 2]; - fKey += inputs[offset + 3]; - b->add32(*(int32_t*) (inputs + offset)); + case SkSL::Layout::CType::kFloat: { + offset = SkAlign4(offset); + if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { + fKey += inputs[offset + 0]; + fKey += inputs[offset + 1]; + fKey += inputs[offset + 2]; + fKey += inputs[offset + 3]; + b->add32(*(float*)(inputs + offset)); + } + offset += sizeof(float); + break; } - offset += sizeof(int32_t); - break; + case SkSL::Layout::CType::kFloat2: + copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 2, + &offset, &fKey); + break; + case SkSL::Layout::CType::kFloat3: + copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 3, + &offset, &fKey); + break; + case SkSL::Layout::CType::kSkPMColor: + case SkSL::Layout::CType::kSkPMColor4f: + case SkSL::Layout::CType::kSkRect: + copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 4, + &offset, &fKey); + break; + default: + // unsupported input var type + printf("%s\n", SkSL::String(v->fType.fName).c_str()); + SkASSERT(false); } - case SkSL::Layout::CType::kFloat: { - offset = SkAlign4(offset); - if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { - fKey += inputs[offset + 0]; - fKey += inputs[offset + 1]; - fKey += inputs[offset + 2]; - fKey += inputs[offset + 3]; - b->add32(*(float*) (inputs + offset)); - } - offset += sizeof(float); - break; - } - case SkSL::Layout::CType::kFloat2: - copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 2, - &offset, &fKey); - break; - case SkSL::Layout::CType::kFloat3: - copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 3, - &offset, &fKey); - break; - case SkSL::Layout::CType::kSkPMColor: - case SkSL::Layout::CType::kSkPMColor4f: - case SkSL::Layout::CType::kSkRect: - copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 4, - &offset, &fKey); - break; - default: - // unsupported input var type - printf("%s\n", SkSL::String(v->fType.fName).c_str()); - SkASSERT(false); } } }