aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-02-16 16:37:32 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-02-17 22:00:23 +0000
commit52cad15d0b4443b763a7d41ec8d1131a7638f866 (patch)
tree67c5e00fd79130b1c49b93556152cf29480b3a58
parentc12551c1f3f34f50cd58b4e3fb0697c7fe40e8f0 (diff)
sksl support for geometry shaders
BUG=skia: Change-Id: I8541b98aadcf4c2484fef73e2f49be3ee38bc1e2 Reviewed-on: https://skia-review.googlesource.com/8409 Reviewed-by: Ben Wagner <benjaminwagner@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
-rw-r--r--src/sksl/SkSLCompiler.cpp7
-rw-r--r--src/sksl/SkSLCompiler.h2
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.cpp8
-rw-r--r--src/sksl/SkSLMain.cpp4
-rw-r--r--src/sksl/SkSLParser.cpp43
-rw-r--r--src/sksl/SkSLParser.h11
-rw-r--r--src/sksl/SkSLSPIRVCodeGenerator.cpp5
-rw-r--r--src/sksl/ir/SkSLLayout.h72
-rw-r--r--src/sksl/ir/SkSLProgram.h3
-rw-r--r--src/sksl/sksl.include4
-rw-r--r--src/sksl/sksl_geom.include24
-rw-r--r--src/sksl/sksl_vert.include4
-rw-r--r--tests/SkSLGLSLTest.cpp27
13 files changed, 197 insertions, 17 deletions
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 743745ad14..004eab7053 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -37,6 +37,10 @@ static const char* SKSL_FRAG_INCLUDE =
#include "sksl_frag.include"
;
+static const char* SKSL_GEOM_INCLUDE =
+#include "sksl_geom.include"
+;
+
namespace SkSL {
Compiler::Compiler()
@@ -459,6 +463,9 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString t
case Program::kFragment_Kind:
this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
break;
+ case Program::kGeometry_Kind:
+ this->internalConvertProgram(SkString(SKSL_GEOM_INCLUDE), &ignored, &elements);
+ break;
}
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Modifiers::Flag defaultPrecision;
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index f7dcf2b5b9..497d06dd83 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -18,9 +18,11 @@
#include "SkSLIRGenerator.h"
#define SK_FRAGCOLOR_BUILTIN 10001
+#define SK_IN_BUILTIN 10002
#define SK_FRAGCOORD_BUILTIN 15
#define SK_VERTEXID_BUILTIN 5
#define SK_CLIPDISTANCE_BUILTIN 3
+#define SK_INVOCATIONID_BUILTIN 8
namespace SkSL {
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 18cfba79e9..3f5f9d1b39 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -332,6 +332,12 @@ void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
case SK_CLIPDISTANCE_BUILTIN:
this->write("gl_ClipDistance");
break;
+ case SK_IN_BUILTIN:
+ this->write("gl_in");
+ break;
+ case SK_INVOCATIONID_BUILTIN:
+ this->write("gl_InvocationID");
+ break;
default:
this->write(ref.fVariable.fName);
}
@@ -584,7 +590,7 @@ void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
}
void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
- if (intf.fTypeName == "gl_PerVertex") {
+ if (intf.fTypeName == "sk_PerVertex") {
return;
}
this->writeModifiers(intf.fVariable.fModifiers, true);
diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp
index f493b0577d..46e9c18757 100644
--- a/src/sksl/SkSLMain.cpp
+++ b/src/sksl/SkSLMain.cpp
@@ -24,8 +24,10 @@ int main(int argc, const char** argv) {
kind = SkSL::Program::kVertex_Kind;
} else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".frag")) {
kind = SkSL::Program::kFragment_Kind;
+ } else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".geom")) {
+ kind = SkSL::Program::kGeometry_Kind;
} else {
- printf("input filename must end in '.vert' or '.frag'\n");
+ printf("input filename must end in '.vert', '.frag', or '.geom'\n");
exit(1);
}
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 5bffe1e8c3..cc47577e93 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -123,6 +123,15 @@ Parser::Parser(SkString text, SymbolTable& types, ErrorReporter& errors)
fLayoutKeys[SkString("override_coverage")] = kOverrideCoverage_LayoutKey;
fLayoutKeys[SkString("blend_support_all_equations")] = kBlendSupportAllEquations_LayoutKey;
fLayoutKeys[SkString("push_constant")] = kPushConstant_LayoutKey;
+ fLayoutKeys[SkString("points")] = kPoints_LayoutKey;
+ fLayoutKeys[SkString("lines")] = kLines_LayoutKey;
+ fLayoutKeys[SkString("line_strip")] = kLineStrip_LayoutKey;
+ fLayoutKeys[SkString("lines_adjacency")] = kLinesAdjacency_LayoutKey;
+ fLayoutKeys[SkString("triangles")] = kTriangles_LayoutKey;
+ fLayoutKeys[SkString("triangle_strip")] = kTriangleStrip_LayoutKey;
+ fLayoutKeys[SkString("triangles_adjacency")] = kTrianglesAdjacency_LayoutKey;
+ fLayoutKeys[SkString("max_vertices")] = kMaxVertices_LayoutKey;
+ fLayoutKeys[SkString("invocations")] = kInvocations_LayoutKey;
}
Parser::~Parser() {
@@ -570,12 +579,15 @@ Layout Parser::layout() {
bool blendSupportAllEquations = false;
Layout::Format format = Layout::Format::kUnspecified;
bool pushConstant = false;
+ Layout::Primitive primitive = Layout::kUnspecified_Primitive;
+ int maxVertices = -1;
+ int invocations = -1;
if (this->peek().fKind == Token::LAYOUT) {
this->nextToken();
if (!this->expect(Token::LPAREN, "'('")) {
return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
- pushConstant);
+ pushConstant, primitive, maxVertices, invocations);
}
for (;;) {
Token t = this->nextToken();
@@ -615,6 +627,33 @@ Layout Parser::layout() {
case kPushConstant_LayoutKey:
pushConstant = true;
break;
+ case kPoints_LayoutKey:
+ primitive = Layout::kPoints_Primitive;
+ break;
+ case kLines_LayoutKey:
+ primitive = Layout::kLines_Primitive;
+ break;
+ case kLineStrip_LayoutKey:
+ primitive = Layout::kLineStrip_Primitive;
+ break;
+ case kLinesAdjacency_LayoutKey:
+ primitive = Layout::kLinesAdjacency_Primitive;
+ break;
+ case kTriangles_LayoutKey:
+ primitive = Layout::kTriangles_Primitive;
+ break;
+ case kTriangleStrip_LayoutKey:
+ primitive = Layout::kTriangleStrip_Primitive;
+ break;
+ case kTrianglesAdjacency_LayoutKey:
+ primitive = Layout::kTrianglesAdjacency_Primitive;
+ break;
+ case kMaxVertices_LayoutKey:
+ maxVertices = this->layoutInt();
+ break;
+ case kInvocations_LayoutKey:
+ invocations = this->layoutInt();
+ break;
}
} else if (Layout::ReadFormat(t.fText, &format)) {
// AST::ReadFormat stored the result in 'format'.
@@ -633,7 +672,7 @@ Layout Parser::layout() {
}
return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
- pushConstant);
+ pushConstant, primitive, maxVertices, invocations);
}
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index f277745925..78d9933871 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -218,7 +218,16 @@ private:
kOriginUpperLeft_LayoutKey,
kOverrideCoverage_LayoutKey,
kBlendSupportAllEquations_LayoutKey,
- kPushConstant_LayoutKey
+ kPushConstant_LayoutKey,
+ kPoints_LayoutKey,
+ kLines_LayoutKey,
+ kLineStrip_LayoutKey,
+ kLinesAdjacency_LayoutKey,
+ kTriangles_LayoutKey,
+ kTriangleStrip_LayoutKey,
+ kTrianglesAdjacency_LayoutKey,
+ kMaxVertices_LayoutKey,
+ kInvocations_LayoutKey
};
std::unordered_map<SkString, LayoutKey> fLayoutKeys;
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index 0b7da5771b..feb66a60f4 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -1873,7 +1873,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, S
SkString name("sksl_synthetic_uniforms");
Type intfStruct(Position(), name, fields);
Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false, Layout::Format::kUnspecified,
- false);
+ false, Layout::kUnspecified_Primitive, -1, -1);
Variable intfVar(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name,
intfStruct, Variable::kGlobal_Storage);
InterfaceBlock intf(Position(), intfVar, name, SkString(""),
@@ -2859,6 +2859,9 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, SkWStream& ou
case Program::kFragment_Kind:
this->writeWord(SpvExecutionModelFragment, out);
break;
+ case Program::kGeometry_Kind:
+ this->writeWord(SpvExecutionModelGeometry, out);
+ break;
}
this->writeWord(fFunctionMap[main], out);
this->writeString(main->fName.c_str(), out);
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index 75650e271d..5e7ec4486b 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -19,6 +19,17 @@ namespace SkSL {
* layout (location = 0) int x;
*/
struct Layout {
+ enum Primitive {
+ kUnspecified_Primitive = -1,
+ kPoints_Primitive,
+ kLines_Primitive,
+ kLineStrip_Primitive,
+ kLinesAdjacency_Primitive,
+ kTriangles_Primitive,
+ kTriangleStrip_Primitive,
+ kTrianglesAdjacency_Primitive
+ };
+
// These are used by images in GLSL. We only support a subset of what GL supports.
enum class Format {
kUnspecified = -1,
@@ -79,7 +90,8 @@ struct Layout {
Layout(int location, int offset, int binding, int index, int set, int builtin,
int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage,
- bool blendSupportAllEquations, Format format, bool pushconstant)
+ bool blendSupportAllEquations, Format format, bool pushconstant, Primitive primitive,
+ int maxVertices, int invocations)
: fLocation(location)
, fOffset(offset)
, fBinding(binding)
@@ -91,7 +103,10 @@ struct Layout {
, fOverrideCoverage(overrideCoverage)
, fBlendSupportAllEquations(blendSupportAllEquations)
, fFormat(format)
- , fPushConstant(pushconstant) {}
+ , fPushConstant(pushconstant)
+ , fPrimitive(primitive)
+ , fMaxVertices(maxVertices)
+ , fInvocations(invocations) {}
Layout()
: fLocation(-1)
@@ -105,7 +120,10 @@ struct Layout {
, fOverrideCoverage(false)
, fBlendSupportAllEquations(false)
, fFormat(Format::kUnspecified)
- , fPushConstant(false) {}
+ , fPushConstant(false)
+ , fPrimitive(kUnspecified_Primitive)
+ , fMaxVertices(-1)
+ , fInvocations(-1) {}
SkString description() const {
SkString result;
@@ -158,6 +176,46 @@ struct Layout {
result += separator + "push_constant";
separator = ", ";
}
+ switch (fPrimitive) {
+ case kPoints_Primitive:
+ result += separator + "points";
+ separator = ", ";
+ break;
+ case kLines_Primitive:
+ result += separator + "lines";
+ separator = ", ";
+ break;
+ case kLineStrip_Primitive:
+ result += separator + "line_strip";
+ separator = ", ";
+ break;
+ case kLinesAdjacency_Primitive:
+ result += separator + "lines_adjacency";
+ separator = ", ";
+ break;
+ case kTriangles_Primitive:
+ result += separator + "triangles";
+ separator = ", ";
+ break;
+ case kTriangleStrip_Primitive:
+ result += separator + "triangle_strip";
+ separator = ", ";
+ break;
+ case kTrianglesAdjacency_Primitive:
+ result += separator + "triangles_adjacency";
+ separator = ", ";
+ break;
+ case kUnspecified_Primitive:
+ break;
+ }
+ if (fMaxVertices >= 0) {
+ result += separator + "max_vertices = " + to_string(fMaxVertices);
+ separator = ", ";
+ }
+ if (fInvocations >= 0) {
+ result += separator + "invocations = " + to_string(fInvocations);
+ separator = ", ";
+ }
if (result.size() > 0) {
result = "layout (" + result + ")";
}
@@ -175,7 +233,10 @@ struct Layout {
fOriginUpperLeft == other.fOriginUpperLeft &&
fOverrideCoverage == other.fOverrideCoverage &&
fBlendSupportAllEquations == other.fBlendSupportAllEquations &&
- fFormat == other.fFormat;
+ fFormat == other.fFormat &&
+ fPrimitive == other.fPrimitive &&
+ fMaxVertices == other.fMaxVertices &&
+ fInvocations == other.fInvocations;
}
bool operator!=(const Layout& other) const {
@@ -198,6 +259,9 @@ struct Layout {
bool fBlendSupportAllEquations;
Format fFormat;
bool fPushConstant;
+ Primitive fPrimitive;
+ int fMaxVertices;
+ int fInvocations;
};
} // namespace
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index e4a975b279..2ca9372ec4 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -52,7 +52,8 @@ struct Program {
enum Kind {
kFragment_Kind,
- kVertex_Kind
+ kVertex_Kind,
+ kGeometry_Kind
};
Program(Kind kind,
diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include
index fc5e40f87d..11e3710556 100644
--- a/src/sksl/sksl.include
+++ b/src/sksl/sksl.include
@@ -516,10 +516,6 @@ vec4 interpolateAtOffset(vec4 interpolant, vec2 offset);
$genType fwidth($genType p);
$genType fwidthCoarse($genType p);
$genType fwidthFine($genType p);
-void EmitStreamVertex(int stream);
-void EndStreamPrimitive(int stream);
-void EmitVertex();
-void EndPrimitive();
void barrier();
void memoryBarrier();
void memoryBarrierAtomicCounter();
diff --git a/src/sksl/sksl_geom.include b/src/sksl/sksl_geom.include
new file mode 100644
index 0000000000..18e779f330
--- /dev/null
+++ b/src/sksl/sksl_geom.include
@@ -0,0 +1,24 @@
+STRINGIFY(
+
+// defines built-in interfaces supported by SkiaSL geometry shaders
+
+layout(builtin=10002) in sk_PerVertex {
+ layout(builtin=0) vec4 gl_Position;
+ layout(builtin=1) float gl_PointSize;
+ layout(builtin=3) float sk_ClipDistance[];
+} sk_in[];
+
+out sk_PerVertex {
+ layout(builtin=0) vec4 gl_Position;
+ layout(builtin=1) float gl_PointSize;
+ layout(builtin=3) float sk_ClipDistance[];
+};
+
+layout(builtin=8) int sk_InvocationID;
+
+void EmitStreamVertex(int stream);
+void EndStreamPrimitive(int stream);
+void EmitVertex();
+void EndPrimitive();
+
+)
diff --git a/src/sksl/sksl_vert.include b/src/sksl/sksl_vert.include
index b5ccfcb2a3..e7e9d59ea8 100644
--- a/src/sksl/sksl_vert.include
+++ b/src/sksl/sksl_vert.include
@@ -2,8 +2,8 @@ STRINGIFY(
// defines built-in interfaces supported by SkiaSL vertex shaders
-out gl_PerVertex {
- layout(builtin=0) vec4 gl_Position;
+out sk_PerVertex {
+ layout(builtin=0) vec4 gl_Position;
layout(builtin=1) float gl_PointSize;
layout(builtin=3) float sk_ClipDistance[1];
};
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index a57fd9d4fb..a0fdb98dcf 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -750,4 +750,31 @@ DEF_TEST(SkSLArrayTypes, r) {
"}\n");
}
+DEF_TEST(SkSLGeometry, r) {
+ test(r,
+ "layout(points) in;"
+ "layout(invocations = 2) in;"
+ "layout(line_strip, max_vertices = 2) out;"
+ "void main() {"
+ "gl_Position = sk_in[0].gl_Position + vec4(-0.5, 0, 0, sk_InvocationID);"
+ "EmitVertex();"
+ "gl_Position = sk_in[0].gl_Position + vec4(0.5, 0, 0, sk_InvocationID);"
+ "EmitVertex();"
+ "EndPrimitive();"
+ "}",
+ *SkSL::ShaderCapsFactory::Default(),
+ "#version 400\n"
+ "layout (points) in ;\n"
+ "layout (invocations = 2) in ;\n"
+ "layout (line_strip, max_vertices = 2) out ;\n"
+ "void main() {\n"
+ " gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.0, 0.0, float(gl_InvocationID));\n"
+ " EmitVertex();\n"
+ " gl_Position = gl_in[0].gl_Position + vec4(0.5, 0.0, 0.0, float(gl_InvocationID));\n"
+ " EmitVertex();\n"
+ " EndPrimitive();\n"
+ "}\n",
+ SkSL::Program::kGeometry_Kind);
+}
+
#endif