Remove tessellation backdoor in GrGeometryProcessor
Bug: skia:13263, skia:12198 Change-Id: I70988b765dc21e7c8728ea614c0974f9696eac33 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/534203 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
2e1cc9a946
commit
7ace65de40
@ -404,7 +404,6 @@ filegroup(
|
||||
"swizzle.cpp",
|
||||
"tablecolorfilter.cpp",
|
||||
"tallstretchedbitmaps.cpp",
|
||||
"tessellation.cpp",
|
||||
"testgradient.cpp",
|
||||
"texelsubset.cpp",
|
||||
"text_scale_skew.cpp",
|
||||
@ -8658,32 +8657,6 @@ generated_cc_atom(
|
||||
],
|
||||
)
|
||||
|
||||
generated_cc_atom(
|
||||
name = "tessellation_src",
|
||||
srcs = ["tessellation.cpp"],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
":gm_hdr",
|
||||
"//src/core:SkCanvasPriv_hdr",
|
||||
"//src/gpu/ganesh:GrCaps_hdr",
|
||||
"//src/gpu/ganesh:GrDirectContextPriv_hdr",
|
||||
"//src/gpu/ganesh:GrGeometryProcessor_hdr",
|
||||
"//src/gpu/ganesh:GrMemoryPool_hdr",
|
||||
"//src/gpu/ganesh:GrOpFlushState_hdr",
|
||||
"//src/gpu/ganesh:GrOpsRenderPass_hdr",
|
||||
"//src/gpu/ganesh:GrPipeline_hdr",
|
||||
"//src/gpu/ganesh:GrProgramInfo_hdr",
|
||||
"//src/gpu/ganesh:GrRecordingContextPriv_hdr",
|
||||
"//src/gpu/ganesh:GrShaderCaps_hdr",
|
||||
"//src/gpu/ganesh:GrShaderVar_hdr",
|
||||
"//src/gpu/ganesh/glsl:GrGLSLFragmentShaderBuilder_hdr",
|
||||
"//src/gpu/ganesh/glsl:GrGLSLVarying_hdr",
|
||||
"//src/gpu/ganesh/glsl:GrGLSLVertexGeoBuilder_hdr",
|
||||
"//src/gpu/ganesh/ops:GrDrawOp_hdr",
|
||||
"//src/gpu/ganesh/v1:SurfaceDrawContext_v1_hdr",
|
||||
],
|
||||
)
|
||||
|
||||
generated_cc_atom(
|
||||
name = "testgradient_src",
|
||||
srcs = ["testgradient.cpp"],
|
||||
|
@ -1,414 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm/gm.h"
|
||||
|
||||
#include "src/core/SkCanvasPriv.h"
|
||||
#include "src/gpu/ganesh/GrCaps.h"
|
||||
#include "src/gpu/ganesh/GrDirectContextPriv.h"
|
||||
#include "src/gpu/ganesh/GrGeometryProcessor.h"
|
||||
#include "src/gpu/ganesh/GrMemoryPool.h"
|
||||
#include "src/gpu/ganesh/GrOpFlushState.h"
|
||||
#include "src/gpu/ganesh/GrOpsRenderPass.h"
|
||||
#include "src/gpu/ganesh/GrPipeline.h"
|
||||
#include "src/gpu/ganesh/GrProgramInfo.h"
|
||||
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
|
||||
#include "src/gpu/ganesh/GrShaderCaps.h"
|
||||
#include "src/gpu/ganesh/GrShaderVar.h"
|
||||
#include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
|
||||
#include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
|
||||
#include "src/gpu/ganesh/ops/GrDrawOp.h"
|
||||
#include "src/gpu/ganesh/v1/SurfaceDrawContext_v1.h"
|
||||
|
||||
namespace skiagm {
|
||||
|
||||
constexpr static GrGeometryProcessor::Attribute kPositionAttrib =
|
||||
{"position", kFloat3_GrVertexAttribType, SkSLType::kFloat3};
|
||||
|
||||
constexpr static std::array<float, 3> kTri1[3] = {
|
||||
{20.5f,20.5f,1}, {170.5f,280.5f,4}, {320.5f,20.5f,1}};
|
||||
constexpr static std::array<float, 3> kTri2[3] = {
|
||||
{640.5f,280.5f,3}, {490.5f,20.5f,1}, {340.5f,280.5f,6}};
|
||||
constexpr static SkRect kRect = {20.5f, 340.5f, 640.5f, 480.5f};
|
||||
|
||||
constexpr static int kWidth = (int)kRect.fRight + 21;
|
||||
constexpr static int kHeight = (int)kRect.fBottom + 21;
|
||||
|
||||
/**
|
||||
* This is a GPU-backend specific test. It ensures that tessellation works as expected by drawing
|
||||
* several triangles. The test passes as long as the triangle tessellations match the reference
|
||||
* images on gold.
|
||||
*/
|
||||
class TessellationGM : public GpuGM {
|
||||
SkString onShortName() override { return SkString("tessellation"); }
|
||||
SkISize onISize() override { return {kWidth, kHeight}; }
|
||||
DrawResult onDraw(GrRecordingContext*, SkCanvas*, SkString*) override;
|
||||
};
|
||||
|
||||
|
||||
class TessellationTestTriShader : public GrGeometryProcessor {
|
||||
public:
|
||||
TessellationTestTriShader(const SkMatrix& viewMatrix)
|
||||
: GrGeometryProcessor(kTessellationTestTriShader_ClassID), fViewMatrix(viewMatrix) {
|
||||
this->setVertexAttributesWithImplicitOffsets(&kPositionAttrib, 1);
|
||||
this->setWillUseTessellationShaders();
|
||||
}
|
||||
|
||||
private:
|
||||
const char* name() const final { return "TessellationTestTriShader"; }
|
||||
void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const final {}
|
||||
|
||||
class Impl : public ProgramImpl {
|
||||
public:
|
||||
void setData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrShaderCaps&,
|
||||
const GrGeometryProcessor& geomProc) override {
|
||||
pdman.setSkMatrix(fViewMatrixUniform,
|
||||
geomProc.cast<TessellationTestTriShader>().fViewMatrix);
|
||||
}
|
||||
|
||||
private:
|
||||
void onEmitCode(EmitArgs& args, GrGPArgs*) override {
|
||||
args.fVaryingHandler->emitAttributes(args.fGeomProc.cast<TessellationTestTriShader>());
|
||||
const char* viewMatrix;
|
||||
fViewMatrixUniform = args.fUniformHandler->addUniform(
|
||||
nullptr, kVertex_GrShaderFlag, SkSLType::kFloat3x3, "view_matrix", &viewMatrix);
|
||||
args.fVertBuilder->declareGlobal(
|
||||
GrShaderVar("P_", SkSLType::kFloat3, GrShaderVar::TypeModifier::Out));
|
||||
args.fVertBuilder->codeAppendf(R"(
|
||||
P_.xy = (%s * float3(position.xy, 1)).xy;
|
||||
P_.z = position.z;)", viewMatrix);
|
||||
// GrGLProgramBuilder will call writeTess*ShaderGLSL when it is compiling.
|
||||
this->writeFragmentShader(args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
|
||||
}
|
||||
|
||||
SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
|
||||
const char* versionAndExtensionDecls,
|
||||
const GrGLSLUniformHandler&,
|
||||
const GrShaderCaps&) const override {
|
||||
SkString code(versionAndExtensionDecls);
|
||||
code.append(R"(
|
||||
layout(vertices = 3) out;
|
||||
|
||||
in vec3 P_[];
|
||||
out vec3 P[];
|
||||
|
||||
void main() {
|
||||
P[gl_InvocationID] = P_[gl_InvocationID];
|
||||
gl_TessLevelOuter[gl_InvocationID] = P_[gl_InvocationID].z;
|
||||
gl_TessLevelInner[0] = 2.0;
|
||||
})");
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
|
||||
const char* versionAndExtensionDecls,
|
||||
const GrGLSLUniformHandler&,
|
||||
const GrShaderCaps&) const override {
|
||||
SkString code(versionAndExtensionDecls);
|
||||
code.append(R"(
|
||||
layout(triangles, equal_spacing, cw) in;
|
||||
|
||||
uniform vec4 sk_RTAdjust;
|
||||
|
||||
in vec3 P[];
|
||||
out vec3 barycentric_coord;
|
||||
|
||||
void main() {
|
||||
vec2 devcoord = mat3x2(P[0].xy, P[1].xy, P[2].xy) * gl_TessCoord.xyz;
|
||||
devcoord = round(devcoord - .5) + .5; // Make horz and vert lines on px bounds.
|
||||
gl_Position = vec4(devcoord.xy * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);
|
||||
|
||||
float i = 0.0;
|
||||
if (gl_TessCoord.y == 0.0) {
|
||||
i += gl_TessCoord.z * P[1].z;
|
||||
} else {
|
||||
i += P[1].z;
|
||||
if (gl_TessCoord.x == 0.0) {
|
||||
i += gl_TessCoord.y * P[0].z;
|
||||
} else {
|
||||
i += P[0].z;
|
||||
if (gl_TessCoord.z == 0.0) {
|
||||
i += gl_TessCoord.x * P[2].z;
|
||||
} else {
|
||||
barycentric_coord = vec3(0, 1, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = abs(mod(i, 2.0) - 1.0);
|
||||
barycentric_coord = vec3(i, 0, 1.0 - i);
|
||||
})");
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void writeFragmentShader(GrGLSLFPFragmentBuilder* f, const char* color,
|
||||
const char* coverage) {
|
||||
f->declareGlobal(GrShaderVar("barycentric_coord", SkSLType::kFloat3,
|
||||
GrShaderVar::TypeModifier::In));
|
||||
f->codeAppendf(R"(
|
||||
half3 d = half3(1 - barycentric_coord/fwidth(barycentric_coord));
|
||||
half coverage = max(max(d.x, d.y), d.z);
|
||||
half4 %s = half4(0, coverage, coverage, 1);
|
||||
const half4 %s = half4(1);)", color, coverage);
|
||||
}
|
||||
|
||||
GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
|
||||
};
|
||||
|
||||
std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final {
|
||||
return std::make_unique<Impl>();
|
||||
}
|
||||
|
||||
const SkMatrix fViewMatrix;
|
||||
};
|
||||
|
||||
class TessellationTestRectShader : public GrGeometryProcessor {
|
||||
public:
|
||||
TessellationTestRectShader(const SkMatrix& viewMatrix)
|
||||
: GrGeometryProcessor(kTessellationTestTriShader_ClassID), fViewMatrix(viewMatrix) {
|
||||
this->setWillUseTessellationShaders();
|
||||
}
|
||||
|
||||
const char* name() const final { return "TessellationTestRectShader"; }
|
||||
|
||||
void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const final {}
|
||||
|
||||
private:
|
||||
class Impl : public ProgramImpl {
|
||||
public:
|
||||
void setData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrShaderCaps&,
|
||||
const GrGeometryProcessor& geomProc) override {
|
||||
pdman.setSkMatrix(fViewMatrixUniform,
|
||||
geomProc.cast<TessellationTestRectShader>().fViewMatrix);
|
||||
}
|
||||
|
||||
private:
|
||||
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
|
||||
const char* viewMatrix;
|
||||
fViewMatrixUniform = args.fUniformHandler->addUniform(
|
||||
nullptr, kVertex_GrShaderFlag, SkSLType::kFloat3x3, "view_matrix", &viewMatrix);
|
||||
args.fVertBuilder->declareGlobal(
|
||||
GrShaderVar("M_", SkSLType::kFloat3x3, GrShaderVar::TypeModifier::Out));
|
||||
args.fVertBuilder->codeAppendf("M_ = %s;", viewMatrix);
|
||||
// GrGLProgramBuilder will call writeTess*ShaderGLSL when it is compiling.
|
||||
this->writeFragmentShader(args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
|
||||
}
|
||||
|
||||
SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
|
||||
const char* versionAndExtensionDecls,
|
||||
const GrGLSLUniformHandler&,
|
||||
const GrShaderCaps&) const override {
|
||||
SkString code(versionAndExtensionDecls);
|
||||
code.append(R"(
|
||||
layout(vertices = 1) out;
|
||||
|
||||
in mat3 M_[];
|
||||
out mat3 M[];
|
||||
|
||||
void main() {
|
||||
M[gl_InvocationID] = M_[gl_InvocationID];
|
||||
gl_TessLevelInner[0] = 8.0;
|
||||
gl_TessLevelInner[1] = 2.0;
|
||||
gl_TessLevelOuter[0] = 2.0;
|
||||
gl_TessLevelOuter[1] = 8.0;
|
||||
gl_TessLevelOuter[2] = 2.0;
|
||||
gl_TessLevelOuter[3] = 8.0;
|
||||
})");
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
|
||||
const char* versionAndExtensionDecls,
|
||||
const GrGLSLUniformHandler&,
|
||||
const GrShaderCaps&) const override {
|
||||
SkString code(versionAndExtensionDecls);
|
||||
code.appendf(R"(
|
||||
layout(quads, equal_spacing, cw) in;
|
||||
|
||||
uniform vec4 sk_RTAdjust;
|
||||
|
||||
in mat3 M[];
|
||||
out vec4 barycentric_coord;
|
||||
|
||||
void main() {
|
||||
vec4 R = vec4(%f, %f, %f, %f);
|
||||
vec2 localcoord = mix(R.xy, R.zw, gl_TessCoord.xy);
|
||||
vec2 devcoord = (M[0] * vec3(localcoord, 1)).xy;
|
||||
devcoord = round(devcoord - .5) + .5; // Make horz and vert lines on px bounds.
|
||||
gl_Position = vec4(devcoord.xy * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);
|
||||
|
||||
float i = gl_TessCoord.x * 8.0;
|
||||
i = abs(mod(i, 2.0) - 1.0);
|
||||
if (gl_TessCoord.y == 0.0 || gl_TessCoord.y == 1.0) {
|
||||
barycentric_coord = vec4(i, 1.0 - i, 0, 0);
|
||||
} else {
|
||||
barycentric_coord = vec4(0, 0, i, 1.0 - i);
|
||||
}
|
||||
})", kRect.left(), kRect.top(), kRect.right(), kRect.bottom());
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void writeFragmentShader(GrGLSLFPFragmentBuilder* f, const char* color,
|
||||
const char* coverage) {
|
||||
f->declareGlobal(GrShaderVar("barycentric_coord", SkSLType::kFloat4,
|
||||
GrShaderVar::TypeModifier::In));
|
||||
f->codeAppendf(R"(
|
||||
float4 fwidths = fwidth(barycentric_coord);
|
||||
half coverage = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (fwidths[i] != 0) {
|
||||
coverage = half(max(coverage, 1 - barycentric_coord[i]/fwidths[i]));
|
||||
}
|
||||
}
|
||||
half4 %s = half4(coverage, 0, coverage, 1);
|
||||
const half4 %s = half4(1);)", color, coverage);
|
||||
|
||||
}
|
||||
|
||||
GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
|
||||
};
|
||||
|
||||
std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final {
|
||||
return std::make_unique<Impl>();
|
||||
}
|
||||
|
||||
const SkMatrix fViewMatrix;
|
||||
};
|
||||
|
||||
class TessellationTestOp : public GrDrawOp {
|
||||
DEFINE_OP_CLASS_ID
|
||||
|
||||
public:
|
||||
TessellationTestOp(const SkMatrix& viewMatrix, const std::array<float, 3>* triPositions)
|
||||
: GrDrawOp(ClassID()), fViewMatrix(viewMatrix), fTriPositions(triPositions) {
|
||||
this->setBounds(SkRect::MakeIWH(kWidth, kHeight), HasAABloat::kNo, IsHairline::kNo);
|
||||
}
|
||||
|
||||
private:
|
||||
const char* name() const override { return "TessellationTestOp"; }
|
||||
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
|
||||
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
|
||||
return GrProcessorSet::EmptySetAnalysis();
|
||||
}
|
||||
|
||||
void onPrePrepare(GrRecordingContext*,
|
||||
const GrSurfaceProxyView& writeView,
|
||||
GrAppliedClip*,
|
||||
const GrDstProxyView&,
|
||||
GrXferBarrierFlags renderPassXferBarriers,
|
||||
GrLoadOp colorLoadOp) override {}
|
||||
|
||||
void onPrepare(GrOpFlushState* flushState) override {
|
||||
if (fTriPositions) {
|
||||
if (void* vertexData = flushState->makeVertexSpace(sizeof(float) * 3, 3, &fVertexBuffer,
|
||||
&fBaseVertex)) {
|
||||
memcpy(vertexData, fTriPositions, sizeof(float) * 3 * 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
|
||||
GrPipeline pipeline(GrScissorTest::kDisabled, SkBlendMode::kSrc,
|
||||
state->drawOpArgs().writeView().swizzle());
|
||||
int tessellationPatchVertexCount;
|
||||
std::unique_ptr<GrGeometryProcessor> shader;
|
||||
if (fTriPositions) {
|
||||
if (!fVertexBuffer) {
|
||||
return;
|
||||
}
|
||||
tessellationPatchVertexCount = 3;
|
||||
shader = std::make_unique<TessellationTestTriShader>(fViewMatrix);
|
||||
} else {
|
||||
// Use a mismatched number of vertices in the input patch vs output.
|
||||
// (The tessellation control shader will output one vertex per patch.)
|
||||
tessellationPatchVertexCount = 5;
|
||||
shader = std::make_unique<TessellationTestRectShader>(fViewMatrix);
|
||||
}
|
||||
|
||||
GrProgramInfo programInfo(state->caps(), state->writeView(), state->usesMSAASurface(),
|
||||
&pipeline, &GrUserStencilSettings::kUnused,
|
||||
shader.get(), GrPrimitiveType::kPatches,
|
||||
tessellationPatchVertexCount, state->renderPassBarriers(),
|
||||
state->colorLoadOp());
|
||||
|
||||
state->bindPipeline(programInfo, SkRect::MakeIWH(kWidth, kHeight));
|
||||
state->bindBuffers(nullptr, nullptr, std::move(fVertexBuffer));
|
||||
state->draw(tessellationPatchVertexCount, fBaseVertex);
|
||||
}
|
||||
|
||||
const SkMatrix fViewMatrix;
|
||||
const std::array<float, 3>* const fTriPositions;
|
||||
sk_sp<const GrBuffer> fVertexBuffer;
|
||||
int fBaseVertex = 0;
|
||||
};
|
||||
|
||||
|
||||
static SkPath build_outset_triangle(const std::array<float, 3>* tri) {
|
||||
SkPath outset;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
SkPoint p = {tri[i][0], tri[i][1]};
|
||||
SkPoint left = {tri[(i + 2) % 3][0], tri[(i + 2) % 3][1]};
|
||||
SkPoint right = {tri[(i + 1) % 3][0], tri[(i + 1) % 3][1]};
|
||||
SkPoint n0, n1;
|
||||
n0.setNormalize(left.y() - p.y(), p.x() - left.x());
|
||||
n1.setNormalize(p.y() - right.y(), right.x() - p.x());
|
||||
p += (n0 + n1) * 3;
|
||||
if (0 == i) {
|
||||
outset.moveTo(p);
|
||||
} else {
|
||||
outset.lineTo(p);
|
||||
}
|
||||
}
|
||||
return outset;
|
||||
}
|
||||
|
||||
DrawResult TessellationGM::onDraw(GrRecordingContext* rContext,
|
||||
SkCanvas* canvas,
|
||||
SkString* errorMsg) {
|
||||
auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);
|
||||
if (!sdc) {
|
||||
*errorMsg = kErrorMsg_DrawSkippedGpuOnly;
|
||||
return DrawResult::kSkip;
|
||||
}
|
||||
|
||||
if (!rContext->priv().caps()->shaderCaps()->tessellationSupport()) {
|
||||
*errorMsg = "Requires GPU tessellation support.";
|
||||
return DrawResult::kSkip;
|
||||
}
|
||||
if (!rContext->priv().caps()->shaderCaps()->shaderDerivativeSupport()) {
|
||||
*errorMsg = "Requires shader derivatives."
|
||||
"(These are expected to always be present when there is tessellation!!)";
|
||||
return DrawResult::kFail;
|
||||
}
|
||||
|
||||
canvas->clear(SK_ColorBLACK);
|
||||
SkPaint borderPaint;
|
||||
borderPaint.setColor4f({0,1,1,1});
|
||||
borderPaint.setAntiAlias(true);
|
||||
canvas->drawPath(build_outset_triangle(kTri1), borderPaint);
|
||||
canvas->drawPath(build_outset_triangle(kTri2), borderPaint);
|
||||
|
||||
borderPaint.setColor4f({1,0,1,1});
|
||||
canvas->drawRect(kRect.makeOutset(1.5f, 1.5f), borderPaint);
|
||||
|
||||
sdc->addDrawOp(GrOp::Make<TessellationTestOp>(rContext, canvas->getTotalMatrix(), kTri1));
|
||||
sdc->addDrawOp(GrOp::Make<TessellationTestOp>(rContext, canvas->getTotalMatrix(), kTri2));
|
||||
sdc->addDrawOp(GrOp::Make<TessellationTestOp>(rContext, canvas->getTotalMatrix(), nullptr));
|
||||
|
||||
return skiagm::DrawResult::kOk;
|
||||
}
|
||||
|
||||
DEF_GM( return new TessellationGM(); )
|
||||
|
||||
} // namespace skiagm
|
@ -428,7 +428,6 @@ skgpu_v1_gm_sources = [
|
||||
"$_gm/lazytiling.cpp",
|
||||
"$_gm/preservefillrule.cpp",
|
||||
"$_gm/rrects.cpp",
|
||||
"$_gm/tessellation.cpp",
|
||||
"$_gm/texelsubset.cpp",
|
||||
"$_gm/widebuttcaps.cpp",
|
||||
"$_gm/yuvtorgbsubset.cpp",
|
||||
|
@ -79,32 +79,24 @@ ProgramImpl::emitCode(EmitArgs& args, const GrPipeline& pipeline) {
|
||||
GrGPArgs gpArgs;
|
||||
this->onEmitCode(args, &gpArgs);
|
||||
|
||||
GrShaderVar positionVar = gpArgs.fPositionVar;
|
||||
// skia:12198
|
||||
if (args.fGeomProc.willUseTessellationShaders()) {
|
||||
positionVar = {};
|
||||
}
|
||||
FPCoordsMap transformMap = this->collectTransforms(args.fVertBuilder,
|
||||
args.fVaryingHandler,
|
||||
args.fUniformHandler,
|
||||
gpArgs.fLocalCoordShader,
|
||||
gpArgs.fLocalCoordVar,
|
||||
positionVar,
|
||||
gpArgs.fPositionVar,
|
||||
pipeline);
|
||||
|
||||
// Tessellation shaders are temporarily responsible for integrating their own code strings
|
||||
// while we work out full support.
|
||||
if (!args.fGeomProc.willUseTessellationShaders()) {
|
||||
GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
|
||||
// Emit the vertex position to the hardware in the normalized window coordinates it expects.
|
||||
SkASSERT(SkSLType::kFloat2 == gpArgs.fPositionVar.getType() ||
|
||||
SkSLType::kFloat3 == gpArgs.fPositionVar.getType());
|
||||
vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(),
|
||||
gpArgs.fPositionVar.getType());
|
||||
if (SkSLType::kFloat2 == gpArgs.fPositionVar.getType()) {
|
||||
args.fVaryingHandler->setNoPerspective();
|
||||
}
|
||||
GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
|
||||
// Emit the vertex position to the hardware in the normalized window coordinates it expects.
|
||||
SkASSERT(SkSLType::kFloat2 == gpArgs.fPositionVar.getType() ||
|
||||
SkSLType::kFloat3 == gpArgs.fPositionVar.getType());
|
||||
vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(),
|
||||
gpArgs.fPositionVar.getType());
|
||||
if (SkSLType::kFloat2 == gpArgs.fPositionVar.getType()) {
|
||||
args.fVaryingHandler->setNoPerspective();
|
||||
}
|
||||
|
||||
return {transformMap, gpArgs.fLocalCoordVar};
|
||||
}
|
||||
|
||||
|
@ -194,10 +194,6 @@ public:
|
||||
size_t vertexStride() const { return fVertexAttributes.stride(); }
|
||||
size_t instanceStride() const { return fInstanceAttributes.stride(); }
|
||||
|
||||
bool willUseTessellationShaders() const {
|
||||
return fShaders & (kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a key for the transforms owned by an FP based on the shader code that will be
|
||||
* emitted by the primitive processor to implement them.
|
||||
@ -243,9 +239,6 @@ protected:
|
||||
SkASSERT(attrCount >= 0);
|
||||
fInstanceAttributes.initImplicit(attrs, attrCount);
|
||||
}
|
||||
void setWillUseTessellationShaders() {
|
||||
fShaders |= kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag;
|
||||
}
|
||||
void setTextureSamplerCnt(int cnt) {
|
||||
SkASSERT(cnt >= 0);
|
||||
fTextureSamplerCnt = cnt;
|
||||
@ -348,21 +341,6 @@ public:
|
||||
const GrShaderCaps&,
|
||||
const GrGeometryProcessor&) = 0;
|
||||
|
||||
// We use these methods as a temporary back door to inject OpenGL tessellation code. Once
|
||||
// tessellation is supported by SkSL we can remove these.
|
||||
virtual SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
|
||||
const char* versionAndExtensionDecls,
|
||||
const GrGLSLUniformHandler&,
|
||||
const GrShaderCaps&) const {
|
||||
SK_ABORT("Not implemented.");
|
||||
}
|
||||
virtual SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
|
||||
const char* versionAndExtensionDecls,
|
||||
const GrGLSLUniformHandler&,
|
||||
const GrShaderCaps&) const {
|
||||
SK_ABORT("Not implemented.");
|
||||
}
|
||||
|
||||
// GPs that use writeOutputPosition and/or writeLocalCoord must incorporate the matrix type
|
||||
// into their key, and should use this function or one of the other related helpers.
|
||||
static uint32_t ComputeMatrixKey(const GrShaderCaps& caps, const SkMatrix& mat) {
|
||||
|
@ -97,13 +97,6 @@ struct GrShaderCaps : SkSL::ShaderCaps {
|
||||
return fSampleVariablesExtensionString;
|
||||
}
|
||||
|
||||
// NOTE: This is never called since tessellationSupport() always returns false; it will be
|
||||
// removed as more HW tessellation code is deleted.
|
||||
const char* tessellationExtensionString() const {
|
||||
SkASSERT(this->tessellationSupport());
|
||||
return "";
|
||||
}
|
||||
|
||||
int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
|
||||
|
||||
// Maximum number of segments a tessellation edge can be divided into.
|
||||
|
@ -373,44 +373,6 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
|
||||
// This also binds vertex attribute locations.
|
||||
this->computeCountsAndStrides(programID, geomProc, true);
|
||||
|
||||
/*
|
||||
Tessellation Shaders
|
||||
*/
|
||||
if (fProgramInfo.geomProc().willUseTessellationShaders()) {
|
||||
// Tessellation shaders are not currently supported by SkSL. So here, we temporarily
|
||||
// generate GLSL strings directly using back door methods on GrGeometryProcessor, and
|
||||
// pass those raw strings on to the driver.
|
||||
SkString versionAndExtensionDecls;
|
||||
versionAndExtensionDecls.appendf("%s\n", this->shaderCaps()->versionDeclString());
|
||||
if (const char* extensionString = this->shaderCaps()->tessellationExtensionString()) {
|
||||
versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString);
|
||||
}
|
||||
|
||||
SkString tessControlShader =
|
||||
fGPImpl->getTessControlShaderGLSL(geomProc,
|
||||
versionAndExtensionDecls.c_str(),
|
||||
fUniformHandler,
|
||||
*this->shaderCaps());
|
||||
if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
|
||||
GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
|
||||
errorHandler)) {
|
||||
cleanup_program(fGpu, programID, shadersToDelete);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkString tessEvaluationShader =
|
||||
fGPImpl->getTessEvaluationShaderGLSL(geomProc,
|
||||
versionAndExtensionDecls.c_str(),
|
||||
fUniformHandler,
|
||||
*this->shaderCaps());
|
||||
if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
|
||||
GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
|
||||
errorHandler)) {
|
||||
cleanup_program(fGpu, programID, shadersToDelete);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
this->bindProgramResourceLocations(programID);
|
||||
|
||||
{
|
||||
@ -428,14 +390,9 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
|
||||
|
||||
cleanup_shaders(fGpu, shadersToDelete);
|
||||
|
||||
// We temporarily can't cache tessellation shaders while using back door GLSL.
|
||||
//
|
||||
// We also can't cache SkSL or GLSL if we were given a precompiled program, but there's not
|
||||
// We can't cache SkSL or GLSL if we were given a precompiled program, but there's not
|
||||
// much point in doing so.
|
||||
if (!cached && !geomProc.willUseTessellationShaders() && !precompiledProgram) {
|
||||
// FIXME: Remove the check for tessellation shaders in the above 'if' once the back door
|
||||
// GLSL mechanism is removed.
|
||||
(void)&GrGeometryProcessor::ProgramImpl::getTessControlShaderGLSL;
|
||||
if (!cached && !precompiledProgram) {
|
||||
bool isSkSL = false;
|
||||
if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
|
||||
GrContextOptions::ShaderCacheStrategy::kSkSL) {
|
||||
|
@ -79,14 +79,8 @@ bool GrGLSLProgramBuilder::emitAndInstallPrimProc(SkString* outputColor, SkStrin
|
||||
this->nameExpression(outputCoverage, "outputCoverage");
|
||||
|
||||
SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
|
||||
GrShaderFlags rtAdjustVisibility;
|
||||
if (geomProc.willUseTessellationShaders()) {
|
||||
rtAdjustVisibility = kTessEvaluation_GrShaderFlag;
|
||||
} else {
|
||||
rtAdjustVisibility = kVertex_GrShaderFlag;
|
||||
}
|
||||
fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(
|
||||
nullptr, rtAdjustVisibility, SkSLType::kFloat4, SkSL::Compiler::RTADJUST_NAME);
|
||||
nullptr, kVertex_GrShaderFlag, SkSLType::kFloat4, SkSL::Compiler::RTADJUST_NAME);
|
||||
|
||||
fFS.codeAppendf("// Stage %d, %s\n", fStageIndex, geomProc.name());
|
||||
fVS.codeAppendf("// Primitive Processor %s\n", geomProc.name());
|
||||
|
Loading…
Reference in New Issue
Block a user