CCPR: Initial semi-optimized vertex shader Impl
TBR=bsalomon@google.com Bug: skia: Change-Id: I24173e146d8c95cec5f29e8cb4fa5e2c28f9a33c Reviewed-on: https://skia-review.googlesource.com/89120 Reviewed-by: Chris Dalton <csmartdalton@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
92c7fa6b00
commit
e3877ce5ce
@ -301,6 +301,7 @@ skia_gpu_sources = [
|
|||||||
"$_src/gpu/ccpr/GrCCPRCoverageOp.h",
|
"$_src/gpu/ccpr/GrCCPRCoverageOp.h",
|
||||||
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.cpp",
|
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.cpp",
|
||||||
"$_src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp",
|
"$_src/gpu/ccpr/GrCCPRCoverageProcessor_GSImpl.cpp",
|
||||||
|
"$_src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp",
|
||||||
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.h",
|
"$_src/gpu/ccpr/GrCCPRCoverageProcessor.h",
|
||||||
"$_src/gpu/ccpr/GrCCPRCubicShader.cpp",
|
"$_src/gpu/ccpr/GrCCPRCubicShader.cpp",
|
||||||
"$_src/gpu/ccpr/GrCCPRCubicShader.h",
|
"$_src/gpu/ccpr/GrCCPRCubicShader.h",
|
||||||
|
@ -236,6 +236,10 @@ void CCPRGeometryView::updateGpuData() {
|
|||||||
GrCCPRGeometry::Verb::kEndClosedContour == verb) {
|
GrCCPRGeometry::Verb::kEndClosedContour == verb) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (GrCCPRGeometry::Verb::kLineTo == verb) {
|
||||||
|
++ptsIdx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
SkASSERT(GrCCPRGeometry::Verb::kMonotonicQuadraticTo == verb);
|
SkASSERT(GrCCPRGeometry::Verb::kMonotonicQuadraticTo == verb);
|
||||||
fTriangleInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0));
|
fTriangleInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0));
|
||||||
ptsIdx += 2;
|
ptsIdx += 2;
|
||||||
@ -251,10 +255,14 @@ void CCPRGeometryView::Op::onExecute(GrOpFlushState* state) {
|
|||||||
GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend() ?
|
GrGLGpu* glGpu = kOpenGL_GrBackend == context->contextPriv().getBackend() ?
|
||||||
static_cast<GrGLGpu*>(state->gpu()) : nullptr;
|
static_cast<GrGLGpu*>(state->gpu()) : nullptr;
|
||||||
|
|
||||||
GrCCPRCoverageProcessor proc(fView->fRenderPass);
|
if (!GrCCPRCoverageProcessor::DoesRenderPass(fView->fRenderPass, *state->caps().shaderCaps())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GrCCPRCoverageProcessor proc(rp, fView->fRenderPass, *state->caps().shaderCaps());
|
||||||
SkDEBUGCODE(proc.enableDebugVisualizations(kDebugBloat);)
|
SkDEBUGCODE(proc.enableDebugVisualizations(kDebugBloat);)
|
||||||
|
|
||||||
SkSTArray<1, GrMesh, true> mesh;
|
SkSTArray<1, GrMesh> mesh;
|
||||||
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fView->fRenderPass)) {
|
if (GrCCPRCoverageProcessor::RenderPassIsCubic(fView->fRenderPass)) {
|
||||||
sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fCubicInstances.count() *
|
sk_sp<GrBuffer> instBuff(rp->createBuffer(fView->fCubicInstances.count() *
|
||||||
sizeof(CubicInstance), kVertex_GrBufferType,
|
sizeof(CubicInstance), kVertex_GrBufferType,
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "GrCCPRCoverageOp.h"
|
#include "GrCCPRCoverageOp.h"
|
||||||
|
|
||||||
|
#include "GrCaps.h"
|
||||||
#include "GrGpuCommandBuffer.h"
|
#include "GrGpuCommandBuffer.h"
|
||||||
#include "GrOnFlushResourceProvider.h"
|
#include "GrOnFlushResourceProvider.h"
|
||||||
#include "GrOpFlushState.h"
|
#include "GrOpFlushState.h"
|
||||||
@ -396,7 +397,7 @@ void GrCCPRCoverageOp::onExecute(GrOpFlushState* flushState) {
|
|||||||
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleHulls,
|
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleHulls,
|
||||||
&PrimitiveTallies::fTriangles);
|
&PrimitiveTallies::fTriangles);
|
||||||
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleEdges,
|
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleEdges,
|
||||||
&PrimitiveTallies::fTriangles);
|
&PrimitiveTallies::fTriangles); // Might get skipped.
|
||||||
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleCorners,
|
this->drawMaskPrimitives(flushState, pipeline, RenderPass::kTriangleCorners,
|
||||||
&PrimitiveTallies::fTriangles);
|
&PrimitiveTallies::fTriangles);
|
||||||
|
|
||||||
@ -419,14 +420,19 @@ void GrCCPRCoverageOp::drawMaskPrimitives(GrOpFlushState* flushState, const GrPi
|
|||||||
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode;
|
using ScissorMode = GrCCPRCoverageOpsBuilder::ScissorMode;
|
||||||
SkASSERT(pipeline.getScissorState().enabled());
|
SkASSERT(pipeline.getScissorState().enabled());
|
||||||
|
|
||||||
|
if (!GrCCPRCoverageProcessor::DoesRenderPass(renderPass, *flushState->caps().shaderCaps())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fMeshesScratchBuffer.reset();
|
fMeshesScratchBuffer.reset();
|
||||||
fDynamicStatesScratchBuffer.reset();
|
fDynamicStatesScratchBuffer.reset();
|
||||||
|
|
||||||
GrCCPRCoverageProcessor proc(renderPass);
|
GrCCPRCoverageProcessor proc(flushState->resourceProvider(), renderPass,
|
||||||
|
*flushState->caps().shaderCaps());
|
||||||
|
|
||||||
if (const int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) {
|
if (int instanceCount = fInstanceCounts[(int)ScissorMode::kNonScissored].*instanceType) {
|
||||||
SkASSERT(instanceCount > 0);
|
SkASSERT(instanceCount > 0);
|
||||||
const int baseInstance = fBaseInstances[(int)ScissorMode::kNonScissored].*instanceType;
|
int baseInstance = fBaseInstances[(int)ScissorMode::kNonScissored].*instanceType;
|
||||||
proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseInstance, &fMeshesScratchBuffer);
|
proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseInstance, &fMeshesScratchBuffer);
|
||||||
fDynamicStatesScratchBuffer.push_back().fScissorRect.setXYWH(0, 0, fDrawBounds.width(),
|
fDynamicStatesScratchBuffer.push_back().fScissorRect.setXYWH(0, 0, fDrawBounds.width(),
|
||||||
fDrawBounds.height());
|
fDrawBounds.height());
|
||||||
|
@ -167,7 +167,7 @@ private:
|
|||||||
const SkTArray<ScissorBatch, true> fScissorBatches;
|
const SkTArray<ScissorBatch, true> fScissorBatches;
|
||||||
const SkISize fDrawBounds;
|
const SkISize fDrawBounds;
|
||||||
|
|
||||||
mutable SkTArray<GrMesh, true> fMeshesScratchBuffer;
|
mutable SkTArray<GrMesh> fMeshesScratchBuffer;
|
||||||
mutable SkTArray<GrPipeline::DynamicState, true> fDynamicStatesScratchBuffer;
|
mutable SkTArray<GrPipeline::DynamicState, true> fDynamicStatesScratchBuffer;
|
||||||
|
|
||||||
friend class GrCCPRCoverageOpsBuilder;
|
friend class GrCCPRCoverageOpsBuilder;
|
||||||
|
@ -11,17 +11,21 @@
|
|||||||
#include "ccpr/GrCCPRCubicShader.h"
|
#include "ccpr/GrCCPRCubicShader.h"
|
||||||
#include "ccpr/GrCCPRQuadraticShader.h"
|
#include "ccpr/GrCCPRQuadraticShader.h"
|
||||||
#include "ccpr/GrCCPRTriangleShader.h"
|
#include "ccpr/GrCCPRTriangleShader.h"
|
||||||
|
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||||
|
|
||||||
void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
void GrCCPRCoverageProcessor::Shader::emitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
SkString* code, const char* position,
|
GrGLSLVarying::Scope scope, SkString* code,
|
||||||
const char* coverage, const char* wind) {
|
const char* position, const char* coverage,
|
||||||
WindHandling windHandling = this->onEmitVaryings(varyingHandler, code, position, coverage,
|
const char* wind) {
|
||||||
wind);
|
SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope);
|
||||||
|
WindHandling windHandling = this->onEmitVaryings(varyingHandler, scope, code, position,
|
||||||
|
coverage, wind);
|
||||||
if (WindHandling::kNotHandled == windHandling) {
|
if (WindHandling::kNotHandled == windHandling) {
|
||||||
|
fWind.reset(kHalf_GrSLType, scope);
|
||||||
varyingHandler->addFlatVarying("wind", &fWind);
|
varyingHandler->addFlatVarying("wind", &fWind);
|
||||||
code->appendf("%s = %s;", fWind.gsOut(), wind);
|
code->appendf("%s = %s;", OutName(fWind), wind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +84,16 @@ int GrCCPRCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentB
|
|||||||
|
|
||||||
void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
|
void GrCCPRCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
|
||||||
GrProcessorKeyBuilder* b) const {
|
GrProcessorKeyBuilder* b) const {
|
||||||
b->add32((int)fRenderPass);
|
int key = (int)fRenderPass << 1;
|
||||||
|
if (Impl::kGeometryShader == fImpl) {
|
||||||
|
key |= 1;
|
||||||
|
}
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
uint32_t bloatBits;
|
||||||
|
memcpy(&bloatBits, &fDebugBloat, 4);
|
||||||
|
b->add32(bloatBits);
|
||||||
|
#endif
|
||||||
|
b->add32(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
|
GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
|
||||||
@ -106,5 +119,6 @@ GrGLSLPrimitiveProcessor* GrCCPRCoverageProcessor::createGLSLInstance(const GrSh
|
|||||||
shader = skstd::make_unique<GrCCPRCubicCornerShader>();
|
shader = skstd::make_unique<GrCCPRCubicCornerShader>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return this->createGSImpl(std::move(shader));
|
return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader))
|
||||||
|
: this->createVSImpl(std::move(shader));
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define GrCCPRCoverageProcessor_DEFINED
|
#define GrCCPRCoverageProcessor_DEFINED
|
||||||
|
|
||||||
#include "GrGeometryProcessor.h"
|
#include "GrGeometryProcessor.h"
|
||||||
|
#include "GrShaderCaps.h"
|
||||||
#include "SkNx.h"
|
#include "SkNx.h"
|
||||||
#include "glsl/GrGLSLGeometryProcessor.h"
|
#include "glsl/GrGLSLGeometryProcessor.h"
|
||||||
#include "glsl/GrGLSLVarying.h"
|
#include "glsl/GrGLSLVarying.h"
|
||||||
@ -52,14 +53,15 @@ public:
|
|||||||
// render pass. Here we enumerate every render pass needed in order to produce a complete
|
// render pass. Here we enumerate every render pass needed in order to produce a complete
|
||||||
// coverage count mask. This is an exhaustive list of all ccpr coverage shaders.
|
// coverage count mask. This is an exhaustive list of all ccpr coverage shaders.
|
||||||
//
|
//
|
||||||
// During a render pass, the "Impl" (currently only GSImpl) generates conservative geometry for
|
// During a render pass, the "Impl" (GSImpl or VSimpl) generates conservative geometry for
|
||||||
// rasterization, and the Shader decides the coverage value at each pixel.
|
// rasterization, and the Shader decides the coverage value at each pixel.
|
||||||
enum class RenderPass {
|
enum class RenderPass {
|
||||||
// For a Hull, the Impl generates a "conservative raster hull" around the input points. This
|
// For a Hull, the Impl generates a "conservative raster hull" around the input points. This
|
||||||
// is the geometry that causes a pixel to be rasterized if it is touched anywhere by the
|
// is the geometry that causes a pixel to be rasterized if it is touched anywhere by the
|
||||||
// input polygon. Initial coverage values sent to the Shader at each vertex will be null.
|
// input polygon. The initial coverage values sent to the Shader at each vertex are either
|
||||||
// Logically, the conservative raster hull is equivalent to the convex hull of pixel size
|
// null, or +1 all around if the Impl combines this pass with kTriangleEdges. Logically,
|
||||||
// boxes centered on each input point.
|
// the conservative raster hull is equivalent to the convex hull of pixel size boxes
|
||||||
|
// centered on each input point.
|
||||||
kTriangleHulls,
|
kTriangleHulls,
|
||||||
kQuadraticHulls,
|
kQuadraticHulls,
|
||||||
kCubicHulls,
|
kCubicHulls,
|
||||||
@ -70,6 +72,9 @@ public:
|
|||||||
// edge geometry and 0 on the inside. This is the only geometry type that associates
|
// edge geometry and 0 on the inside. This is the only geometry type that associates
|
||||||
// coverage values with the output vertices. Interpolated, these coverage values convert
|
// coverage values with the output vertices. Interpolated, these coverage values convert
|
||||||
// jagged conservative raster edges into a smooth antialiased edge.
|
// jagged conservative raster edges into a smooth antialiased edge.
|
||||||
|
//
|
||||||
|
// NOTE: The Impl may combine this pass with kTriangleHulls, in which case DoesRenderPass()
|
||||||
|
// will be false for kTriangleEdges and it must not be used.
|
||||||
kTriangleEdges,
|
kTriangleEdges,
|
||||||
|
|
||||||
// For Corners, the Impl Generates the conservative rasters of corner points (i.e.
|
// For Corners, the Impl Generates the conservative rasters of corner points (i.e.
|
||||||
@ -82,10 +87,20 @@ public:
|
|||||||
static bool RenderPassIsCubic(RenderPass);
|
static bool RenderPassIsCubic(RenderPass);
|
||||||
static const char* RenderPassName(RenderPass);
|
static const char* RenderPassName(RenderPass);
|
||||||
|
|
||||||
GrCCPRCoverageProcessor(RenderPass pass)
|
constexpr static bool DoesRenderPass(RenderPass renderPass, const GrShaderCaps& caps) {
|
||||||
|
return RenderPass::kTriangleEdges != renderPass || caps.geometryShaderSupport();
|
||||||
|
}
|
||||||
|
|
||||||
|
GrCCPRCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrShaderCaps& caps)
|
||||||
: INHERITED(kGrCCPRCoverageProcessor_ClassID)
|
: INHERITED(kGrCCPRCoverageProcessor_ClassID)
|
||||||
, fRenderPass(pass) {
|
, fRenderPass(pass)
|
||||||
|
, fImpl(caps.geometryShaderSupport() ? Impl::kGeometryShader : Impl::kVertexShader) {
|
||||||
|
SkASSERT(DoesRenderPass(pass, caps));
|
||||||
|
if (Impl::kGeometryShader == fImpl) {
|
||||||
this->initGS();
|
this->initGS();
|
||||||
|
} else {
|
||||||
|
this->initVS(rp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a GrMesh that will draw the provided instances. The instanceBuffer must be an array
|
// Appends a GrMesh that will draw the provided instances. The instanceBuffer must be an array
|
||||||
@ -94,8 +109,12 @@ public:
|
|||||||
//
|
//
|
||||||
// NOTE: Quadratics use TriangleInstance since both have 3 points.
|
// NOTE: Quadratics use TriangleInstance since both have 3 points.
|
||||||
void appendMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
|
void appendMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
|
||||||
SkTArray<GrMesh, true>* out) {
|
SkTArray<GrMesh>* out) {
|
||||||
|
if (Impl::kGeometryShader == fImpl) {
|
||||||
this->appendGSMesh(instanceBuffer, instanceCount, baseInstance, out);
|
this->appendGSMesh(instanceBuffer, instanceCount, baseInstance, out);
|
||||||
|
} else {
|
||||||
|
this->appendVSMesh(instanceBuffer, instanceCount, baseInstance, out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GrPrimitiveProcessor overrides.
|
// GrPrimitiveProcessor overrides.
|
||||||
@ -140,8 +159,8 @@ public:
|
|||||||
const char* repetitionID, const char* wind,
|
const char* repetitionID, const char* wind,
|
||||||
GeometryVars*) const {}
|
GeometryVars*) const {}
|
||||||
|
|
||||||
void emitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
|
void emitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
||||||
const char* coverage, const char* wind);
|
const char* position, const char* coverage, const char* wind);
|
||||||
|
|
||||||
void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
|
void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
|
||||||
const char* skOutputColor, const char* skOutputCoverage) const;
|
const char* skOutputColor, const char* skOutputCoverage) const;
|
||||||
@ -169,15 +188,23 @@ public:
|
|||||||
//
|
//
|
||||||
// NOTE: the coverage parameter is only relevant for edges (see comments in RenderPass).
|
// NOTE: the coverage parameter is only relevant for edges (see comments in RenderPass).
|
||||||
// Otherwise it is +1 all around.
|
// Otherwise it is +1 all around.
|
||||||
virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code,
|
virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope,
|
||||||
const char* position, const char* coverage,
|
SkString* code, const char* position,
|
||||||
const char* wind) = 0;
|
const char* coverage, const char* wind) = 0;
|
||||||
|
|
||||||
// Emits the fragment code that calculates a pixel's coverage value. If using
|
// Emits the fragment code that calculates a pixel's coverage value. If using
|
||||||
// WindHandling::kHandled, this value must be signed appropriately.
|
// WindHandling::kHandled, this value must be signed appropriately.
|
||||||
virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
|
virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
|
||||||
const char* outputCoverage) const = 0;
|
const char* outputCoverage) const = 0;
|
||||||
|
|
||||||
|
// Returns the name of a Shader's internal varying at the point where where its value is
|
||||||
|
// assigned. This is intended to work whether called for a vertex or a geometry shader.
|
||||||
|
const char* OutName(const GrGLSLVarying& varying) const {
|
||||||
|
using Scope = GrGLSLVarying::Scope;
|
||||||
|
SkASSERT(Scope::kVertToGeo != varying.scope());
|
||||||
|
return Scope::kGeoToFrag == varying.scope() ? varying.gsOut() : varying.vsOut();
|
||||||
|
}
|
||||||
|
|
||||||
// Defines a global float2 array that contains MSAA sample locations as offsets from pixel
|
// Defines a global float2 array that contains MSAA sample locations as offsets from pixel
|
||||||
// center. Subclasses can use this for software multisampling.
|
// center. Subclasses can use this for software multisampling.
|
||||||
//
|
//
|
||||||
@ -185,10 +212,11 @@ public:
|
|||||||
static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
|
static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrGLSLVarying fWind{kHalf_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fWind;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GSImpl;
|
class GSImpl;
|
||||||
|
class VSImpl;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
|
// Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
|
||||||
@ -198,12 +226,26 @@ private:
|
|||||||
// Number of bezier points for curves, or 3 for triangles.
|
// Number of bezier points for curves, or 3 for triangles.
|
||||||
int numInputPoints() const { return RenderPassIsCubic(fRenderPass) ? 4 : 3; }
|
int numInputPoints() const { return RenderPassIsCubic(fRenderPass) ? 4 : 3; }
|
||||||
|
|
||||||
|
enum class Impl : bool {
|
||||||
|
kGeometryShader,
|
||||||
|
kVertexShader
|
||||||
|
};
|
||||||
|
|
||||||
void initGS();
|
void initGS();
|
||||||
|
void initVS(GrResourceProvider*);
|
||||||
|
|
||||||
void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
|
void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
|
||||||
SkTArray<GrMesh, true>* out) const;
|
SkTArray<GrMesh>* out) const;
|
||||||
|
void appendVSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
|
||||||
|
SkTArray<GrMesh>* out) const;
|
||||||
|
|
||||||
GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr<Shader>) const;
|
GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr<Shader>) const;
|
||||||
|
GrGLSLPrimitiveProcessor* createVSImpl(std::unique_ptr<Shader>) const;
|
||||||
|
|
||||||
const RenderPass fRenderPass;
|
const RenderPass fRenderPass;
|
||||||
|
const Impl fImpl;
|
||||||
|
sk_sp<const GrBuffer> fVertexBuffer; // Used by VSImpl.
|
||||||
|
sk_sp<const GrBuffer> fIndexBuffer; // Used by VSImpl.
|
||||||
SkDEBUGCODE(float fDebugBloat = 0;)
|
SkDEBUGCODE(float fDebugBloat = 0;)
|
||||||
|
|
||||||
typedef GrGeometryProcessor INHERITED;
|
typedef GrGeometryProcessor INHERITED;
|
||||||
|
@ -72,7 +72,8 @@ protected:
|
|||||||
}
|
}
|
||||||
g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
|
g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
|
||||||
SkString fnBody;
|
SkString fnBody;
|
||||||
fShader->emitVaryings(varyingHandler, &fnBody, position, coverage, wind.c_str());
|
fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kGeoToFrag, &fnBody,
|
||||||
|
position, coverage, wind.c_str());
|
||||||
g->emitVertex(&fnBody, position, rtAdjust);
|
g->emitVertex(&fnBody, position, rtAdjust);
|
||||||
return fnBody;
|
return fnBody;
|
||||||
}().c_str(), &emitVertexFn);
|
}().c_str(), &emitVertexFn);
|
||||||
@ -292,7 +293,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates conservatives around corners. (See comments for RenderPass)
|
* Generates conservative rasters around corners. (See comments for RenderPass)
|
||||||
*/
|
*/
|
||||||
class GSCornerImpl : public GrCCPRCoverageProcessor::GSImpl {
|
class GSCornerImpl : public GrCCPRCoverageProcessor::GSImpl {
|
||||||
public:
|
public:
|
||||||
@ -320,6 +321,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void GrCCPRCoverageProcessor::initGS() {
|
void GrCCPRCoverageProcessor::initGS() {
|
||||||
|
SkASSERT(Impl::kGeometryShader == fImpl);
|
||||||
if (RenderPassIsCubic(fRenderPass)) {
|
if (RenderPassIsCubic(fRenderPass)) {
|
||||||
this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.)
|
this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.)
|
||||||
SkASSERT(sizeof(CubicInstance) == this->getVertexStride() * 2);
|
SkASSERT(sizeof(CubicInstance) == this->getVertexStride() * 2);
|
||||||
@ -331,11 +333,12 @@ void GrCCPRCoverageProcessor::initGS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrCCPRCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount,
|
void GrCCPRCoverageProcessor::appendGSMesh(GrBuffer* instanceBuffer, int instanceCount,
|
||||||
int baseInstance, SkTArray<GrMesh, true>* out) const {
|
int baseInstance, SkTArray<GrMesh>* out) const {
|
||||||
// GSImpl doesn't actually make instanced draw calls. Instead, we feed transposed x,y point
|
// GSImpl doesn't actually make instanced draw calls. Instead, we feed transposed x,y point
|
||||||
// values to the GPU in a regular vertex array and draw kLines (see initGS). Then, each vertex
|
// values to the GPU in a regular vertex array and draw kLines (see initGS). Then, each vertex
|
||||||
// invocation receives either the shape's x or y values as inputs, which it forwards to the
|
// invocation receives either the shape's x or y values as inputs, which it forwards to the
|
||||||
// geometry shader.
|
// geometry shader.
|
||||||
|
SkASSERT(Impl::kGeometryShader == fImpl);
|
||||||
GrMesh& mesh = out->emplace_back(GrPrimitiveType::kLines);
|
GrMesh& mesh = out->emplace_back(GrPrimitiveType::kLines);
|
||||||
mesh.setNonIndexedNonInstanced(instanceCount * 2);
|
mesh.setNonIndexedNonInstanced(instanceCount * 2);
|
||||||
mesh.setVertexData(instanceBuffer, baseInstance * 2);
|
mesh.setVertexData(instanceBuffer, baseInstance * 2);
|
||||||
|
441
src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp
Normal file
441
src/gpu/ccpr/GrCCPRCoverageProcessor_VSImpl.cpp
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
/*
|
||||||
|
* 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 "GrCCPRCoverageProcessor.h"
|
||||||
|
|
||||||
|
#include "GrMesh.h"
|
||||||
|
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||||
|
|
||||||
|
using Shader = GrCCPRCoverageProcessor::Shader;
|
||||||
|
|
||||||
|
static constexpr int kAttribIdx_X = 0;
|
||||||
|
static constexpr int kAttribIdx_Y = 1;
|
||||||
|
static constexpr int kAttribIdx_VertexData = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class and its subclasses implement the coverage processor with vertex shaders.
|
||||||
|
*/
|
||||||
|
class GrCCPRCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
|
||||||
|
protected:
|
||||||
|
VSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
|
||||||
|
|
||||||
|
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
|
||||||
|
FPCoordTransformIter&& transformIter) final {
|
||||||
|
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
|
||||||
|
const GrCCPRCoverageProcessor& proc = args.fGP.cast<GrCCPRCoverageProcessor>();
|
||||||
|
|
||||||
|
// Vertex shader.
|
||||||
|
GrGLSLVertexBuilder* v = args.fVertBuilder;
|
||||||
|
int numInputPoints = proc.numInputPoints();
|
||||||
|
|
||||||
|
v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s, %s));",
|
||||||
|
numInputPoints, numInputPoints, proc.getAttrib(kAttribIdx_X).fName,
|
||||||
|
proc.getAttrib(kAttribIdx_Y).fName);
|
||||||
|
|
||||||
|
v->codeAppend ("float area_x2 = determinant(float2x2(pts[0] - pts[1], pts[0] - pts[2]));");
|
||||||
|
if (4 == numInputPoints) {
|
||||||
|
v->codeAppend ("area_x2 += determinant(float2x2(pts[0] - pts[2], pts[0] - pts[3]));");
|
||||||
|
}
|
||||||
|
v->codeAppend ("half wind = sign(area_x2);");
|
||||||
|
|
||||||
|
float bloat = kAABloatRadius;
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
if (proc.debugVisualizationsEnabled()) {
|
||||||
|
bloat *= proc.debugBloat();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
v->defineConstant("bloat", bloat);
|
||||||
|
|
||||||
|
const char* coverage = this->emitVertexPosition(proc, v, gpArgs);
|
||||||
|
SkASSERT(kFloat2_GrSLType == gpArgs->fPositionVar.getType());
|
||||||
|
|
||||||
|
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
|
||||||
|
SkString varyingCode;
|
||||||
|
fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &varyingCode,
|
||||||
|
gpArgs->fPositionVar.c_str(), coverage, "wind");
|
||||||
|
v->codeAppend(varyingCode.c_str());
|
||||||
|
|
||||||
|
varyingHandler->emitAttributes(proc);
|
||||||
|
SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());
|
||||||
|
|
||||||
|
// Fragment shader.
|
||||||
|
fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* emitVertexPosition(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*,
|
||||||
|
GrGPArgs*) const = 0;
|
||||||
|
|
||||||
|
virtual ~VSImpl() {}
|
||||||
|
|
||||||
|
const std::unique_ptr<Shader> fShader;
|
||||||
|
|
||||||
|
typedef GrGLSLGeometryProcessor INHERITED;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vertex data tells the shader how to offset vertices for conservative raster, and how/whether to
|
||||||
|
* calculate initial coverage values for edges. See VSHullAndEdgeImpl.
|
||||||
|
*/
|
||||||
|
static constexpr int32_t pack_vertex_data(int32_t bloatIdx, int32_t edgeData,
|
||||||
|
int32_t cornerVertexID, int32_t cornerIdx) {
|
||||||
|
return (bloatIdx << 6) | (edgeData << 4) | (cornerVertexID << 2) | cornerIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int32_t hull_vertex_data(int32_t cornerIdx, int32_t cornerVertexID, int n) {
|
||||||
|
return pack_vertex_data((cornerIdx + (2 == cornerVertexID ? 1 : n - 1)) % n, 0, cornerVertexID,
|
||||||
|
cornerIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int32_t edge_vertex_data(int32_t edgeID, int32_t endptIdx, int32_t endptVertexID,
|
||||||
|
int n) {
|
||||||
|
return pack_vertex_data(0 == endptIdx ? (edgeID + 1) % n : edgeID, (endptIdx << 1) | 1,
|
||||||
|
endptVertexID, 0 == endptIdx ? edgeID : (edgeID + 1) % n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int32_t kHull3AndEdgeVertices[] = {
|
||||||
|
hull_vertex_data(0, 0, 3),
|
||||||
|
hull_vertex_data(0, 1, 3),
|
||||||
|
hull_vertex_data(0, 2, 3),
|
||||||
|
hull_vertex_data(1, 0, 3),
|
||||||
|
hull_vertex_data(1, 1, 3),
|
||||||
|
hull_vertex_data(1, 2, 3),
|
||||||
|
hull_vertex_data(2, 0, 3),
|
||||||
|
hull_vertex_data(2, 1, 3),
|
||||||
|
hull_vertex_data(2, 2, 3),
|
||||||
|
|
||||||
|
edge_vertex_data(0, 0, 0, 3),
|
||||||
|
edge_vertex_data(0, 0, 1, 3),
|
||||||
|
edge_vertex_data(0, 0, 2, 3),
|
||||||
|
edge_vertex_data(0, 1, 0, 3),
|
||||||
|
edge_vertex_data(0, 1, 1, 3),
|
||||||
|
edge_vertex_data(0, 1, 2, 3),
|
||||||
|
|
||||||
|
edge_vertex_data(1, 0, 0, 3),
|
||||||
|
edge_vertex_data(1, 0, 1, 3),
|
||||||
|
edge_vertex_data(1, 0, 2, 3),
|
||||||
|
edge_vertex_data(1, 1, 0, 3),
|
||||||
|
edge_vertex_data(1, 1, 1, 3),
|
||||||
|
edge_vertex_data(1, 1, 2, 3),
|
||||||
|
|
||||||
|
edge_vertex_data(2, 0, 0, 3),
|
||||||
|
edge_vertex_data(2, 0, 1, 3),
|
||||||
|
edge_vertex_data(2, 0, 2, 3),
|
||||||
|
edge_vertex_data(2, 1, 0, 3),
|
||||||
|
edge_vertex_data(2, 1, 1, 3),
|
||||||
|
edge_vertex_data(2, 1, 2, 3),
|
||||||
|
};
|
||||||
|
|
||||||
|
GR_DECLARE_STATIC_UNIQUE_KEY(gHull3AndEdgeVertexBufferKey);
|
||||||
|
|
||||||
|
static constexpr uint16_t kHull3AndEdgeIndices[] = {
|
||||||
|
// First corner and main body of the hull.
|
||||||
|
1, 2, 0,
|
||||||
|
2, 3, 0,
|
||||||
|
0, 3, 8, // Main body.
|
||||||
|
|
||||||
|
// Opposite side and corners of the hull.
|
||||||
|
4, 5, 3,
|
||||||
|
5, 6, 3,
|
||||||
|
3, 6, 8,
|
||||||
|
6, 7, 8,
|
||||||
|
|
||||||
|
// First edge.
|
||||||
|
10, 9, 11,
|
||||||
|
9, 14, 11,
|
||||||
|
11, 14, 12,
|
||||||
|
14, 13, 12,
|
||||||
|
|
||||||
|
// Second edge.
|
||||||
|
16, 15, 17,
|
||||||
|
15, 20, 17,
|
||||||
|
17, 20, 18,
|
||||||
|
20, 19, 18,
|
||||||
|
|
||||||
|
// Third edge.
|
||||||
|
22, 21, 23,
|
||||||
|
21, 26, 23,
|
||||||
|
23, 26, 24,
|
||||||
|
26, 25, 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
GR_DECLARE_STATIC_UNIQUE_KEY(gHull3AndEdgeIndexBufferKey);
|
||||||
|
|
||||||
|
static constexpr int32_t kHull4Vertices[] = {
|
||||||
|
hull_vertex_data(0, 0, 4),
|
||||||
|
hull_vertex_data(0, 1, 4),
|
||||||
|
hull_vertex_data(0, 2, 4),
|
||||||
|
hull_vertex_data(1, 0, 4),
|
||||||
|
hull_vertex_data(1, 1, 4),
|
||||||
|
hull_vertex_data(1, 2, 4),
|
||||||
|
hull_vertex_data(2, 0, 4),
|
||||||
|
hull_vertex_data(2, 1, 4),
|
||||||
|
hull_vertex_data(2, 2, 4),
|
||||||
|
hull_vertex_data(3, 0, 4),
|
||||||
|
hull_vertex_data(3, 1, 4),
|
||||||
|
hull_vertex_data(3, 2, 4),
|
||||||
|
|
||||||
|
// No edges for now (beziers don't use edges).
|
||||||
|
};
|
||||||
|
|
||||||
|
GR_DECLARE_STATIC_UNIQUE_KEY(gHull4VertexBufferKey);
|
||||||
|
|
||||||
|
static constexpr uint16_t kHull4Indices[] = {
|
||||||
|
// First half of the hull (split diagonally).
|
||||||
|
1, 0, 2,
|
||||||
|
0, 11, 2,
|
||||||
|
2, 11, 3,
|
||||||
|
11, 5, 3,
|
||||||
|
3, 5, 4,
|
||||||
|
|
||||||
|
// Second half of the hull.
|
||||||
|
7, 6, 8,
|
||||||
|
6, 5, 8,
|
||||||
|
8, 5, 9,
|
||||||
|
5, 11, 9,
|
||||||
|
9, 11, 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
GR_DECLARE_STATIC_UNIQUE_KEY(gHull4IndexBufferKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a conservative raster hull around a convex polygon. For triangles, we also generate
|
||||||
|
* independent conservative rasters around each edge. (See comments for RenderPass)
|
||||||
|
*/
|
||||||
|
class VSHullAndEdgeImpl : public GrCCPRCoverageProcessor::VSImpl {
|
||||||
|
public:
|
||||||
|
VSHullAndEdgeImpl(std::unique_ptr<Shader> shader, int numSides)
|
||||||
|
: VSImpl(std::move(shader)), fNumSides(numSides) {}
|
||||||
|
|
||||||
|
const char* emitVertexPosition(const GrCCPRCoverageProcessor& proc, GrGLSLVertexBuilder* v,
|
||||||
|
GrGPArgs* gpArgs) const override {
|
||||||
|
Shader::GeometryVars vars;
|
||||||
|
fShader->emitSetupCode(v, "pts", nullptr, "wind", &vars);
|
||||||
|
|
||||||
|
const char* hullPts = vars.fHullVars.fAlternatePoints;
|
||||||
|
if (!hullPts) {
|
||||||
|
hullPts = "pts";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0].
|
||||||
|
v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;",
|
||||||
|
proc.getAttrib(kAttribIdx_VertexData).fName,
|
||||||
|
((fNumSides - 1) << 6) | (0xf << 2) | (fNumSides - 1),
|
||||||
|
proc.getAttrib(kAttribIdx_VertexData).fName);
|
||||||
|
|
||||||
|
// Here we generate conservative raster geometry for the input polygon. It is the convex
|
||||||
|
// hull of N pixel-size boxes, one centered on each the input points. Each corner has three
|
||||||
|
// vertices, where one or two may cause degenerate triangles. The vertex data tells us how
|
||||||
|
// to offset each vertex. Triangle edges are also handled here (see kHull3AndEdgeIndices).
|
||||||
|
// For more details on conservative raster, see:
|
||||||
|
// https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html
|
||||||
|
v->codeAppendf("float2 corner = %s[clockwise_indices & 3];", hullPts);
|
||||||
|
v->codeAppendf("float2 bloatpoint = %s[clockwise_indices >> 6];", hullPts);
|
||||||
|
v->codeAppend ("float2 vertexbloat = float2(bloatpoint.y > corner.y ? -bloat : +bloat, "
|
||||||
|
"bloatpoint.x > corner.x ? +bloat : -bloat);");
|
||||||
|
|
||||||
|
v->codeAppendf("if ((1 << 2) == (%s & (3 << 2))) {",
|
||||||
|
proc.getAttrib(kAttribIdx_VertexData).fName);
|
||||||
|
// We are the corner's middle vertex (of 3).
|
||||||
|
v->codeAppend ( "vertexbloat = float2(-vertexbloat.y, vertexbloat.x);");
|
||||||
|
v->codeAppend ("}");
|
||||||
|
|
||||||
|
v->codeAppendf("if ((2 << 2) == (%s & (3 << 2))) {",
|
||||||
|
proc.getAttrib(kAttribIdx_VertexData).fName);
|
||||||
|
// We are the corner's third vertex (of 3).
|
||||||
|
v->codeAppend ( "vertexbloat = -vertexbloat;");
|
||||||
|
v->codeAppend ("}");
|
||||||
|
|
||||||
|
v->codeAppend ("float2 vertex = corner + vertexbloat;");
|
||||||
|
gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
|
||||||
|
|
||||||
|
if (4 == fNumSides) {
|
||||||
|
// We don't generate edges around 4-sided polygons.
|
||||||
|
return nullptr; // Known hull vertices don't need an initial coverage value.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find coverage for edge vertices.
|
||||||
|
Shader::EmitEdgeDistanceEquation(v, "bloatpoint", "corner",
|
||||||
|
"float3 edge_distance_equation");
|
||||||
|
v->codeAppend ("half coverage = dot(edge_distance_equation.xy, vertex) + "
|
||||||
|
"edge_distance_equation.z;");
|
||||||
|
v->codeAppendf("if (0 == (%s & (1 << 5))) {", proc.getAttrib(kAttribIdx_VertexData).fName);
|
||||||
|
// We are the opposite endpoint. Invert coverage.
|
||||||
|
v->codeAppend ( "coverage = -1 - coverage;");
|
||||||
|
v->codeAppend ("}");
|
||||||
|
v->codeAppendf("if (0 == (%s & (1 << 4))) {", proc.getAttrib(kAttribIdx_VertexData).fName);
|
||||||
|
// We are actually a hull vertex. Hull coverage is +1 all around.
|
||||||
|
v->codeAppend ( "coverage = +1;");
|
||||||
|
v->codeAppend ("}");
|
||||||
|
|
||||||
|
return "coverage";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int fNumSides;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr uint16_t kCornerIndices[] = {
|
||||||
|
// First corner.
|
||||||
|
0, 1, 2,
|
||||||
|
1, 3, 2,
|
||||||
|
|
||||||
|
// Second corner.
|
||||||
|
4, 5, 6,
|
||||||
|
5, 7, 6,
|
||||||
|
|
||||||
|
// Third corner.
|
||||||
|
8, 9, 10,
|
||||||
|
9, 11, 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
GR_DECLARE_STATIC_UNIQUE_KEY(gCornerIndexBufferKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates conservative rasters around corners. (See comments for RenderPass)
|
||||||
|
*/
|
||||||
|
class VSCornerImpl : public GrCCPRCoverageProcessor::VSImpl {
|
||||||
|
public:
|
||||||
|
VSCornerImpl(std::unique_ptr<Shader> shader) : VSImpl(std::move(shader)) {}
|
||||||
|
|
||||||
|
const char* emitVertexPosition(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder* v,
|
||||||
|
GrGPArgs* gpArgs) const override {
|
||||||
|
Shader::GeometryVars vars;
|
||||||
|
v->codeAppend ("int corner_id = sk_VertexID / 4;");
|
||||||
|
fShader->emitSetupCode(v, "pts", "corner_id", "wind", &vars);
|
||||||
|
|
||||||
|
v->codeAppendf("float2 vertex = %s;", vars.fCornerVars.fPoint);
|
||||||
|
v->codeAppend ("vertex.x += (0 == (sk_VertexID & 2)) ? -bloat : +bloat;");
|
||||||
|
v->codeAppend ("vertex.y += (0 == (sk_VertexID & 1)) ? -bloat : +bloat;");
|
||||||
|
|
||||||
|
gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
|
||||||
|
return nullptr; // Corner vertices don't have an initial coverage value.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void GrCCPRCoverageProcessor::initVS(GrResourceProvider* rp) {
|
||||||
|
SkASSERT(Impl::kVertexShader == fImpl);
|
||||||
|
|
||||||
|
GrVertexAttribType inputPtsType = RenderPassIsCubic(fRenderPass) ?
|
||||||
|
kFloat4_GrVertexAttribType : kFloat3_GrVertexAttribType;
|
||||||
|
|
||||||
|
SkASSERT(kAttribIdx_X == this->numAttribs());
|
||||||
|
this->addInstanceAttrib("X", inputPtsType);
|
||||||
|
|
||||||
|
SkASSERT(kAttribIdx_Y == this->numAttribs());
|
||||||
|
this->addInstanceAttrib("Y", inputPtsType);
|
||||||
|
|
||||||
|
switch (fRenderPass) {
|
||||||
|
case RenderPass::kTriangleHulls: {
|
||||||
|
GR_DEFINE_STATIC_UNIQUE_KEY(gHull3AndEdgeVertexBufferKey);
|
||||||
|
fVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType,
|
||||||
|
sizeof(kHull3AndEdgeVertices),
|
||||||
|
kHull3AndEdgeVertices,
|
||||||
|
gHull3AndEdgeVertexBufferKey);
|
||||||
|
GR_DEFINE_STATIC_UNIQUE_KEY(gHull3AndEdgeIndexBufferKey);
|
||||||
|
fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
|
||||||
|
sizeof(kHull3AndEdgeIndices),
|
||||||
|
kHull3AndEdgeIndices,
|
||||||
|
gHull3AndEdgeIndexBufferKey);
|
||||||
|
SkASSERT(kAttribIdx_VertexData == this->numAttribs());
|
||||||
|
this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderPass::kQuadraticHulls:
|
||||||
|
case RenderPass::kCubicHulls: {
|
||||||
|
GR_DEFINE_STATIC_UNIQUE_KEY(gHull4VertexBufferKey);
|
||||||
|
fVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType, sizeof(kHull4Vertices),
|
||||||
|
kHull4Vertices, gHull4VertexBufferKey);
|
||||||
|
GR_DEFINE_STATIC_UNIQUE_KEY(gHull4IndexBufferKey);
|
||||||
|
fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, sizeof(kHull4Indices),
|
||||||
|
kHull4Indices, gHull4IndexBufferKey);
|
||||||
|
SkASSERT(kAttribIdx_VertexData == this->numAttribs());
|
||||||
|
this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderPass::kTriangleEdges:
|
||||||
|
SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
|
||||||
|
break;
|
||||||
|
case RenderPass::kTriangleCorners:
|
||||||
|
case RenderPass::kQuadraticCorners:
|
||||||
|
case RenderPass::kCubicCorners: {
|
||||||
|
GR_DEFINE_STATIC_UNIQUE_KEY(gCornerIndexBufferKey);
|
||||||
|
fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, sizeof(kCornerIndices),
|
||||||
|
kCornerIndices, gCornerIndexBufferKey);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
if (RenderPassIsCubic(fRenderPass)) {
|
||||||
|
SkASSERT(offsetof(CubicInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord);
|
||||||
|
SkASSERT(offsetof(CubicInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord);
|
||||||
|
SkASSERT(sizeof(CubicInstance) == this->getInstanceStride());
|
||||||
|
} else {
|
||||||
|
SkASSERT(offsetof(TriangleInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord);
|
||||||
|
SkASSERT(offsetof(TriangleInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord);
|
||||||
|
SkASSERT(sizeof(TriangleInstance) == this->getInstanceStride());
|
||||||
|
}
|
||||||
|
if (fVertexBuffer) {
|
||||||
|
SkASSERT(sizeof(int32_t) == this->getVertexStride());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int num_indices_per_instance(GrCCPRCoverageProcessor::RenderPass pass) {
|
||||||
|
switch (pass) {
|
||||||
|
using RenderPass = GrCCPRCoverageProcessor::RenderPass;
|
||||||
|
case RenderPass::kTriangleHulls:
|
||||||
|
return SK_ARRAY_COUNT(kHull3AndEdgeIndices);
|
||||||
|
case RenderPass::kQuadraticHulls:
|
||||||
|
case RenderPass::kCubicHulls:
|
||||||
|
return SK_ARRAY_COUNT(kHull4Indices);
|
||||||
|
case RenderPass::kTriangleEdges:
|
||||||
|
SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
|
||||||
|
return 0;
|
||||||
|
case RenderPass::kTriangleCorners:
|
||||||
|
return SK_ARRAY_COUNT(kCornerIndices);
|
||||||
|
case RenderPass::kQuadraticCorners:
|
||||||
|
case RenderPass::kCubicCorners:
|
||||||
|
return SK_ARRAY_COUNT(kCornerIndices) * 2/3;
|
||||||
|
}
|
||||||
|
SK_ABORT("Invalid RenderPass");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GrCCPRCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount,
|
||||||
|
int baseInstance, SkTArray<GrMesh>* out) const {
|
||||||
|
SkASSERT(Impl::kVertexShader == fImpl);
|
||||||
|
GrMesh& mesh = out->emplace_back(GrPrimitiveType::kTriangles);
|
||||||
|
mesh.setIndexedInstanced(fIndexBuffer.get(), num_indices_per_instance(fRenderPass),
|
||||||
|
instanceBuffer, instanceCount, baseInstance);
|
||||||
|
if (fVertexBuffer) {
|
||||||
|
mesh.setVertexData(fVertexBuffer.get(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GrGLSLPrimitiveProcessor*
|
||||||
|
GrCCPRCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shader) const {
|
||||||
|
switch (fRenderPass) {
|
||||||
|
case RenderPass::kTriangleHulls:
|
||||||
|
return new VSHullAndEdgeImpl(std::move(shader), 3);
|
||||||
|
case RenderPass::kQuadraticHulls:
|
||||||
|
case RenderPass::kCubicHulls:
|
||||||
|
return new VSHullAndEdgeImpl(std::move(shader), 4);
|
||||||
|
case RenderPass::kTriangleEdges:
|
||||||
|
SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
|
||||||
|
return nullptr;
|
||||||
|
case RenderPass::kTriangleCorners:
|
||||||
|
case RenderPass::kQuadraticCorners:
|
||||||
|
case RenderPass::kCubicCorners:
|
||||||
|
return new VSCornerImpl(std::move(shader));
|
||||||
|
}
|
||||||
|
SK_ABORT("Invalid RenderPass");
|
||||||
|
return nullptr;
|
||||||
|
}
|
@ -76,25 +76,29 @@ void GrCCPRCubicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts
|
|||||||
}
|
}
|
||||||
|
|
||||||
Shader::WindHandling GrCCPRCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
Shader::WindHandling GrCCPRCubicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
|
GrGLSLVarying::Scope scope,
|
||||||
SkString* code, const char* position,
|
SkString* code, const char* position,
|
||||||
const char* coverage, const char* /*wind*/) {
|
const char* coverage, const char* /*wind*/) {
|
||||||
SkASSERT(!coverage);
|
SkASSERT(!coverage);
|
||||||
|
|
||||||
|
fKLMD.reset(kFloat4_GrSLType, scope);
|
||||||
varyingHandler->addVarying("klmd", &fKLMD);
|
varyingHandler->addVarying("klmd", &fKLMD);
|
||||||
code->appendf("float3 klm = float3(%s, 1) * %s;", position, fKLMMatrix.c_str());
|
code->appendf("float3 klm = float3(%s, 1) * %s;", position, fKLMMatrix.c_str());
|
||||||
code->appendf("float d = dot(float3(%s, 1), %s);", position, fEdgeDistanceEquation.c_str());
|
code->appendf("float d = dot(float3(%s, 1), %s);", position, fEdgeDistanceEquation.c_str());
|
||||||
code->appendf("%s = float4(klm, d);", fKLMD.gsOut());
|
code->appendf("%s = float4(klm, d);", OutName(fKLMD));
|
||||||
|
|
||||||
this->onEmitVaryings(varyingHandler, code);
|
this->onEmitVaryings(varyingHandler, scope, code);
|
||||||
return WindHandling::kNotHandled;
|
return WindHandling::kNotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrCCPRCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, SkString* code) {
|
void GrCCPRCubicHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
// "klm" was just defined by the base class.
|
GrGLSLVarying::Scope scope, SkString* code) {
|
||||||
|
fGradMatrix.reset(kFloat2x2_GrSLType, scope);
|
||||||
varyingHandler->addVarying("grad_matrix", &fGradMatrix);
|
varyingHandler->addVarying("grad_matrix", &fGradMatrix);
|
||||||
code->appendf("%s[0] = 3 * klm[0] * %s[0].xy;", fGradMatrix.gsOut(), fKLMMatrix.c_str());
|
// "klm" was just defined by the base class.
|
||||||
|
code->appendf("%s[0] = 3 * klm[0] * %s[0].xy;", OutName(fGradMatrix), fKLMMatrix.c_str());
|
||||||
code->appendf("%s[1] = -klm[1] * %s[2].xy - klm[2] * %s[1].xy;",
|
code->appendf("%s[1] = -klm[1] * %s[2].xy - klm[2] * %s[1].xy;",
|
||||||
fGradMatrix.gsOut(), fKLMMatrix.c_str(), fKLMMatrix.c_str());
|
OutName(fGradMatrix), fKLMMatrix.c_str(), fKLMMatrix.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrCCPRCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
void GrCCPRCubicHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||||
@ -113,15 +117,18 @@ void GrCCPRCubicCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const c
|
|||||||
vars->fCornerVars.fPoint = "corner";
|
vars->fCornerVars.fPoint = "corner";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrCCPRCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, SkString* code) {
|
void GrCCPRCubicCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
|
GrGLSLVarying::Scope scope, SkString* code) {
|
||||||
|
fdKLMDdx.reset(kFloat4_GrSLType, scope);
|
||||||
varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx);
|
varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx);
|
||||||
code->appendf("%s = float4(%s[0].x, %s[1].x, %s[2].x, %s.x);",
|
code->appendf("%s = float4(%s[0].x, %s[1].x, %s[2].x, %s.x);",
|
||||||
fdKLMDdx.gsOut(), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
|
OutName(fdKLMDdx), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
|
||||||
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
|
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
|
||||||
|
|
||||||
|
fdKLMDdy.reset(kFloat4_GrSLType, scope);
|
||||||
varyingHandler->addFlatVarying("dklmddy", &fdKLMDdy);
|
varyingHandler->addFlatVarying("dklmddy", &fdKLMDdy);
|
||||||
code->appendf("%s = float4(%s[0].y, %s[1].y, %s[2].y, %s.y);",
|
code->appendf("%s = float4(%s[0].y, %s[1].y, %s[2].y, %s.y);",
|
||||||
fdKLMDdy.gsOut(), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
|
OutName(fdKLMDdy), fKLMMatrix.c_str(), fKLMMatrix.c_str(),
|
||||||
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
|
fKLMMatrix.c_str(), fEdgeDistanceEquation.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,31 +29,31 @@ protected:
|
|||||||
virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||||
GeometryVars*) const {}
|
GeometryVars*) const {}
|
||||||
|
|
||||||
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
|
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
||||||
const char* coverage, const char* wind) final;
|
const char* position, const char* coverage, const char* wind) final;
|
||||||
|
|
||||||
virtual void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) = 0;
|
virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) = 0;
|
||||||
|
|
||||||
GrShaderVar fKLMMatrix{"klm_matrix", kFloat3x3_GrSLType};
|
GrShaderVar fKLMMatrix{"klm_matrix", kFloat3x3_GrSLType};
|
||||||
GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
|
GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
|
||||||
GrGLSLVarying fKLMD{kFloat4_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fKLMD;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GrCCPRCubicHullShader : public GrCCPRCubicShader {
|
class GrCCPRCubicHullShader : public GrCCPRCubicShader {
|
||||||
void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
|
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
|
||||||
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
||||||
|
|
||||||
GrGLSLVarying fGradMatrix{kFloat2x2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fGradMatrix;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GrCCPRCubicCornerShader : public GrCCPRCubicShader {
|
class GrCCPRCubicCornerShader : public GrCCPRCubicShader {
|
||||||
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||||
GeometryVars*) const override;
|
GeometryVars*) const override;
|
||||||
void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
|
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
|
||||||
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
||||||
|
|
||||||
GrGLSLVarying fdKLMDdx{kFloat4_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fdKLMDdx;
|
||||||
GrGLSLVarying fdKLMDdy{kFloat4_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fdKLMDdy;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "GrCCPRQuadraticShader.h"
|
#include "GrCCPRQuadraticShader.h"
|
||||||
|
|
||||||
|
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||||
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
#include "glsl/GrGLSLVertexGeoBuilder.h"
|
||||||
|
|
||||||
@ -33,19 +34,21 @@ void GrCCPRQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
Shader::WindHandling GrCCPRQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
Shader::WindHandling GrCCPRQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
|
GrGLSLVarying::Scope scope,
|
||||||
SkString* code, const char* position,
|
SkString* code, const char* position,
|
||||||
const char* coverage,
|
const char* coverage,
|
||||||
const char* /*wind*/) {
|
const char* /*wind*/) {
|
||||||
SkASSERT(!coverage);
|
SkASSERT(!coverage);
|
||||||
|
|
||||||
|
fXYD.reset(kFloat3_GrSLType, scope);
|
||||||
varyingHandler->addVarying("xyd", &fXYD);
|
varyingHandler->addVarying("xyd", &fXYD);
|
||||||
code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
|
code->appendf("%s.xy = (%s * float3(%s, 1)).xy;",
|
||||||
fXYD.gsOut(), fCanonicalMatrix.c_str(), position);
|
OutName(fXYD), fCanonicalMatrix.c_str(), position);
|
||||||
code->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
|
code->appendf("%s.z = dot(%s.xy, %s) + %s.z;",
|
||||||
fXYD.gsOut(), fEdgeDistanceEquation.c_str(), position,
|
OutName(fXYD), fEdgeDistanceEquation.c_str(), position,
|
||||||
fEdgeDistanceEquation.c_str());
|
fEdgeDistanceEquation.c_str());
|
||||||
|
|
||||||
this->onEmitVaryings(varyingHandler, code);
|
this->onEmitVaryings(varyingHandler, scope, code);
|
||||||
return WindHandling::kNotHandled;
|
return WindHandling::kNotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,10 +72,11 @@ void GrCCPRQuadraticHullShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrCCPRQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
void GrCCPRQuadraticHullShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
SkString* code) {
|
GrGLSLVarying::Scope scope, SkString* code) {
|
||||||
|
fGrad.reset(kFloat2_GrSLType, scope);
|
||||||
varyingHandler->addVarying("grad", &fGrad);
|
varyingHandler->addVarying("grad", &fGrad);
|
||||||
code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);",
|
code->appendf("%s = float2(2 * %s.x, -1) * float2x2(%s);",
|
||||||
fGrad.gsOut(), fXYD.gsOut(), fCanonicalMatrix.c_str());
|
OutName(fGrad), OutName(fXYD), fCanonicalMatrix.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrCCPRQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
void GrCCPRQuadraticHullShader::onEmitFragmentCode(GrGLSLPPFragmentBuilder* f,
|
||||||
@ -91,15 +95,17 @@ void GrCCPRQuadraticCornerShader::onEmitSetupCode(GrGLSLVertexGeoBuilder* s, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrCCPRQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
void GrCCPRQuadraticCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
SkString* code) {
|
GrGLSLVarying::Scope scope, SkString* code) {
|
||||||
|
fdXYDdx.reset(kFloat3_GrSLType, scope);
|
||||||
varyingHandler->addFlatVarying("dXYDdx", &fdXYDdx);
|
varyingHandler->addFlatVarying("dXYDdx", &fdXYDdx);
|
||||||
code->appendf("%s = float3(%s[0].x, %s[0].y, %s.x);",
|
code->appendf("%s = float3(%s[0].x, %s[0].y, %s.x);",
|
||||||
fdXYDdx.gsOut(), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
|
OutName(fdXYDdx), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
|
||||||
fEdgeDistanceEquation.c_str());
|
fEdgeDistanceEquation.c_str());
|
||||||
|
|
||||||
|
fdXYDdy.reset(kFloat3_GrSLType, scope);
|
||||||
varyingHandler->addFlatVarying("dXYDdy", &fdXYDdy);
|
varyingHandler->addFlatVarying("dXYDdy", &fdXYDdy);
|
||||||
code->appendf("%s = float3(%s[1].x, %s[1].y, %s.y);",
|
code->appendf("%s = float3(%s[1].x, %s[1].y, %s.y);",
|
||||||
fdXYDdy.gsOut(), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
|
OutName(fdXYDdy), fCanonicalMatrix.c_str(), fCanonicalMatrix.c_str(),
|
||||||
fEdgeDistanceEquation.c_str());
|
fEdgeDistanceEquation.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,14 +28,14 @@ protected:
|
|||||||
virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
virtual void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||||
GeometryVars*) const = 0;
|
GeometryVars*) const = 0;
|
||||||
|
|
||||||
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
|
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
||||||
const char* coverage, const char* wind) final;
|
const char* position, const char* coverage, const char* wind) final;
|
||||||
|
|
||||||
virtual void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) = 0;
|
virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) {}
|
||||||
|
|
||||||
const GrShaderVar fCanonicalMatrix{"canonical_matrix", kFloat3x3_GrSLType};
|
const GrShaderVar fCanonicalMatrix{"canonical_matrix", kFloat3x3_GrSLType};
|
||||||
const GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
|
const GrShaderVar fEdgeDistanceEquation{"edge_distance_equation", kFloat3_GrSLType};
|
||||||
GrGLSLVarying fXYD{kFloat3_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fXYD;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,10 +47,10 @@ protected:
|
|||||||
class GrCCPRQuadraticHullShader : public GrCCPRQuadraticShader {
|
class GrCCPRQuadraticHullShader : public GrCCPRQuadraticShader {
|
||||||
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||||
GeometryVars*) const override;
|
GeometryVars*) const override;
|
||||||
void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
|
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
|
||||||
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
||||||
|
|
||||||
GrGLSLVarying fGrad{kFloat2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fGrad;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,11 +59,11 @@ class GrCCPRQuadraticHullShader : public GrCCPRQuadraticShader {
|
|||||||
class GrCCPRQuadraticCornerShader : public GrCCPRQuadraticShader {
|
class GrCCPRQuadraticCornerShader : public GrCCPRQuadraticShader {
|
||||||
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
void onEmitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||||
GeometryVars*) const override;
|
GeometryVars*) const override;
|
||||||
void onEmitVaryings(GrGLSLVaryingHandler*, SkString* code) override;
|
void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code) override;
|
||||||
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
||||||
|
|
||||||
GrGLSLVarying fdXYDdx{kFloat3_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fdXYDdx;
|
||||||
GrGLSLVarying fdXYDdy{kFloat3_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fdXYDdy;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,14 +13,16 @@
|
|||||||
using Shader = GrCCPRCoverageProcessor::Shader;
|
using Shader = GrCCPRCoverageProcessor::Shader;
|
||||||
|
|
||||||
Shader::WindHandling GrCCPRTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
Shader::WindHandling GrCCPRTriangleShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
|
GrGLSLVarying::Scope scope,
|
||||||
SkString* code, const char* /*position*/,
|
SkString* code, const char* /*position*/,
|
||||||
const char* coverage, const char* wind) {
|
const char* coverage, const char* wind) {
|
||||||
|
fCoverageTimesWind.reset(kHalf_GrSLType, scope);
|
||||||
if (!coverage) {
|
if (!coverage) {
|
||||||
varyingHandler->addFlatVarying("wind", &fCoverageTimesWind);
|
varyingHandler->addFlatVarying("wind", &fCoverageTimesWind);
|
||||||
code->appendf("%s = %s;", fCoverageTimesWind.gsOut(), wind);
|
code->appendf("%s = %s;", OutName(fCoverageTimesWind), wind);
|
||||||
} else {
|
} else {
|
||||||
varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind);
|
varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind);
|
||||||
code->appendf("%s = %s * %s;", fCoverageTimesWind.gsOut(), coverage, wind);
|
code->appendf("%s = %s * %s;", OutName(fCoverageTimesWind), coverage, wind);
|
||||||
}
|
}
|
||||||
return WindHandling::kHandled;
|
return WindHandling::kHandled;
|
||||||
}
|
}
|
||||||
@ -85,18 +87,23 @@ void GrCCPRTriangleCornerShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Shader::WindHandling
|
Shader::WindHandling
|
||||||
GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, SkString* code,
|
GrCCPRTriangleCornerShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
|
||||||
|
GrGLSLVarying::Scope scope, SkString* code,
|
||||||
const char* position, const char* coverage,
|
const char* position, const char* coverage,
|
||||||
const char* /*wind*/) {
|
const char* /*wind*/) {
|
||||||
SkASSERT(!coverage);
|
SkASSERT(!coverage);
|
||||||
|
|
||||||
|
fCornerLocationInAABoxes.reset(kFloat2x2_GrSLType, scope);
|
||||||
varyingHandler->addVarying("corner_location_in_aa_boxes", &fCornerLocationInAABoxes);
|
varyingHandler->addVarying("corner_location_in_aa_boxes", &fCornerLocationInAABoxes);
|
||||||
|
|
||||||
|
fBisectInAABoxes.reset(kFloat2x2_GrSLType, scope);
|
||||||
varyingHandler->addFlatVarying("bisect_in_aa_boxes", &fBisectInAABoxes);
|
varyingHandler->addFlatVarying("bisect_in_aa_boxes", &fBisectInAABoxes);
|
||||||
|
|
||||||
code->appendf("for (int i = 0; i < 2; ++i) {");
|
code->appendf("for (int i = 0; i < 2; ++i) {");
|
||||||
code->appendf( "%s[i] = %s * %s[i] + %s[i];",
|
code->appendf( "%s[i] = %s * %s[i] + %s[i];",
|
||||||
fCornerLocationInAABoxes.gsOut(), position, fAABoxMatrices.c_str(),
|
OutName(fCornerLocationInAABoxes), position, fAABoxMatrices.c_str(),
|
||||||
fAABoxTranslates.c_str());
|
fAABoxTranslates.c_str());
|
||||||
code->appendf( "%s[i] = %s[i];", fBisectInAABoxes.gsOut(), fGeoShaderBisects.c_str());
|
code->appendf( "%s[i] = %s[i];", OutName(fBisectInAABoxes), fGeoShaderBisects.c_str());
|
||||||
code->appendf("}");
|
code->appendf("}");
|
||||||
|
|
||||||
return WindHandling::kNotHandled;
|
return WindHandling::kNotHandled;
|
||||||
|
@ -11,35 +11,38 @@
|
|||||||
#include "ccpr/GrCCPRCoverageProcessor.h"
|
#include "ccpr/GrCCPRCoverageProcessor.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passes 1 & 2: Draw the triangle's conservative raster hull with a coverage of 1, then smooth the
|
* Steps 1 & 2: Draw the triangle's conservative raster hull with a coverage of +1, then smooth the
|
||||||
* edges by drawing the conservative rasters of all 3 edges and interpolating from
|
* edges by drawing the conservative rasters of all 3 edges and interpolating from
|
||||||
* coverage=-1 on the outside to coverage=0 on the inside.
|
* coverage=-1 on the outside to coverage=0 on the inside. The Impl may choose to
|
||||||
|
* implement these steps in either one or two actual render passes.
|
||||||
*/
|
*/
|
||||||
class GrCCPRTriangleShader : public GrCCPRCoverageProcessor::Shader {
|
class GrCCPRTriangleShader : public GrCCPRCoverageProcessor::Shader {
|
||||||
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
|
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
||||||
const char* coverage, const char* wind) override;
|
const char* position, const char* coverage,
|
||||||
|
const char* wind) override;
|
||||||
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, const char* outputCoverage) const override;
|
||||||
|
|
||||||
GrGLSLVarying fCoverageTimesWind{kHalf_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fCoverageTimesWind;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass 3: Touch up the corner pixels. Here we fix the simple distance-to-edge coverage analysis
|
* Step 3: Touch up the corner pixels. Here we fix the simple distance-to-edge coverage analysis
|
||||||
* done previously so that it takes into account the region that is outside both edges at
|
* done previously so that it takes into account the region that is outside both edges at
|
||||||
* the same time.
|
* the same time.
|
||||||
*/
|
*/
|
||||||
class GrCCPRTriangleCornerShader : public GrCCPRCoverageProcessor::Shader {
|
class GrCCPRTriangleCornerShader : public GrCCPRCoverageProcessor::Shader {
|
||||||
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* repetitionID,
|
||||||
const char* wind, GeometryVars*) const override;
|
const char* wind, GeometryVars*) const override;
|
||||||
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
|
WindHandling onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
|
||||||
const char* coverage, const char* wind) override;
|
const char* position, const char* coverage,
|
||||||
|
const char* wind) override;
|
||||||
void onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, const char* outputCoverage) const override;
|
void onEmitFragmentCode(GrGLSLPPFragmentBuilder* f, const char* outputCoverage) const override;
|
||||||
|
|
||||||
GrShaderVar fAABoxMatrices{"aa_box_matrices", kFloat2x2_GrSLType, 2};
|
GrShaderVar fAABoxMatrices{"aa_box_matrices", kFloat2x2_GrSLType, 2};
|
||||||
GrShaderVar fAABoxTranslates{"aa_box_translates", kFloat2_GrSLType, 2};
|
GrShaderVar fAABoxTranslates{"aa_box_translates", kFloat2_GrSLType, 2};
|
||||||
GrShaderVar fGeoShaderBisects{"bisects", kFloat2_GrSLType, 2};
|
GrShaderVar fGeoShaderBisects{"bisects", kFloat2_GrSLType, 2};
|
||||||
GrGLSLVarying fCornerLocationInAABoxes{kFloat2x2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fCornerLocationInAABoxes;
|
||||||
GrGLSLVarying fBisectInAABoxes{kFloat2x2_GrSLType, GrGLSLVarying::Scope::kGeoToFrag};
|
GrGLSLVarying fBisectInAABoxes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,14 +38,12 @@ static void crop_path(const SkPath& path, const SkIRect& cropbox, SkPath* out) {
|
|||||||
|
|
||||||
bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
|
bool GrCoverageCountingPathRenderer::IsSupported(const GrCaps& caps) {
|
||||||
const GrShaderCaps& shaderCaps = *caps.shaderCaps();
|
const GrShaderCaps& shaderCaps = *caps.shaderCaps();
|
||||||
return shaderCaps.geometryShaderSupport() &&
|
return shaderCaps.integerSupport() &&
|
||||||
shaderCaps.integerSupport() &&
|
|
||||||
shaderCaps.flatInterpolationSupport() &&
|
shaderCaps.flatInterpolationSupport() &&
|
||||||
caps.instanceAttribSupport() &&
|
caps.instanceAttribSupport() &&
|
||||||
GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
|
GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
|
||||||
caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
|
caps.isConfigTexturable(kAlpha_half_GrPixelConfig) &&
|
||||||
caps.isConfigRenderable(kAlpha_half_GrPixelConfig, /*withMSAA=*/false) &&
|
caps.isConfigRenderable(kAlpha_half_GrPixelConfig, /*withMSAA=*/false) &&
|
||||||
GrCaps::kNone_MapFlags != caps.mapBufferFlags() &&
|
|
||||||
!caps.blacklistCoverageCounting();
|
!caps.blacklistCoverageCounting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ void GrGLSLVaryingHandler::internalAddVarying(const char* name, GrGLSLVarying* v
|
|||||||
VaryingInfo& v = fVaryings.push_back();
|
VaryingInfo& v = fVaryings.push_back();
|
||||||
|
|
||||||
SkASSERT(varying);
|
SkASSERT(varying);
|
||||||
|
SkASSERT(kVoid_GrSLType != varying->fType);
|
||||||
v.fType = varying->fType;
|
v.fType = varying->fType;
|
||||||
v.fIsFlat = flat;
|
v.fIsFlat = flat;
|
||||||
fProgramBuilder->nameVariable(&v.fVsOut, 'v', name);
|
fProgramBuilder->nameVariable(&v.fVsOut, 'v', name);
|
||||||
|
@ -24,8 +24,15 @@ public:
|
|||||||
kGeoToFrag
|
kGeoToFrag
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GrGLSLVarying() = default;
|
||||||
GrGLSLVarying(GrSLType type, Scope scope = Scope::kVertToFrag) : fType(type), fScope(scope) {}
|
GrGLSLVarying(GrSLType type, Scope scope = Scope::kVertToFrag) : fType(type), fScope(scope) {}
|
||||||
|
|
||||||
|
void reset(GrSLType type, Scope scope = Scope::kVertToFrag) {
|
||||||
|
*this = GrGLSLVarying();
|
||||||
|
fType = type;
|
||||||
|
fScope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
GrSLType type() const { return fType; }
|
GrSLType type() const { return fType; }
|
||||||
Scope scope() const { return fScope; }
|
Scope scope() const { return fScope; }
|
||||||
bool isInVertexShader() const { return Scope::kGeoToFrag != fScope; }
|
bool isInVertexShader() const { return Scope::kGeoToFrag != fScope; }
|
||||||
@ -37,8 +44,8 @@ public:
|
|||||||
const char* fsIn() const { SkASSERT(this->isInFragmentShader()); return fFsIn; }
|
const char* fsIn() const { SkASSERT(this->isInFragmentShader()); return fFsIn; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const GrSLType fType;
|
GrSLType fType = kVoid_GrSLType;
|
||||||
const Scope fScope;
|
Scope fScope = Scope::kVertToFrag;
|
||||||
const char* fVsOut = nullptr;
|
const char* fVsOut = nullptr;
|
||||||
const char* fGsIn = nullptr;
|
const char* fGsIn = nullptr;
|
||||||
const char* fGsOut = nullptr;
|
const char* fGsOut = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user