130ba436f04e61d4505fb854d5fc56079636e0788joshualitt/*
230ba436f04e61d4505fb854d5fc56079636e0788joshualitt * Copyright 2014 Google Inc.
330ba436f04e61d4505fb854d5fc56079636e0788joshualitt *
430ba436f04e61d4505fb854d5fc56079636e0788joshualitt * Use of this source code is governed by a BSD-style license that can be
530ba436f04e61d4505fb854d5fc56079636e0788joshualitt * found in the LICENSE file.
630ba436f04e61d4505fb854d5fc56079636e0788joshualitt */
730ba436f04e61d4505fb854d5fc56079636e0788joshualitt
82d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "GrGLSLGeometryShaderBuilder.h"
92d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "GrGLSLProgramBuilder.h"
100eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel#include "GrGLSLVarying.h"
1130ba436f04e61d4505fb854d5fc56079636e0788joshualitt
12276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdaltonstatic const char* input_type_name(GrGLSLGeometryBuilder::InputType in) {
13276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    using InputType = GrGLSLGeometryBuilder::InputType;
14276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    switch (in) {
15276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case InputType::kPoints: return "points";
16276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case InputType::kLines: return "lines";
17276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case InputType::kLinesAdjacency: return "lines_adjacency";
18276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case InputType::kTriangles: return "triangles";
19276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case InputType::kTrianglesAdjacency: return "triangles_adjacency";
20276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    }
21276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    SkFAIL("invalid input type");
22276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    return "unknown_input";
23276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton}
24276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton
25276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdaltonstatic const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) {
26276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    using OutputType = GrGLSLGeometryBuilder::OutputType;
27276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    switch (out) {
28276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case OutputType::kPoints: return "points";
29276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case OutputType::kLineStrip: return "line_strip";
30276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton        case OutputType::kTriangleStrip: return "triangle_strip";
31276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    }
32276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    SkFAIL("invalid output type");
33276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    return "unknown_output";
34276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton}
35276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton
362d721d33aad192cc8a7a1321504b39bdca2a57ceegdanielGrGLSLGeometryBuilder::GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program)
37276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    : INHERITED(program)
382e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    , fNumInvocations(0) {
39276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton}
4030ba436f04e61d4505fb854d5fc56079636e0788joshualitt
41276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdaltonvoid GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
42276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton                                      int numInvocations) {
432e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    SkASSERT(!this->isConfigured());
442e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    fNumInvocations = numInvocations;
452e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
462e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton        maxVertices *= numInvocations;
472e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton        numInvocations = 1;
482e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    }
49276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier);
50276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(),
51276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton                             kIn_InterfaceQualifier);
52276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier);
53276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton    this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(),
54276cc4113a6440b842c0dacb6d668ee3b45a3b7dcsmartdalton                             kOut_InterfaceQualifier);
5530ba436f04e61d4505fb854d5fc56079636e0788joshualitt}
5630ba436f04e61d4505fb854d5fc56079636e0788joshualitt
570eafe79f42e3c675f3c504aed4a41abf511df2b7egdanielvoid GrGLSLGeometryBuilder::onFinalize() {
582e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    SkASSERT(this->isConfigured());
590eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel    fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
602e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    GrShaderVar sk_InvocationID("sk_InvocationID", kInt_GrSLType);
612e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    this->declareGlobal(sk_InvocationID);
622e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    SkASSERT(sk_InvocationID.getName() == SkString("sk_InvocationID"));
632e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
642e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton        SkString invokeFn;
652e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton        this->emitFunction(kVoid_GrSLType, "invoke", 0, nullptr, this->code().c_str(), &invokeFn);
662e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton        this->code().printf("for (sk_InvocationID = 0; sk_InvocationID < %i; ++sk_InvocationID) {"
672e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton                                "%s();"
682e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton                                "EndPrimitive();"
692e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton                            "}", fNumInvocations, invokeFn.c_str());
702e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    } else {
712e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton        this->codePrependf("sk_InvocationID = gl_InvocationID;");
722e777ead127b03a06ccc7dfc983e1b28e1aa2f86csmartdalton    }
7374077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt}
74