blob: 1bb80a8f3cb85e86c78d997f84cfe589d5c191c5 [file] [log] [blame]
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/graphite/render/VerticesRenderStep.h"
#include "src/core/SkPipelineData.h"
#include "src/core/SkSLTypeShared.h"
#include "src/core/SkVertState.h"
#include "src/core/SkVerticesPriv.h"
#include "src/gpu/graphite/DrawParams.h"
#include "src/gpu/graphite/DrawTypes.h"
#include "src/gpu/graphite/DrawWriter.h"
#include "src/gpu/graphite/render/CommonDepthStencilSettings.h"
namespace skgpu::graphite {
namespace {
static constexpr Attribute kPositionAttr =
{"position", VertexAttribType::kFloat2, SkSLType::kFloat2};
static constexpr Attribute kTexCoordAttr =
{"texCoords", VertexAttribType::kFloat2, SkSLType::kFloat2};
static constexpr Attribute kColorAttr =
{"vertColor", VertexAttribType::kUByte4_norm, SkSLType::kHalf4};
static constexpr Attribute kSsboIndexAttr =
{"ssboIndex", VertexAttribType::kInt, SkSLType::kInt};
static constexpr Attribute kAttributePositionOnly[] =
{kPositionAttr, kSsboIndexAttr};
static constexpr Attribute kAttributeColor[] =
{kPositionAttr, kColorAttr, kSsboIndexAttr};
static constexpr Attribute kAttributeTexCoords[] =
{kPositionAttr, kTexCoordAttr, kSsboIndexAttr};
static constexpr Attribute kAttributeColorAndTexCoords[] =
{kPositionAttr, kColorAttr, kTexCoordAttr, kSsboIndexAttr};
static constexpr SkSpan<const Attribute> kAttributes[4] = {
kAttributePositionOnly,
kAttributeColor,
kAttributeTexCoords,
kAttributeColorAndTexCoords,
};
static constexpr Varying kVaryingColor[] =
{{"color", SkSLType::kHalf4}};
static constexpr SkSpan<const Varying> kVaryings[2] = {
/*none*/ {},
/*color*/ kVaryingColor
};
std::string variant_name(PrimitiveType type, bool hasColor, bool hasTexCoords) {
SkASSERT(type == PrimitiveType::kTriangles || type == PrimitiveType::kTriangleStrip);
std::string name = (type == PrimitiveType::kTriangles ? "tris" : "tristrips");
if (hasColor) {
name += "-color";
}
if (hasTexCoords) {
name += "-texCoords";
}
return name;
}
} // namespace
VerticesRenderStep::VerticesRenderStep(PrimitiveType type, bool hasColor, bool hasTexCoords)
: RenderStep("VerticesRenderStep",
variant_name(type, hasColor, hasTexCoords),
hasColor ? Flags::kEmitsPrimitiveColor | Flags::kPerformsShading
: Flags::kPerformsShading,
/*uniforms=*/{{"depth", SkSLType::kFloat}},
type,
kDirectDepthGEqualPass,
/*vertexAttrs=*/ kAttributes[2*hasTexCoords + hasColor],
/*instanceAttrs=*/{},
/*varyings=*/ kVaryings[hasColor])
, fHasColor(hasColor)
, fHasTexCoords(hasTexCoords) {}
VerticesRenderStep::~VerticesRenderStep() {}
const char* VerticesRenderStep::vertexSkSL() const {
if (fHasColor && fHasTexCoords) {
return R"(
color = half4(vertColor.bgr * vertColor.a, vertColor.a);
float4 devPosition = float4(position, 1.0, 1.0);
stepLocalCoords = texCoords;
)";
} else if (fHasTexCoords) {
return R"(
float4 devPosition = float4(position, 1.0, 1.0);
stepLocalCoords = texCoords;
)";
} else if (fHasColor) {
return R"(
color = half4(vertColor.bgr * vertColor.a, vertColor.a);
float4 devPosition = float4(position, 1.0, 1.0);
stepLocalCoords = position;
)";
} else {
return R"(
float4 devPosition = float4(position, 1.0, 1.0);
stepLocalCoords = position;
)";
}
}
void VerticesRenderStep::writeVertices(DrawWriter* writer,
const DrawParams& params,
int ssboIndex) const {
// TODO: Instead of fHasColor and fHasTexture, use info() and assert.
if (fHasColor && fHasTexCoords) {
writeVerticesColorAndTexture(writer, params, ssboIndex);
} else if (fHasColor) {
writeVerticesColor(writer, params, ssboIndex);
} else if (fHasTexCoords) {
writeVerticesTexture(writer, params, ssboIndex);
} else {
SkVerticesPriv info(params.geometry().vertices()->priv());
const int vertexCount = info.vertexCount();
const int indexCount = info.indexCount();
const SkPoint* positions = info.positions();
const uint16_t* indices = info.indices();
DrawWriter::Vertices verts{*writer};
verts.reserve(indexCount);
VertState state(vertexCount, indices, indexCount);
VertState::Proc vertProc = state.chooseProc(info.mode());
while (vertProc(&state)) {
SkV2 p[3] = {{positions[state.f0].x(), positions[state.f0].y()},
{positions[state.f1].x(), positions[state.f1].y()},
{positions[state.f2].x(), positions[state.f2].y()}};
SkV4 devPoints[3];
params.transform().mapPoints(p, devPoints, 3);
verts.append(3) << devPoints[0].x << devPoints[0].y << ssboIndex
<< devPoints[1].x << devPoints[1].y << ssboIndex
<< devPoints[2].x << devPoints[2].y << ssboIndex;
}
}
}
void VerticesRenderStep::writeUniformsAndTextures(const DrawParams& params,
SkPipelineDataGatherer* gatherer) const {
// Vertices are currently pre-transformed to device space on the CPU so no transformation matrix
// is needed. Store PaintDepth as a uniform to avoid copying the same depth for each vertex.
SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)
gatherer->write(params.order().depthAsFloat());
}
const char* VerticesRenderStep::fragmentColorSkSL() const {
if (fHasColor) {
return "primitiveColor = color;\n";
} else {
return "";
}
}
void VerticesRenderStep::writeVerticesColorAndTexture(DrawWriter* writer, const DrawParams& params,
int ssboIndex) const {
SkVerticesPriv info(params.geometry().vertices()->priv());
const int vertexCount = info.vertexCount();
const int indexCount = info.indexCount();
const SkPoint* positions = info.positions();
const uint16_t* indices = info.indices();
const SkColor* colors = info.colors();
const SkPoint* texCoords = info.texCoords();
DrawWriter::Vertices verts{*writer};
VertState state(vertexCount, indices, indexCount);
VertState::Proc vertProc = state.chooseProc(info.mode());
while (vertProc(&state)) {
SkV2 p[3] = {{positions[state.f0].x(), positions[state.f0].y()},
{positions[state.f1].x(), positions[state.f1].y()},
{positions[state.f2].x(), positions[state.f2].y()}};
SkV4 devPoints[3];
params.transform().mapPoints(p, devPoints, 3);
verts.append(3) << devPoints[0].x << devPoints[0].y << colors[state.f0]
<< texCoords[state.f0] << ssboIndex
<< devPoints[1].x << devPoints[1].y << colors[state.f1]
<< texCoords[state.f1] << ssboIndex
<< devPoints[2].x << devPoints[2].y << colors[state.f2]
<< texCoords[state.f2] << ssboIndex;
}
}
void VerticesRenderStep::writeVerticesColor(DrawWriter* writer, const DrawParams& params,
int ssboIndex) const {
SkVerticesPriv info(params.geometry().vertices()->priv());
const int vertexCount = info.vertexCount();
const int indexCount = info.indexCount();
const SkPoint* positions = info.positions();
const uint16_t* indices = info.indices();
const SkColor* colors = info.colors();
DrawWriter::Vertices verts{*writer};
VertState state(vertexCount, indices, indexCount);
VertState::Proc vertProc = state.chooseProc(info.mode());
while (vertProc(&state)) {
SkV2 p[3] = {{positions[state.f0].x(), positions[state.f0].y()},
{positions[state.f1].x(), positions[state.f1].y()},
{positions[state.f2].x(), positions[state.f2].y()}};
SkV4 devPoints[3];
params.transform().mapPoints(p, devPoints, 3);
verts.append(3) << devPoints[0].x << devPoints[0].y << colors[state.f0] << ssboIndex
<< devPoints[1].x << devPoints[1].y << colors[state.f1] << ssboIndex
<< devPoints[2].x << devPoints[2].y << colors[state.f2] << ssboIndex;
}
}
void VerticesRenderStep::writeVerticesTexture(DrawWriter* writer, const DrawParams& params,
int ssboIndex) const {
SkVerticesPriv info(params.geometry().vertices()->priv());
const int vertexCount = info.vertexCount();
const int indexCount = info.indexCount();
const SkPoint* positions = info.positions();
const uint16_t* indices = info.indices();
const SkPoint* texCoords = info.texCoords();
DrawWriter::Vertices verts{*writer};
VertState state(vertexCount, indices, indexCount);
VertState::Proc vertProc = state.chooseProc(info.mode());
while (vertProc(&state)) {
SkV2 p[3] = {{positions[state.f0].x(), positions[state.f0].y()},
{positions[state.f1].x(), positions[state.f1].y()},
{positions[state.f2].x(), positions[state.f2].y()}};
SkV4 devPoints[3];
params.transform().mapPoints(p, devPoints, 3);
verts.append(3) << devPoints[0].x << devPoints[0].y << texCoords[state.f0] << ssboIndex
<< devPoints[1].x << devPoints[1].y << texCoords[state.f1] << ssboIndex
<< devPoints[2].x << devPoints[2].y << texCoords[state.f2] << ssboIndex;
}
}
} // namespace skgpu::graphite