Convert geometry shaders to operate in Skia device space
Defers the transformation to normalized window coordinates until after
the geometry shader. Merges vertex and a geometry shader builders into
a single compilation unit with a common base class. Updates CCPR
geometry shaders accordingly.
Bug: skia:
Change-Id: If93c90e978b1fdc7120febd05cfb05810fd496b5
Reviewed-on: https://skia-review.googlesource.com/62980
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index cb421ad..8ee9bbd 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -11,15 +11,31 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLUniformHandler.h"
#include "glsl/GrGLSLVarying.h"
-#include "glsl/GrGLSLVertexShaderBuilder.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
- GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
GrGPArgs gpArgs;
this->onEmitCode(args, &gpArgs);
- vBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar, args.fRTAdjustName);
- if (kFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
- kHalf2_GrSLType == gpArgs.fPositionVar.getType()) {
+ SkASSERT(kFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
+ kFloat3_GrSLType == gpArgs.fPositionVar.getType());
+
+ GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
+ if (!args.fGP.willUseGeoShader()) {
+ // Emit the vertex position to the hardware in the normalized window coordinates it expects.
+ vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(), args.fRTAdjustName,
+ gpArgs.fPositionVar.getType());
+ } else {
+ // Since we have a geometry shader, leave the vertex position in Skia device space for now.
+ // The geometry Shader will operate in device space, and then convert the final positions to
+ // normalized hardware window coordinates under the hood, once everything else has finished.
+ vBuilder->codeAppendf("sk_Position = float4(%s", gpArgs.fPositionVar.c_str());
+ if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) {
+ vBuilder->codeAppend(", 0");
+ }
+ vBuilder->codeAppend(", 1);");
+ }
+
+ if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) {
args.fVaryingHandler->setNoPerspective();
}
}
diff --git a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp
deleted file mode 100644
index d9f34c2..0000000
--- a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrGLSLGeometryShaderBuilder.h"
-#include "GrGLSLProgramBuilder.h"
-#include "GrGLSLVarying.h"
-
-static const char* input_type_name(GrGLSLGeometryBuilder::InputType in) {
- using InputType = GrGLSLGeometryBuilder::InputType;
- switch (in) {
- case InputType::kPoints: return "points";
- case InputType::kLines: return "lines";
- case InputType::kLinesAdjacency: return "lines_adjacency";
- case InputType::kTriangles: return "triangles";
- case InputType::kTrianglesAdjacency: return "triangles_adjacency";
- }
- SK_ABORT("invalid input type");
- return "unknown_input";
-}
-
-static const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) {
- using OutputType = GrGLSLGeometryBuilder::OutputType;
- switch (out) {
- case OutputType::kPoints: return "points";
- case OutputType::kLineStrip: return "line_strip";
- case OutputType::kTriangleStrip: return "triangle_strip";
- }
- SK_ABORT("invalid output type");
- return "unknown_output";
-}
-
-GrGLSLGeometryBuilder::GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program)
- : INHERITED(program)
- , fNumInvocations(0) {
-}
-
-void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
- int numInvocations) {
- SkASSERT(!this->isConfigured());
- fNumInvocations = numInvocations;
- this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier);
- this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(),
- kIn_InterfaceQualifier);
- this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier);
- this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(),
- kOut_InterfaceQualifier);
-}
-
-void GrGLSLGeometryBuilder::onFinalize() {
- SkASSERT(this->isConfigured());
- fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
-}
diff --git a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.h b/src/gpu/glsl/GrGLSLGeometryShaderBuilder.h
deleted file mode 100644
index 04be530..0000000
--- a/src/gpu/glsl/GrGLSLGeometryShaderBuilder.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrGLSLGeometryShaderBuilder_DEFINED
-#define GrGLSLGeometryShaderBuilder_DEFINED
-
-#include "GrGLSLShaderBuilder.h"
-
-class GrGLSLVarying;
-
-class GrGLSLGeometryBuilder : public GrGLSLShaderBuilder {
-public:
- GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program);
-
- enum class InputType {
- kPoints,
- kLines,
- kLinesAdjacency,
- kTriangles,
- kTrianglesAdjacency
- };
-
- enum class OutputType {
- kPoints,
- kLineStrip,
- kTriangleStrip
- };
-
- void configure(InputType, OutputType, int maxVertices, int numInvocations = 1);
- bool isConfigured() const { return fNumInvocations; }
-
-private:
- void onFinalize() override;
-
- int fNumInvocations;
-
- friend class GrGLProgramBuilder;
-
- typedef GrGLSLShaderBuilder INHERITED;
-};
-
-#endif
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
index 0cb7e4d..02fa2e7 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
@@ -12,7 +12,7 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLUniformHandler.h"
-#include "glsl/GrGLSLVertexShaderBuilder.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
SkMatrix GrGLSLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
const GrCoordTransform& coordTransform) {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 0457e71..83a437f 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -13,11 +13,10 @@
#include "GrProgramDesc.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "glsl/GrGLSLGeometryShaderBuilder.h"
#include "glsl/GrGLSLPrimitiveProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLUniformHandler.h"
-#include "glsl/GrGLSLVertexShaderBuilder.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
#include "glsl/GrGLSLXferProcessor.h"
class GrShaderVar;
diff --git a/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
new file mode 100644
index 0000000..1cf85f7
--- /dev/null
+++ b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLSLVertexGeoBuilder.h"
+
+#include "GrGLSLProgramBuilder.h"
+#include "GrGLSLVarying.h"
+#include "GrTypes.h"
+
+void GrGLSLVertexGeoBuilder::emitNormalizedSkPosition(SkString* out, const char* devPos,
+ const char* rtAdjustName,
+ GrSLType devPosType) {
+ if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
+ if (kFloat3_GrSLType == devPosType) {
+ const char* p = devPos;
+ out->appendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
+ } else {
+ SkASSERT(kFloat2_GrSLType == devPosType);
+ out->appendf("{float2 _posTmp = %s;", devPos);
+ }
+ out->appendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
+ "sk_Position = float4(_posTmp.x * %s.x + %s.y,"
+ "_posTmp.y * %s.z + %s.w, 0, 1);}",
+ rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName);
+ } else if (kFloat3_GrSLType == devPosType) {
+ out->appendf("sk_Position = float4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
+ devPos, rtAdjustName, devPos, rtAdjustName, devPos);
+ } else {
+ SkASSERT(kFloat2_GrSLType == devPosType);
+ out->appendf("sk_Position = float4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
+ devPos, rtAdjustName, rtAdjustName, devPos, rtAdjustName, rtAdjustName);
+ }
+}
+
+void GrGLSLVertexBuilder::onFinalize() {
+ // We could have the GrGeometryProcessor do this, but its just easier to have it performed
+ // here. If we ever need to set variable pointsize, then we can reinvestigate.
+ if (this->getProgramBuilder()->desc()->header().fHasPointSize) {
+ this->codeAppend("sk_PointSize = 1.0;");
+ }
+ fProgramBuilder->varyingHandler()->getVertexDecls(&this->inputs(), &this->outputs());
+}
+
+static const char* input_type_name(GrGLSLGeometryBuilder::InputType in) {
+ using InputType = GrGLSLGeometryBuilder::InputType;
+ switch (in) {
+ case InputType::kPoints: return "points";
+ case InputType::kLines: return "lines";
+ case InputType::kLinesAdjacency: return "lines_adjacency";
+ case InputType::kTriangles: return "triangles";
+ case InputType::kTrianglesAdjacency: return "triangles_adjacency";
+ }
+ SK_ABORT("invalid input type");
+ return "unknown_input";
+}
+
+static const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) {
+ using OutputType = GrGLSLGeometryBuilder::OutputType;
+ switch (out) {
+ case OutputType::kPoints: return "points";
+ case OutputType::kLineStrip: return "line_strip";
+ case OutputType::kTriangleStrip: return "triangle_strip";
+ }
+ SK_ABORT("invalid output type");
+ return "unknown_output";
+}
+
+void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
+ int numInvocations) {
+ SkASSERT(!this->isConfigured());
+ fNumInvocations = numInvocations;
+ this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier);
+ this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(),
+ kIn_InterfaceQualifier);
+ this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier);
+ this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(),
+ kOut_InterfaceQualifier);
+}
+
+void GrGLSLGeometryBuilder::emitVertex(SkString* out, const char* devPos, const char* rtAdjustName,
+ GrSLType devPosType) {
+ this->emitNormalizedSkPosition(out, devPos, rtAdjustName, devPosType);
+ out->append("EmitVertex();");
+}
+
+void GrGLSLGeometryBuilder::endPrimitive() {
+ this->codeAppend("EndPrimitive();");
+}
+
+void GrGLSLGeometryBuilder::onFinalize() {
+ SkASSERT(this->isConfigured());
+ fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
+}
diff --git a/src/gpu/glsl/GrGLSLVertexGeoBuilder.h b/src/gpu/glsl/GrGLSLVertexGeoBuilder.h
new file mode 100644
index 0000000..c0a55a0
--- /dev/null
+++ b/src/gpu/glsl/GrGLSLVertexGeoBuilder.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLSLVertexGeoBuilder_DEFINED
+#define GrGLSLVertexGeoBuilder_DEFINED
+
+#include "GrGLSLShaderBuilder.h"
+
+/**
+ * Base class for vertex and geometry shader builders. This is the stage that computes input
+ * geometry for the rasterizer.
+ */
+class GrGLSLVertexGeoBuilder : public GrGLSLShaderBuilder {
+protected:
+ GrGLSLVertexGeoBuilder(GrGLSLProgramBuilder* program) : INHERITED(program) {}
+
+ void emitNormalizedSkPosition(const char* devPos, const char* rtAdjustName,
+ GrSLType devPosType = GrSLType::kFloat2_GrSLType) {
+ this->emitNormalizedSkPosition(&this->code(), devPos, rtAdjustName, devPosType);
+ }
+
+ void emitNormalizedSkPosition(SkString* out, const char* devPos, const char* rtAdjustName,
+ GrSLType devPosType = GrSLType::kFloat2_GrSLType);
+
+ friend class GrGLSLGeometryProcessor;
+
+ typedef GrGLSLShaderBuilder INHERITED;
+};
+
+
+class GrGLSLVertexBuilder : public GrGLSLVertexGeoBuilder {
+public:
+ GrGLSLVertexBuilder(GrGLSLProgramBuilder* program) : INHERITED(program) {}
+
+private:
+ void onFinalize() override;
+
+ friend class GrGLProgramBuilder;
+
+ typedef GrGLSLVertexGeoBuilder INHERITED;
+};
+
+
+class GrGLSLGeometryBuilder : public GrGLSLVertexGeoBuilder {
+public:
+ GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program) : INHERITED(program) {}
+
+ enum class InputType {
+ kPoints,
+ kLines,
+ kLinesAdjacency,
+ kTriangles,
+ kTrianglesAdjacency
+ };
+
+ enum class OutputType {
+ kPoints,
+ kLineStrip,
+ kTriangleStrip
+ };
+
+ void configure(InputType, OutputType, int maxVertices, int numInvocations = 1);
+ bool isConfigured() const { return fNumInvocations; }
+
+ void emitVertex(const char* devPos, const char* rtAdjustName,
+ GrSLType devPosType = GrSLType::kFloat2_GrSLType) {
+ this->emitVertex(&this->code(), devPos, rtAdjustName, devPosType);
+ }
+ void emitVertex(SkString* out, const char* devPos, const char* rtAdjustName,
+ GrSLType devPosType = GrSLType::kFloat2_GrSLType);
+
+ void endPrimitive();
+
+private:
+ void onFinalize() override;
+
+ int fNumInvocations = 0;
+
+ friend class GrGLProgramBuilder;
+
+ typedef GrGLSLVertexGeoBuilder INHERITED;
+};
+
+#endif
diff --git a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp b/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
deleted file mode 100644
index 192417c..0000000
--- a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrGLSLVertexShaderBuilder.h"
-#include "glsl/GrGLSLProgramBuilder.h"
-#include "glsl/GrGLSLUniformHandler.h"
-#include "glsl/GrGLSLVarying.h"
-
-GrGLSLVertexBuilder::GrGLSLVertexBuilder(GrGLSLProgramBuilder* program)
- : INHERITED(program) {
-}
-
-void GrGLSLVertexBuilder::transformToNormalizedDeviceSpace(const GrShaderVar& posVar,
- const char* rtAdjustName) {
- // setup RT Uniform
- if (this->getProgramBuilder()->desc()->header().fSnapVerticesToPixelCenters) {
- if (kFloat3_GrSLType == posVar.getType()) {
- const char* p = posVar.c_str();
- this->codeAppendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
- } else {
- SkASSERT(kFloat2_GrSLType == posVar.getType());
- this->codeAppendf("{float2 _posTmp = %s;", posVar.c_str());
- }
- this->codeAppendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
- "sk_Position = float4(_posTmp.x * %s.x + %s.y,"
- "_posTmp.y * %s.z + %s.w, 0, 1);}",
- rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName);
- } else if (kFloat3_GrSLType == posVar.getType()) {
- this->codeAppendf("sk_Position = float4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
- posVar.c_str(), rtAdjustName,
- posVar.c_str(), rtAdjustName,
- posVar.c_str());
- } else {
- SkASSERT(kFloat2_GrSLType == posVar.getType());
- this->codeAppendf("sk_Position = float4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
- posVar.c_str(), rtAdjustName, rtAdjustName,
- posVar.c_str(), rtAdjustName, rtAdjustName);
- }
- // We could have the GrGeometryProcessor do this, but its just easier to have it performed
- // here. If we ever need to set variable pointsize, then we can reinvestigate.
- if (this->getProgramBuilder()->desc()->header().fHasPointSize) {
- this->codeAppend("sk_PointSize = 1.0;");
- }
-}
-
-void GrGLSLVertexBuilder::onFinalize() {
- fProgramBuilder->varyingHandler()->getVertexDecls(&this->inputs(), &this->outputs());
-}
diff --git a/src/gpu/glsl/GrGLSLVertexShaderBuilder.h b/src/gpu/glsl/GrGLSLVertexShaderBuilder.h
deleted file mode 100644
index 5d71565..0000000
--- a/src/gpu/glsl/GrGLSLVertexShaderBuilder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrGLSLVertexShader_DEFINED
-#define GrGLSLVertexShader_DEFINED
-
-#include "GrGLSLShaderBuilder.h"
-#include "GrGeometryProcessor.h"
-
-class GrGLSLVarying;
-
-// Enough precision to represent 1 / 2048 accurately in printf
-#define GR_SIGNIFICANT_POW2_DECIMAL_DIG 11
-
-class GrGLSLVertexBuilder : public GrGLSLShaderBuilder {
-public:
- GrGLSLVertexBuilder(GrGLSLProgramBuilder* program);
-
- void transformToNormalizedDeviceSpace(const GrShaderVar& posVar, const char* rtAdjustName);
-private:
- void onFinalize() override;
-
- friend class GrGLProgramBuilder;
-
- typedef GrGLSLShaderBuilder INHERITED;
-};
-
-#endif