Specialize scale+translate transforms for explicitly sampled FPs.
This is to support using YUV->RGB in more places where we would incur a full 3x3 matrix multiply for each plane in the fragment shader without this. Change-Id: I27c2a403429c36662eba91f61b08e5331ec678b5 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/278356 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
973236fcd4
commit
8d1dcd7d98
@ -62,12 +62,10 @@ public:
|
||||
FPCoordTransformHandler* transformHandler) {
|
||||
for (int i = 0; *transformHandler; ++*transformHandler, ++i) {
|
||||
auto [coordTransform, fp] = transformHandler->get();
|
||||
GrSLType varyingType =
|
||||
coordTransform.matrix().hasPerspective() ? kHalf3_GrSLType : kHalf2_GrSLType;
|
||||
|
||||
SkString matrix;
|
||||
UniformHandle uniformHandle;
|
||||
GrShaderVar fragmentVar;
|
||||
GrShaderVar transformVar;
|
||||
if (fp.isSampledWithExplicitCoords()) {
|
||||
if (coordTransform.isNoOp()) {
|
||||
transformHandler->omitCoordsForCurrCoordTransform();
|
||||
@ -76,19 +74,25 @@ public:
|
||||
const char* name;
|
||||
SkString strUniName;
|
||||
strUniName.printf("CoordTransformMatrix_%d", i);
|
||||
fUniformTransform.push_back().fHandle =
|
||||
uniformHandler
|
||||
->addUniform(kFragment_GrShaderFlag,
|
||||
kFloat3x3_GrSLType,
|
||||
strUniName.c_str(),
|
||||
&name)
|
||||
.toIndex();
|
||||
uniformHandle = fUniformTransform.back().fHandle;
|
||||
matrix = name;
|
||||
auto& uni = fUniformTransform.push_back();
|
||||
if (coordTransform.matrix().isScaleTranslate()) {
|
||||
uni.fType = kFloat4_GrSLType;
|
||||
} else {
|
||||
uni.fType = kFloat3x3_GrSLType;
|
||||
}
|
||||
uni.fHandle = uniformHandler
|
||||
->addUniform(kFragment_GrShaderFlag,
|
||||
uni.fType,
|
||||
strUniName.c_str(),
|
||||
&name)
|
||||
.toIndex();
|
||||
transformVar = uniformHandler->getUniformVariable(uni.fHandle);
|
||||
}
|
||||
} else {
|
||||
SkString strVaryingName;
|
||||
strVaryingName.printf("TransformedCoord_%d", i);
|
||||
GrSLType varyingType = coordTransform.matrix().hasPerspective() ? kHalf3_GrSLType
|
||||
: kHalf2_GrSLType;
|
||||
GrGLSLVarying v(varyingType);
|
||||
#ifdef SK_GL
|
||||
GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*)varyingHandler;
|
||||
@ -100,8 +104,7 @@ public:
|
||||
matrix = matrix_to_sksl(coordTransform.matrix());
|
||||
fragmentVar = {SkString(v.fsIn()), varyingType};
|
||||
}
|
||||
transformHandler->specifyCoordsForCurrCoordTransform(matrix, uniformHandle,
|
||||
fragmentVar);
|
||||
transformHandler->specifyCoordsForCurrCoordTransform(transformVar, fragmentVar);
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +127,14 @@ public:
|
||||
SkMatrix m = GetTransformMatrix(transform, SkMatrix::I());
|
||||
if (!SkMatrixPriv::CheapEqual(fUniformTransform[u].fCurrentValue, m)) {
|
||||
fUniformTransform[u].fCurrentValue = m;
|
||||
pd.setSkMatrix(fUniformTransform[u].fHandle.toIndex(), m);
|
||||
if (fUniformTransform[u].fType == kFloat4_GrSLType) {
|
||||
float values[4] = {m.getScaleX(), m.getTranslateX(),
|
||||
m.getScaleY(), m.getTranslateY()};
|
||||
pd.set4fv(fUniformTransform[u].fHandle.toIndex(), 1, values);
|
||||
} else {
|
||||
SkASSERT(fUniformTransform[u].fType == kFloat3x3_GrSLType);
|
||||
pd.setSkMatrix(fUniformTransform[u].fHandle.toIndex(), m);
|
||||
}
|
||||
}
|
||||
}
|
||||
++u;
|
||||
@ -159,6 +169,7 @@ private:
|
||||
struct TransformUniform {
|
||||
UniformHandle fHandle;
|
||||
SkMatrix fCurrentValue = SkMatrix::InvalidMatrix();
|
||||
GrSLType fType = kVoid_GrSLType;
|
||||
};
|
||||
|
||||
SkTArray<TransformVarying, true> fVaryingTransform;
|
||||
|
@ -11,12 +11,15 @@
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
|
||||
/**
|
||||
* We specialize the vertex code for each of these matrix types.
|
||||
* We specialize the vertex or fragment coord transform code for these matrix types.
|
||||
* Some specializations are only applied when the coord transform is applied in the fragment
|
||||
* shader.
|
||||
*/
|
||||
enum MatrixType {
|
||||
kNone_MatrixType = 0,
|
||||
kNoPersp_MatrixType = 1,
|
||||
kGeneral_MatrixType = 2,
|
||||
kNone_MatrixType = 0, // Used only in FS for explicitly sampled FPs
|
||||
kScaleTranslate_MatrixType = 1, // Used only in FS for explicitly sampled FPs
|
||||
kNoPersp_MatrixType = 2,
|
||||
kGeneral_MatrixType = 3,
|
||||
};
|
||||
|
||||
GrPrimitiveProcessor::GrPrimitiveProcessor(ClassID classID) : GrProcessor(classID) {}
|
||||
@ -35,13 +38,15 @@ uint32_t GrPrimitiveProcessor::computeCoordTransformsKey(const GrFragmentProcess
|
||||
const GrCoordTransform& coordTransform = fp.coordTransform(t);
|
||||
if (fp.isSampledWithExplicitCoords() && coordTransform.isNoOp()) {
|
||||
key = kNone_MatrixType;
|
||||
} else if (coordTransform.matrix().hasPerspective()) {
|
||||
} else if (fp.isSampledWithExplicitCoords() && coordTransform.matrix().isScaleTranslate()) {
|
||||
key = kScaleTranslate_MatrixType;
|
||||
} else if (!coordTransform.matrix().hasPerspective()) {
|
||||
key = kNoPersp_MatrixType;
|
||||
} else {
|
||||
// Note that we can also have homogeneous varyings as a result of a GP local matrix or
|
||||
// homogeneous local coords generated by GP. We're relying on the GP to include any
|
||||
// variability in those in its key.
|
||||
key = kGeneral_MatrixType;
|
||||
} else {
|
||||
key = kNoPersp_MatrixType;
|
||||
}
|
||||
key <<= 2*t;
|
||||
SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Values for array count that have special meaning. We allow 1-sized arrays.git
|
||||
* Values for array count that have special meaning. We allow 1-sized arrays.
|
||||
*/
|
||||
enum {
|
||||
kNonArray = 0, // not an array
|
||||
@ -37,63 +37,50 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Defaults to a non-arry half with no type modifier or layout qualifier.
|
||||
* Defaults to a void with no type modifier or layout qualifier.
|
||||
*/
|
||||
GrShaderVar()
|
||||
: fType(kHalf_GrSLType)
|
||||
, fTypeModifier(kNone_TypeModifier)
|
||||
, fCount(kNonArray)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {
|
||||
}
|
||||
: fType(kVoid_GrSLType)
|
||||
, fTypeModifier(kNone_TypeModifier)
|
||||
, fCount(kNonArray)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS) {}
|
||||
|
||||
GrShaderVar(const SkString& name, GrSLType type, int arrayCount = kNonArray)
|
||||
: fType(type)
|
||||
, fTypeModifier(kNone_TypeModifier)
|
||||
, fCount(arrayCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
|
||||
}
|
||||
: fType(type)
|
||||
, fTypeModifier(kNone_TypeModifier)
|
||||
, fCount(arrayCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {}
|
||||
|
||||
GrShaderVar(const char* name, GrSLType type, int arrayCount = kNonArray)
|
||||
: fType(type)
|
||||
, fTypeModifier(kNone_TypeModifier)
|
||||
, fCount(arrayCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
fUseUniformFloatArrays = USE_UNIFORM_FLOAT_ARRAYS;
|
||||
}
|
||||
: fType(type)
|
||||
, fTypeModifier(kNone_TypeModifier)
|
||||
, fCount(arrayCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {}
|
||||
|
||||
GrShaderVar(const char* name, GrSLType type, TypeModifier typeModifier)
|
||||
: fType(type)
|
||||
, fTypeModifier(typeModifier)
|
||||
, fCount(kNonArray)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
}
|
||||
: fType(type)
|
||||
, fTypeModifier(typeModifier)
|
||||
, fCount(kNonArray)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {}
|
||||
|
||||
GrShaderVar(const char* name, GrSLType type, TypeModifier typeModifier, int arrayCount)
|
||||
: fType(type)
|
||||
, fTypeModifier(typeModifier)
|
||||
, fCount(arrayCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {
|
||||
SkASSERT(kVoid_GrSLType != type);
|
||||
}
|
||||
: fType(type)
|
||||
, fTypeModifier(typeModifier)
|
||||
, fCount(arrayCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(name) {}
|
||||
|
||||
GrShaderVar(const GrShaderVar& that)
|
||||
: fType(that.fType)
|
||||
, fTypeModifier(that.fTypeModifier)
|
||||
, fCount(that.fCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(that.fName)
|
||||
, fLayoutQualifier(that.fLayoutQualifier)
|
||||
, fExtraModifiers(that.fExtraModifiers) {
|
||||
SkASSERT(kVoid_GrSLType != that.getType());
|
||||
}
|
||||
: fType(that.fType)
|
||||
, fTypeModifier(that.fTypeModifier)
|
||||
, fCount(that.fCount)
|
||||
, fUseUniformFloatArrays(USE_UNIFORM_FLOAT_ARRAYS)
|
||||
, fName(that.fName)
|
||||
, fLayoutQualifier(that.fLayoutQualifier)
|
||||
, fExtraModifiers(that.fExtraModifiers) {}
|
||||
|
||||
/**
|
||||
* Sets as a non-array.
|
||||
|
@ -166,9 +166,18 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor
|
||||
if (args.fFp.isSampledWithExplicitCoords() && args.fTransformedCoords.count() > 0) {
|
||||
// we currently only support overriding a single coordinate pair
|
||||
SkASSERT(args.fTransformedCoords.count() == 1);
|
||||
if (args.fTransformedCoords[0].fUniformMatrix.isValid()) {
|
||||
this->codeAppendf("_coords = (%s * float3(_coords, 1)).xy;\n",
|
||||
args.fTransformedCoords[0].fMatrixCode.c_str());
|
||||
const GrShaderVar& transform = args.fTransformedCoords[0].fTransform;
|
||||
switch (transform.getType()) {
|
||||
case kFloat4_GrSLType:
|
||||
this->codeAppendf("_coords = _coords * %s.xz + %s.yw;\n", transform.c_str(),
|
||||
transform.c_str());
|
||||
break;
|
||||
case kFloat3x3_GrSLType:
|
||||
this->codeAppendf("_coords = (%s * float3(_coords, 1)).xy;\n", transform.c_str());
|
||||
break;
|
||||
default:
|
||||
SkASSERT(transform.getType() == kVoid_GrSLType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->codeAppendf("half4 %s;\n", args.fOutputColor);
|
||||
|
@ -80,6 +80,7 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
return std::make_tuple(localCoords, localCoordLength);
|
||||
};
|
||||
|
||||
GrShaderVar transformVar;
|
||||
for (int i = 0; *handler; ++*handler, ++i) {
|
||||
auto [coordTransform, fp] = handler->get();
|
||||
// Add uniform for coord transform matrix.
|
||||
@ -89,10 +90,16 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
strUniName.printf("CoordTransformMatrix_%d", i);
|
||||
auto flag = fp.isSampledWithExplicitCoords() ? kFragment_GrShaderFlag
|
||||
: kVertex_GrShaderFlag;
|
||||
fInstalledTransforms.push_back().fHandle =
|
||||
uniformHandler
|
||||
->addUniform(flag, kFloat3x3_GrSLType, strUniName.c_str(), &matrixName)
|
||||
.toIndex();
|
||||
auto& uni = fInstalledTransforms.push_back();
|
||||
if (fp.isSampledWithExplicitCoords() && coordTransform.matrix().isScaleTranslate() &&
|
||||
localMatrix.isScaleTranslate()) {
|
||||
uni.fType = kFloat4_GrSLType;
|
||||
} else {
|
||||
uni.fType = kFloat3x3_GrSLType;
|
||||
}
|
||||
uni.fHandle =
|
||||
uniformHandler->addUniform(flag, uni.fType, strUniName.c_str(), &matrixName);
|
||||
transformVar = uniformHandler->getUniformVariable(uni.fHandle);
|
||||
} else {
|
||||
// Install a coord transform that will be skipped.
|
||||
fInstalledTransforms.push_back();
|
||||
@ -100,6 +107,7 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
continue;
|
||||
}
|
||||
|
||||
GrShaderVar fsVar;
|
||||
// Add varying if required and register varying and matrix uniform.
|
||||
if (!fp.isSampledWithExplicitCoords()) {
|
||||
auto [localCoordsStr, localCoordLength] = getLocalCoords();
|
||||
@ -112,19 +120,16 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
strVaryingName.printf("TransformedCoords_%d", i);
|
||||
varyingHandler->addVarying(strVaryingName.c_str(), &v);
|
||||
|
||||
SkASSERT(fInstalledTransforms.back().fType == kFloat3x3_GrSLType);
|
||||
if (v.type() == kFloat2_GrSLType) {
|
||||
vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), matrixName,
|
||||
localCoordsStr.c_str());
|
||||
} else {
|
||||
vb->codeAppendf("%s = %s * %s;", v.vsOut(), matrixName, localCoordsStr.c_str());
|
||||
}
|
||||
GrShaderVar fsVar(SkString(v.fsIn()), v.type(), GrShaderVar::kIn_TypeModifier);
|
||||
handler->specifyCoordsForCurrCoordTransform(SkString(matrixName),
|
||||
fInstalledTransforms.back().fHandle, fsVar);
|
||||
} else {
|
||||
handler->specifyCoordsForCurrCoordTransform(SkString(matrixName),
|
||||
fInstalledTransforms.back().fHandle);
|
||||
fsVar = GrShaderVar(SkString(v.fsIn()), v.type(), GrShaderVar::kIn_TypeModifier);
|
||||
}
|
||||
handler->specifyCoordsForCurrCoordTransform(transformVar, fsVar);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +146,14 @@ void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix
|
||||
m = GetTransformMatrix(transform, localMatrix);
|
||||
}
|
||||
if (!SkMatrixPriv::CheapEqual(fInstalledTransforms[i].fCurrentValue, m)) {
|
||||
pdman.setSkMatrix(fInstalledTransforms[i].fHandle.toIndex(), m);
|
||||
if (fInstalledTransforms[i].fType == kFloat4_GrSLType) {
|
||||
float values[4] = {m.getScaleX(), m.getTranslateX(),
|
||||
m.getScaleY(), m.getTranslateY()};
|
||||
pdman.set4fv(fInstalledTransforms[i].fHandle.toIndex(), 1, values);
|
||||
} else {
|
||||
SkASSERT(fInstalledTransforms[i].fType == kFloat3x3_GrSLType);
|
||||
pdman.setSkMatrix(fInstalledTransforms[i].fHandle.toIndex(), m);
|
||||
}
|
||||
fInstalledTransforms[i].fCurrentValue = m;
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ private:
|
||||
|
||||
struct TransformUniform {
|
||||
UniformHandle fHandle;
|
||||
GrSLType fType = kVoid_GrSLType;
|
||||
SkMatrix fCurrentValue = SkMatrix::InvalidMatrix();
|
||||
};
|
||||
|
||||
|
@ -28,21 +28,12 @@ public:
|
||||
using CoordTransformRange = GrFragmentProcessor::PipelineCoordTransformRange;
|
||||
|
||||
struct TransformVar {
|
||||
TransformVar() = default;
|
||||
|
||||
TransformVar(SkString matrixCode,
|
||||
UniformHandle uniformMatrix,
|
||||
GrShaderVar varyingPoint = {})
|
||||
: fMatrixCode(std::move(matrixCode))
|
||||
, fUniformMatrix(uniformMatrix)
|
||||
, fVaryingPoint(varyingPoint) {}
|
||||
|
||||
// a string of SkSL code which resolves to the transformation matrix
|
||||
SkString fMatrixCode;
|
||||
// the variable containing the matrix, if any, otherwise an invalid handle
|
||||
UniformHandle fUniformMatrix;
|
||||
// the transformed coordinate output by the vertex shader and consumed by the fragment
|
||||
// shader
|
||||
// The transform as a variable. This may be a kFloat3x3 matrix or a kFloat4 representing
|
||||
// {scaleX, transX, scaleY, transY}. For explicitly sampled FPs this is visible in the
|
||||
// FS. This is not available for NV_path_rendering with non-explicitly sampled FPs.
|
||||
GrShaderVar fTransform;
|
||||
// The transformed coordinate output by the vertex shader and consumed by the fragment
|
||||
// shader. Only valid for non-explicitly sampled FPs.
|
||||
GrShaderVar fVaryingPoint;
|
||||
};
|
||||
|
||||
@ -69,10 +60,9 @@ public:
|
||||
FPCoordTransformHandler& operator++();
|
||||
|
||||
// 'args' are constructor params to GrShaderVar.
|
||||
template<typename... Args>
|
||||
void specifyCoordsForCurrCoordTransform(Args&&... args) {
|
||||
void specifyCoordsForCurrCoordTransform(GrShaderVar transformVar, GrShaderVar varyingVar) {
|
||||
SkASSERT(!fAddedCoord);
|
||||
fTransformedCoordVars->emplace_back(std::forward<Args>(args)...);
|
||||
fTransformedCoordVars->push_back({transformVar, varyingVar});
|
||||
SkDEBUGCODE(fAddedCoord = true;)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user