[graphite] Add vertex/instance attribute definition to RenderStep
Moves Attribute into its own header. I did not move AttributeSet/Iter out of GraphicsPipelineDesc because RenderStep should be able to just rely on SkSpan<Attribute>. Since they are fixed definitions, there shouldn't be a need to support skipping over uninitialized attrs. Once GraphicsPipelineDesc just points to a RenderStep, AttributeSet/Iter can be deleted. Bug: skia:12466 Change-Id: I3b01b6283669fc02dc9cd0521bb236a9d0daa5eb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/474136 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
54feafc834
commit
1f224edb2c
46
experimental/graphite/src/Attribute.h
Normal file
46
experimental/graphite/src/Attribute.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef skgpu_Attribute_DEFINED
|
||||
#define skgpu_Attribute_DEFINED
|
||||
|
||||
#include "experimental/graphite/src/DrawTypes.h"
|
||||
|
||||
namespace skgpu {
|
||||
|
||||
/** Describes a vertex or instance attribute. */
|
||||
class Attribute {
|
||||
public:
|
||||
constexpr Attribute() = default;
|
||||
constexpr Attribute(const char* name,
|
||||
VertexAttribType cpuType,
|
||||
SLType gpuType)
|
||||
: fName(name), fCPUType(cpuType), fGPUType(gpuType) {
|
||||
SkASSERT(name && gpuType != SLType::kVoid);
|
||||
}
|
||||
constexpr Attribute(const Attribute&) = default;
|
||||
|
||||
Attribute& operator=(const Attribute&) = default;
|
||||
|
||||
constexpr bool isInitialized() const { return fGPUType != SLType::kVoid; }
|
||||
|
||||
constexpr const char* name() const { return fName; }
|
||||
constexpr VertexAttribType cpuType() const { return fCPUType; }
|
||||
constexpr SLType gpuType() const { return fGPUType; }
|
||||
|
||||
constexpr size_t size() const { return VertexAttribTypeSize(fCPUType); }
|
||||
constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
|
||||
|
||||
private:
|
||||
const char* fName = nullptr;
|
||||
VertexAttribType fCPUType = VertexAttribType::kFloat;
|
||||
SLType fGPUType = SLType::kVoid;
|
||||
};
|
||||
|
||||
} // namespace skgpu
|
||||
|
||||
#endif // skgpu_Attribute_DEFINED
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include "experimental/graphite/src/Attribute.h"
|
||||
#include "experimental/graphite/src/DrawTypes.h"
|
||||
#include "include/private/SkTArray.h"
|
||||
|
||||
@ -23,35 +24,7 @@ class GraphicsPipelineDesc {
|
||||
public:
|
||||
GraphicsPipelineDesc();
|
||||
|
||||
/** Describes a vertex or instance attribute. */
|
||||
class Attribute {
|
||||
public:
|
||||
constexpr Attribute() = default;
|
||||
constexpr Attribute(const char* name,
|
||||
VertexAttribType cpuType,
|
||||
SLType gpuType)
|
||||
: fName(name), fCPUType(cpuType), fGPUType(gpuType) {
|
||||
SkASSERT(name && gpuType != SLType::kVoid);
|
||||
}
|
||||
constexpr Attribute(const Attribute&) = default;
|
||||
|
||||
Attribute& operator=(const Attribute&) = default;
|
||||
|
||||
constexpr bool isInitialized() const { return fGPUType != SLType::kVoid; }
|
||||
|
||||
constexpr const char* name() const { return fName; }
|
||||
constexpr VertexAttribType cpuType() const { return fCPUType; }
|
||||
constexpr SLType gpuType() const { return fGPUType; }
|
||||
|
||||
constexpr size_t size() const { return VertexAttribTypeSize(fCPUType); }
|
||||
constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
|
||||
|
||||
private:
|
||||
const char* fName = nullptr;
|
||||
VertexAttribType fCPUType = VertexAttribType::kFloat;
|
||||
SLType fGPUType = SLType::kVoid;
|
||||
};
|
||||
|
||||
// TODO: Iter and AttributeSet go away when the RenderStep is part of the GraphicsPipelineDesc.
|
||||
class Iter {
|
||||
public:
|
||||
Iter() : fCurr(nullptr), fRemaining(0) {}
|
||||
|
@ -8,13 +8,17 @@
|
||||
#ifndef skgpu_Renderer_DEFINED
|
||||
#define skgpu_Renderer_DEFINED
|
||||
|
||||
#include "experimental/graphite/src/Attribute.h"
|
||||
#include "experimental/graphite/src/DrawTypes.h"
|
||||
#include "experimental/graphite/src/EnumBitMask.h"
|
||||
|
||||
#include "include/core/SkSpan.h"
|
||||
#include "include/core/SkString.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <array>
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
|
||||
namespace skgpu {
|
||||
|
||||
@ -25,23 +29,28 @@ class Uniform;
|
||||
|
||||
class RenderStep {
|
||||
public:
|
||||
virtual ~RenderStep() {}
|
||||
|
||||
virtual const char* name() const = 0;
|
||||
virtual bool requiresStencil() const = 0;
|
||||
virtual bool requiresMSAA() const = 0;
|
||||
virtual bool performsShading() const = 0;
|
||||
virtual ~RenderStep() = default;
|
||||
|
||||
// The DrawWriter is configured with the vertex and instance strides of the RenderStep, and its
|
||||
// primitive type. The recorded draws will be executed with a graphics pipeline compatible with
|
||||
// this RenderStep.
|
||||
virtual void writeVertices(DrawWriter*, const Shape&) const = 0;
|
||||
|
||||
// While RenderStep does not define the full program that's run for a draw, it defines the
|
||||
// entire vertex layout of the pipeline.
|
||||
virtual size_t vertexStride() const = 0;
|
||||
virtual size_t instanceStride() const = 0;
|
||||
virtual PrimitiveType primitiveType() const = 0;
|
||||
virtual const char* name() const = 0;
|
||||
|
||||
bool requiresStencil() const { return fFlags & Flags::kRequiresStencil; }
|
||||
bool requiresMSAA() const { return fFlags & Flags::kRequiresMSAA; }
|
||||
bool performsShading() const { return fFlags & Flags::kPerformsShading; }
|
||||
|
||||
PrimitiveType primitiveType() const { return fPrimitiveType; }
|
||||
size_t vertexStride() const { return fVertexStride; }
|
||||
size_t instanceStride() const { return fInstanceStride; }
|
||||
|
||||
size_t numVertexAttributes() const { return fVertexAttrs.size(); }
|
||||
size_t numInstanceAttributes() const { return fInstanceAttrs.size(); }
|
||||
|
||||
SkSpan<const Attribute> vertexAttributes() const { return SkMakeSpan(fVertexAttrs); }
|
||||
SkSpan<const Attribute> instanceAttributes() const { return SkMakeSpan(fInstanceAttrs); }
|
||||
|
||||
// TODO: Actual API to do things
|
||||
// 1. Provide stencil settings
|
||||
@ -54,12 +63,53 @@ public:
|
||||
// stateless Renderstep can refer to for {draw,step} pairs?
|
||||
// - Does each DrawList::Draw have extra space (e.g. 8 bytes) that steps can cache data in?
|
||||
protected:
|
||||
RenderStep() {}
|
||||
enum class Flags : unsigned {
|
||||
kNone = 0b000,
|
||||
kRequiresStencil = 0b001,
|
||||
kRequiresMSAA = 0b010,
|
||||
kPerformsShading = 0b100,
|
||||
};
|
||||
SKGPU_DECL_MASK_OPS_FRIENDS(Flags);
|
||||
|
||||
// While RenderStep does not define the full program that's run for a draw, it defines the
|
||||
// entire vertex layout of the pipeline. This is not allowed to change, so can be provided to
|
||||
// the RenderStep constructor by subclasses.
|
||||
RenderStep(Mask<Flags> flags, PrimitiveType primitiveType,
|
||||
std::initializer_list<Attribute> vertexAttrs,
|
||||
std::initializer_list<Attribute> instanceAttrs)
|
||||
: fFlags(flags)
|
||||
, fPrimitiveType(primitiveType)
|
||||
, fVertexAttrs(vertexAttrs)
|
||||
, fInstanceAttrs(instanceAttrs)
|
||||
, fVertexStride(0)
|
||||
, fInstanceStride(0) {
|
||||
for (auto v : this->vertexAttributes()) {
|
||||
fVertexStride += v.sizeAlign4();
|
||||
}
|
||||
for (auto i : this->instanceAttributes()) {
|
||||
fInstanceStride += i.sizeAlign4();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Cannot copy or move
|
||||
RenderStep(const RenderStep&) = delete;
|
||||
RenderStep(RenderStep&&) = delete;
|
||||
|
||||
Mask<Flags> fFlags;
|
||||
PrimitiveType fPrimitiveType;
|
||||
|
||||
// TODO: When we always use C++17 for builds, we should be able to just let subclasses declare
|
||||
// constexpr arrays and point to those, but we need explicit storage for C++14.
|
||||
// Alternatively, if we imposed a max attr count, similar to Renderer's num render steps, we
|
||||
// could just have this be std::array and keep all attributes inline with the RenderStep memory.
|
||||
// On the other hand, the attributes are only needed when creating a new pipeline so it's not
|
||||
// that performance sensitive.
|
||||
std::vector<Attribute> fVertexAttrs;
|
||||
std::vector<Attribute> fInstanceAttrs;
|
||||
|
||||
size_t fVertexStride; // derived from vertex attribute set
|
||||
size_t fInstanceStride; // derived from instance attribute set
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -55,21 +55,16 @@ private:
|
||||
// of skgpu::v1::PathStencilCoverOp.
|
||||
class FillBoundsRenderStep final : public RenderStep {
|
||||
public:
|
||||
FillBoundsRenderStep() {}
|
||||
// TODO: Will need to add kRequiresStencil when we support specifying stencil settings and
|
||||
// the Renderer includes the stenciling step first.
|
||||
FillBoundsRenderStep()
|
||||
: RenderStep(Flags::kPerformsShading, PrimitiveType::kTriangleStrip,
|
||||
/*vertexAttrs=*/{{"position", VertexAttribType::kFloat2, SLType::kFloat2}},
|
||||
/*instanceAttrs=*/{}) {}
|
||||
|
||||
~FillBoundsRenderStep() override {}
|
||||
|
||||
const char* name() const override { return "fill-bounds"; }
|
||||
// TODO: true when combined with a stencil step
|
||||
bool requiresStencil() const override { return false; }
|
||||
bool requiresMSAA() const override { return false; }
|
||||
bool performsShading() const override { return true; }
|
||||
|
||||
PrimitiveType primitiveType() const override { return PrimitiveType::kTriangleStrip; }
|
||||
size_t instanceStride() const override { return 0; }
|
||||
size_t vertexStride() const override {
|
||||
return VertexAttribTypeSize(VertexAttribType::kFloat2);
|
||||
}
|
||||
const char* name() const override { return "fill-bounds"; }
|
||||
|
||||
void writeVertices(DrawWriter* writer, const Shape& shape) const override {
|
||||
// TODO: Need to account for the transform eventually, but that requires more plumbing
|
||||
@ -82,8 +77,6 @@ public:
|
||||
// the DrawWriter to support appending both vertex and instance data simultaneously, which
|
||||
// would need to return 2 vertex writers?
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -17,6 +17,7 @@ skia_graphite_sources = [
|
||||
"$_include/Context.h",
|
||||
"$_include/SkStuff.h",
|
||||
"$_include/TextureInfo.h",
|
||||
"$_src/Attribute.h",
|
||||
"$_src/BackendTexture.cpp",
|
||||
"$_src/Buffer.cpp",
|
||||
"$_src/Buffer.h",
|
||||
|
@ -70,7 +70,6 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
target->instantiate(gpu->resourceProvider());
|
||||
DrawBufferManager bufferMgr(gpu->resourceProvider(), 4);
|
||||
|
||||
|
||||
commandBuffer->beginRenderPass(renderPassDesc);
|
||||
|
||||
DrawWriter drawWriter(commandBuffer->asDrawDispatcher(), &bufferMgr);
|
||||
@ -113,7 +112,7 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
|
||||
// Draw inset magenta rectangle with triangles in vertex buffer
|
||||
pipelineDesc.setTestingOnlyShaderIndex(2);
|
||||
skgpu::GraphicsPipelineDesc::Attribute vertexAttributes[1] = {
|
||||
Attribute vertexAttributes[1] = {
|
||||
{ "position", VertexAttribType::kFloat2, SLType::kFloat2 }
|
||||
};
|
||||
pipelineDesc.setVertexAttributes(vertexAttributes, 1);
|
||||
@ -125,9 +124,9 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
|
||||
auto [vertexWriter, vertices] = bufferMgr.getVertexWriter(4 * pipelineDesc.vertexStride());
|
||||
vertexWriter << SkPoint{0.25f, 0.25f}
|
||||
<< SkPoint{0.25f, 0.75f}
|
||||
<< SkPoint{0.75f, 0.25f}
|
||||
<< SkPoint{0.75f, 0.75f};
|
||||
<< SkPoint{0.25f, 0.75f}
|
||||
<< SkPoint{0.75f, 0.25f}
|
||||
<< SkPoint{0.75f, 0.75f};
|
||||
auto [indexWriter, indices] = bufferMgr.getIndexWriter(6 * sizeof(uint16_t));
|
||||
indexWriter << 0 << 1 << 2
|
||||
<< 2 << 1 << 3;
|
||||
@ -140,7 +139,7 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
|
||||
// draw rects using instance buffer
|
||||
pipelineDesc.setTestingOnlyShaderIndex(3);
|
||||
skgpu::GraphicsPipelineDesc::Attribute instanceAttributes[3] = {
|
||||
Attribute instanceAttributes[3] = {
|
||||
{ "position", VertexAttribType::kFloat2, SLType::kFloat2 },
|
||||
{ "dims", VertexAttribType::kFloat2, SLType::kFloat2 },
|
||||
{ "color", VertexAttribType::kFloat4, SLType::kFloat4 }
|
||||
@ -156,7 +155,7 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
drawWriter.setInstanceTemplate({}, indices, 6);
|
||||
auto instanceWriter = drawWriter.appendInstances(2);
|
||||
instanceWriter << SkPoint{-0.4f, -0.4f} << SkPoint{0.4f, 0.4f} << SkColors::kGreen
|
||||
<< SkPoint{0.f, 0.f} << SkPoint{0.25f, 0.25f} << SkColors::kCyan;
|
||||
<< SkPoint{0.f, 0.f} << SkPoint{0.25f, 0.25f} << SkColors::kCyan;
|
||||
|
||||
drawWriter.flush();
|
||||
uniformBuffer->unmap();
|
||||
|
Loading…
Reference in New Issue
Block a user