[graphite] Add support for shader varyings

Bug: skia:13118
Change-Id: I94131b9d05f73445def32d9e880a6048a23de74d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/557585
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Jim Van Verth 2022-07-12 11:09:50 -04:00 committed by SkCQ
parent d9f2c12ec1
commit d0066ba138
4 changed files with 57 additions and 37 deletions

View File

@ -34,6 +34,12 @@ class DrawWriter;
class DrawParams;
class ResourceProvider;
struct Varying {
const char* fName;
SkSLType fType;
// TODO: add modifier (e.g., flat and noperspective) support
};
class RenderStep {
public:
virtual ~RenderStep() = default;
@ -94,13 +100,14 @@ public:
size_t numUniforms() const { return fUniforms.size(); }
size_t numVertexAttributes() const { return fVertexAttrs.size(); }
size_t numInstanceAttributes() const { return fInstanceAttrs.size(); }
size_t numVaryings() const { return fVaryings.size(); }
// The uniforms of a RenderStep are bound to the kRenderStep slot, the rest of the pipeline
// may still use uniforms bound to other slots.
SkSpan<const SkUniform> uniforms() const { return SkSpan(fUniforms); }
SkSpan<const Attribute> vertexAttributes() const { return SkSpan(fVertexAttrs); }
SkSpan<const Attribute> instanceAttributes() const { return SkSpan(fInstanceAttrs); }
SkSpan<const Varying> varyings() const { return SkSpan(fVaryings); }
// TODO: Actual API to do things
// 6. Some Renderers benefit from being able to share vertices between RenderSteps. Must find a
@ -128,13 +135,15 @@ protected:
PrimitiveType primitiveType,
DepthStencilSettings depthStencilSettings,
std::initializer_list<Attribute> vertexAttrs,
std::initializer_list<Attribute> instanceAttrs)
std::initializer_list<Attribute> instanceAttrs,
std::initializer_list<Varying> varyings = {})
: fFlags(flags)
, fPrimitiveType(primitiveType)
, fDepthStencilSettings(depthStencilSettings)
, fUniforms(uniforms)
, fVertexAttrs(vertexAttrs)
, fInstanceAttrs(instanceAttrs)
, fVaryings(varyings)
, fVertexStride(0)
, fInstanceStride(0)
, fName(className) {
@ -170,6 +179,7 @@ private:
std::vector<SkUniform> fUniforms;
std::vector<Attribute> fVertexAttrs;
std::vector<Attribute> fInstanceAttrs;
std::vector<Varying> fVaryings;
size_t fVertexStride; // derived from vertex attribute set
size_t fInstanceStride; // derived from instance attribute set

View File

@ -12,6 +12,7 @@
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/SkSLString.h"
#include "src/core/SkPipelineData.h"
#include "src/core/SkSLTypeShared.h"
#include "src/core/SkShaderCodeDictionary.h"
#include "src/gpu/graphite/GraphicsPipelineDesc.h"
#include "src/gpu/graphite/Log.h"
@ -77,32 +78,8 @@ std::string emit_SkSL_attributes(SkSpan<const Attribute> vertexAttrs,
int attr = 0;
auto add_attrs = [&](SkSpan<const Attribute> attrs) {
for (auto a : attrs) {
// TODO: this is sufficient for the sprint but should be changed to use SkSL's
// machinery
SkSL::String::appendf(&result, " layout(location=%d) in ", attr++);
switch (a.gpuType()) {
case SkSLType::kFloat4:
result.append("float4");
break;
case SkSLType::kFloat2:
result.append("float2");
break;
case SkSLType::kFloat3:
result.append("float3");
break;
case SkSLType::kFloat:
result.append("float");
break;
case SkSLType::kHalf4:
result.append("half4");
break;
case SkSLType::kUShort2:
result.append("ushort2");
break;
default:
SkASSERT(0);
}
result.append(SkSLTypeString(a.gpuType()));
SkSL::String::appendf(&result, " %s;\n", a.name());
}
};
@ -119,6 +96,19 @@ std::string emit_SkSL_attributes(SkSpan<const Attribute> vertexAttrs,
return result;
}
std::string emit_SkSL_varyings(SkSpan<const Varying> varyings, const char* direction) {
std::string result;
int location = 0;
for (auto v : varyings) {
SkSL::String::appendf(&result, " layout(location=%d) %s ", location++, direction);
result.append(SkSLTypeString(v.fType));
SkSL::String::appendf(&result, " %s;\n", v.fName);
}
return result;
}
std::string get_sksl_vs(const GraphicsPipelineDesc& desc) {
const RenderStep* step = desc.renderStep();
// TODO: To more completely support end-to-end rendering, this will need to be updated so that
@ -145,6 +135,11 @@ std::string get_sksl_vs(const GraphicsPipelineDesc& desc) {
sksl += emit_SkSL_uniforms(1, "Step", step->uniforms());
}
// Varyings needed by RenderStep
if (step->numVaryings() > 0) {
sksl += emit_SkSL_varyings(step->varyings(), "out");
}
// Vertex shader function declaration
sksl += "void main() {\n";
// Vertex shader body
@ -169,7 +164,17 @@ std::string get_sksl_fs(SkShaderCodeDictionary* dict,
dict->getShaderInfo(desc.paintParamsID(), &shaderInfo);
*blendInfo = shaderInfo.blendInfo();
return shaderInfo.toSkSL();
std::string sksl;
const RenderStep* step = desc.renderStep();
// Varyings needed by RenderStep
if (step->numVaryings() > 0) {
sksl += emit_SkSL_varyings(step->varyings(), "in");
}
sksl += shaderInfo.toSkSL();
return sksl;
}
inline MTLVertexFormat attribute_type_to_mtlformat(VertexAttribType type) {

View File

@ -40,7 +40,10 @@ TextDirectRenderStep::TextDirectRenderStep()
{{"position", VertexAttribType::kFloat2, SkSLType::kFloat2},
{"depth", VertexAttribType::kFloat, SkSLType::kFloat},
{"texCoords", VertexAttribType::kUShort2, SkSLType::kUShort2}},
/*instanceAttrs=*/{}) {}
/*instanceAttrs=*/{},
/*varyings=*/
{{"textureCoords", SkSLType::kFloat2},
{"texIndex", SkSLType::kFloat}}){}
TextDirectRenderStep::~TextDirectRenderStep() {}
@ -50,9 +53,8 @@ const char* TextDirectRenderStep::vertexSkSL() const {
int texIdx = coords.x >> 13;
float2 unormTexCoords = float2(coords.x & 0x1FFF, coords.y);
// TODO: these should be varyings
float2 textureCoords = unormTexCoords * atlasSizeInv;
float texIndex = float(texIdx);
textureCoords = unormTexCoords * atlasSizeInv;
texIndex = float(texIdx);
float4 devPosition = float4(position, depth, 1);
)";

View File

@ -39,7 +39,11 @@ TextSDFRenderStep::TextSDFRenderStep(bool isA8)
{{"position", VertexAttribType::kFloat2, SkSLType::kFloat2},
{"depth", VertexAttribType::kFloat, SkSLType::kFloat},
{"texCoords", VertexAttribType::kUShort2, SkSLType::kUShort2}},
/*instanceAttrs=*/{}) {
/*instanceAttrs=*/{},
/*varyings=*/
{{"unormTexCoords", SkSLType::kFloat2},
{"textureCoords", SkSLType::kFloat2},
{"texIndex", SkSLType::kFloat}}) {
// TODO: store if it's A8?
}
@ -50,10 +54,9 @@ const char* TextSDFRenderStep::vertexSkSL() const {
int2 coords = int2(texCoords.x, texCoords.y);
int texIdx = coords.x >> 13;
// TODO: these should be varyings
float2 unormTexCoords = float2(coords.x & 0x1FFF, coords.y);
float2 textureCoords = unormTexCoords * atlasSizeInv;
float texIndex = float(texIdx);
unormTexCoords = float2(coords.x & 0x1FFF, coords.y);
textureCoords = unormTexCoords * atlasSizeInv;
texIndex = float(texIdx);
float4 devPosition = float4(position, depth, 1);
)";