Reland "Add support for explicit attribute offsets and strides."
This is a reland of 6927ab9311
Original change's description:
> Add support for explicit attribute offsets and strides.
>
> Previously attribute offsets were always computed based on their
> position in an attribute array and the stride was determined
> by the offset and size of the last attribute.
>
> Now a GP has the option to create attributes with explicit offsets
> and specify an explicit vertex stride. All attributes must either
> be implicit or explicit (enforced by assert).
>
> GrGeometryProcessor::AttributeSet is now responsible for handling
> implicitly determined attribute offsets and strides. The backends
> no longer compute them.
>
> Bug: skia:12720
> Change-Id: I0211673dc70d4797c2d66b2555d8f5fb430be056
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/484736
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
Bug: skia:12720
Change-Id: Ic4975b5b2e52f2d8213154da0e585eca6dfdd78d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/486098
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
f70746701c
commit
dd9ef457d9
@ -117,7 +117,7 @@ private:
|
|||||||
fInColor = {"inColor", kHalf4_GrVertexAttribType, kHalf4_GrSLType};
|
fInColor = {"inColor", kHalf4_GrVertexAttribType, kHalf4_GrSLType};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this->setVertexAttributes(&fInPosition, 2);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mode fMode;
|
Mode fMode;
|
||||||
|
300
gm/attributes.cpp
Normal file
300
gm/attributes.cpp
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Google LLC
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gm/gm.h"
|
||||||
|
#include "include/core/SkPoint.h"
|
||||||
|
#include "include/core/SkRect.h"
|
||||||
|
#include "include/gpu/GrRecordingContext.h"
|
||||||
|
#include "src/core/SkCanvasPriv.h"
|
||||||
|
#include "src/gpu/GrBuffer.h"
|
||||||
|
#include "src/gpu/GrGeometryProcessor.h"
|
||||||
|
#include "src/gpu/GrGpuBuffer.h"
|
||||||
|
#include "src/gpu/GrOpFlushState.h"
|
||||||
|
#include "src/gpu/GrProcessor.h"
|
||||||
|
#include "src/gpu/GrProcessorSet.h"
|
||||||
|
#include "src/gpu/GrProgramInfo.h"
|
||||||
|
#include "src/gpu/GrResourceProvider.h"
|
||||||
|
#include "src/gpu/GrShaderVar.h"
|
||||||
|
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||||
|
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
|
||||||
|
#include "src/gpu/ops/GrDrawOp.h"
|
||||||
|
#include "src/gpu/ops/GrOp.h"
|
||||||
|
#include "src/gpu/v1/SurfaceDrawContext_v1.h"
|
||||||
|
#include "tools/gpu/ProxyUtils.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GrAppliedClip;
|
||||||
|
class GrGLSLProgramDataManager;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
enum class AttrMode {
|
||||||
|
kAuto,
|
||||||
|
kManual,
|
||||||
|
kWacky
|
||||||
|
};
|
||||||
|
|
||||||
|
class AttributeTestProcessor : public GrGeometryProcessor {
|
||||||
|
public:
|
||||||
|
static GrGeometryProcessor* Make(SkArenaAlloc* arena, AttrMode mode) {
|
||||||
|
return arena->make([&](void* ptr) { return new (ptr) AttributeTestProcessor(mode); });
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* name() const final { return "AttributeTestProcessor"; }
|
||||||
|
|
||||||
|
void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {
|
||||||
|
b->add32(static_cast<uint32_t>(fMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AttributeTestProcessor(AttrMode mode)
|
||||||
|
: GrGeometryProcessor(kAttributeTestProcessor_ClassID), fMode(mode) {
|
||||||
|
switch (fMode) {
|
||||||
|
case AttrMode::kAuto:
|
||||||
|
fAttributes.emplace_back("pos", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
|
||||||
|
fAttributes.emplace_back("color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType);
|
||||||
|
this->setVertexAttributesWithImplicitOffsets(fAttributes.data(),
|
||||||
|
fAttributes.size());
|
||||||
|
break;
|
||||||
|
case AttrMode::kManual:
|
||||||
|
// Same result as kAuto but with explicitly specified offsets and stride.
|
||||||
|
fAttributes.emplace_back("pos", kFloat2_GrVertexAttribType, kFloat2_GrSLType, 0);
|
||||||
|
fAttributes.emplace_back(
|
||||||
|
"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType, 8);
|
||||||
|
this->setVertexAttributes(fAttributes.data(), fAttributes.size(), 12);
|
||||||
|
break;
|
||||||
|
case AttrMode::kWacky:
|
||||||
|
// 0 thru 7 : float2 aliased to "pos0" and "pos1"
|
||||||
|
// 8 thru 11: pad
|
||||||
|
// 12 thru 15: unorm4 "color"
|
||||||
|
// 16 thru 19: pad
|
||||||
|
fAttributes.emplace_back("pos0", kFloat2_GrVertexAttribType, kFloat2_GrSLType, 0);
|
||||||
|
fAttributes.emplace_back("pos1", kFloat2_GrVertexAttribType, kFloat2_GrSLType, 0);
|
||||||
|
fAttributes.emplace_back(
|
||||||
|
"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType, 12);
|
||||||
|
this->setVertexAttributes(fAttributes.data(), fAttributes.size(), 20);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AttrMode fMode;
|
||||||
|
|
||||||
|
std::vector<Attribute> fAttributes;
|
||||||
|
|
||||||
|
using INHERITED = GrGeometryProcessor;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<GrGeometryProcessor::ProgramImpl> AttributeTestProcessor::makeProgramImpl(
|
||||||
|
const GrShaderCaps&) const {
|
||||||
|
class Impl : public ProgramImpl {
|
||||||
|
public:
|
||||||
|
void setData(const GrGLSLProgramDataManager&,
|
||||||
|
const GrShaderCaps&,
|
||||||
|
const GrGeometryProcessor&) override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
|
||||||
|
const AttributeTestProcessor& proc = args.fGeomProc.cast<AttributeTestProcessor>();
|
||||||
|
args.fVaryingHandler->emitAttributes(proc);
|
||||||
|
if (proc.fMode == AttrMode::kWacky) {
|
||||||
|
args.fVertBuilder->codeAppend("float2 pos = pos0 + pos1;");
|
||||||
|
}
|
||||||
|
args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
|
||||||
|
args.fVaryingHandler->addPassThroughAttribute(GrShaderVar("color", kHalf4_GrSLType),
|
||||||
|
args.fOutputColor);
|
||||||
|
gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos");
|
||||||
|
args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return std::make_unique<Impl>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AttributeTestOp : public GrDrawOp {
|
||||||
|
public:
|
||||||
|
DEFINE_OP_CLASS_ID
|
||||||
|
|
||||||
|
static GrOp::Owner Make(GrRecordingContext* context, AttrMode mode, const SkRect& r) {
|
||||||
|
return GrOp::Make<AttributeTestOp>(context, mode, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AttributeTestOp(AttrMode mode, SkRect rect) : GrDrawOp(ClassID()), fMode(mode), fRect(rect) {
|
||||||
|
this->setBounds(fRect, HasAABloat::kNo, IsHairline::kNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* name() const override { return "AttributeTestOp"; }
|
||||||
|
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
|
||||||
|
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
|
||||||
|
return GrProcessorSet::EmptySetAnalysis();
|
||||||
|
}
|
||||||
|
|
||||||
|
GrProgramInfo* createProgramInfo(const GrCaps* caps,
|
||||||
|
SkArenaAlloc* arena,
|
||||||
|
const GrSurfaceProxyView& writeView,
|
||||||
|
bool usesMSAASurface,
|
||||||
|
GrAppliedClip&& appliedClip,
|
||||||
|
const GrDstProxyView& dstProxyView,
|
||||||
|
GrXferBarrierFlags renderPassXferBarriers,
|
||||||
|
GrLoadOp colorLoadOp) const {
|
||||||
|
GrGeometryProcessor* geomProc = AttributeTestProcessor::Make(arena, fMode);
|
||||||
|
|
||||||
|
return sk_gpu_test::CreateProgramInfo(caps,
|
||||||
|
arena,
|
||||||
|
writeView,
|
||||||
|
usesMSAASurface,
|
||||||
|
std::move(appliedClip),
|
||||||
|
dstProxyView,
|
||||||
|
geomProc,
|
||||||
|
SkBlendMode::kSrcOver,
|
||||||
|
GrPrimitiveType::kTriangleStrip,
|
||||||
|
renderPassXferBarriers,
|
||||||
|
colorLoadOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) const {
|
||||||
|
return this->createProgramInfo(&flushState->caps(),
|
||||||
|
flushState->allocator(),
|
||||||
|
flushState->writeView(),
|
||||||
|
flushState->usesMSAASurface(),
|
||||||
|
flushState->detachAppliedClip(),
|
||||||
|
flushState->dstProxyView(),
|
||||||
|
flushState->renderPassBarriers(),
|
||||||
|
flushState->colorLoadOp());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPrePrepare(GrRecordingContext* context,
|
||||||
|
const GrSurfaceProxyView& writeView,
|
||||||
|
GrAppliedClip* clip,
|
||||||
|
const GrDstProxyView& dstProxyView,
|
||||||
|
GrXferBarrierFlags renderPassXferBarriers,
|
||||||
|
GrLoadOp colorLoadOp) final {
|
||||||
|
SkArenaAlloc* arena = context->priv().recordTimeAllocator();
|
||||||
|
|
||||||
|
// DMSAA is not supported on DDL.
|
||||||
|
bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;
|
||||||
|
|
||||||
|
// This is equivalent to a GrOpFlushState::detachAppliedClip
|
||||||
|
GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
|
||||||
|
|
||||||
|
fProgramInfo = this->createProgramInfo(context->priv().caps(),
|
||||||
|
arena,
|
||||||
|
writeView,
|
||||||
|
usesMSAASurface,
|
||||||
|
std::move(appliedClip),
|
||||||
|
dstProxyView,
|
||||||
|
renderPassXferBarriers,
|
||||||
|
colorLoadOp);
|
||||||
|
|
||||||
|
context->priv().recordProgramInfo(fProgramInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V> void makeVB(GrOpFlushState* flushState, const SkRect rect) {
|
||||||
|
V v[4];
|
||||||
|
v[0].p = {rect.left() , rect.top() };
|
||||||
|
v[1].p = {rect.right(), rect.top() };
|
||||||
|
v[2].p = {rect.left() , rect.bottom()};
|
||||||
|
v[3].p = {rect.right(), rect.bottom()};
|
||||||
|
v[0].color = SK_ColorRED;
|
||||||
|
v[1].color = SK_ColorGREEN;
|
||||||
|
v[2].color = SK_ColorYELLOW;
|
||||||
|
v[3].color = SK_ColorMAGENTA;
|
||||||
|
fVertexBuffer = flushState->resourceProvider()->createBuffer(
|
||||||
|
sizeof(v), GrGpuBufferType::kVertex, kStatic_GrAccessPattern, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPrepare(GrOpFlushState* flushState) override {
|
||||||
|
if (fMode == AttrMode::kWacky) {
|
||||||
|
struct V {
|
||||||
|
SkPoint p;
|
||||||
|
uint32_t pad0;
|
||||||
|
uint32_t color;
|
||||||
|
uint32_t pad1;
|
||||||
|
};
|
||||||
|
SkRect rect {fRect.fLeft/2.f, fRect.fTop/2.f, fRect.fRight/2.f, fRect.fBottom/2.f};
|
||||||
|
this->makeVB<V>(flushState, rect);
|
||||||
|
} else {
|
||||||
|
struct V {
|
||||||
|
SkPoint p;
|
||||||
|
uint32_t color;
|
||||||
|
};
|
||||||
|
this->makeVB<V>(flushState, fRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
|
||||||
|
if (!fVertexBuffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fProgramInfo) {
|
||||||
|
fProgramInfo = this->createProgramInfo(flushState);
|
||||||
|
}
|
||||||
|
|
||||||
|
flushState->bindPipeline(*fProgramInfo, fRect);
|
||||||
|
flushState->bindBuffers(nullptr, nullptr, std::move(fVertexBuffer));
|
||||||
|
flushState->draw(4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_sp<GrBuffer> fVertexBuffer;
|
||||||
|
const AttrMode fMode;
|
||||||
|
const SkRect fRect;
|
||||||
|
|
||||||
|
// The program info (and both the GrPipeline and GrGeometryProcessor it relies on), when
|
||||||
|
// allocated, are allocated in either the ddl-record-time or flush-time arena. It is the
|
||||||
|
// arena's job to free up their memory so we just have a bare programInfo pointer here. We
|
||||||
|
// don't even store the GrPipeline and GrGeometryProcessor pointers here bc they are
|
||||||
|
// guaranteed to have the same lifetime as the program info.
|
||||||
|
GrProgramInfo* fProgramInfo = nullptr;
|
||||||
|
|
||||||
|
friend class ::GrOp; // for ctor
|
||||||
|
|
||||||
|
using INHERITED = GrDrawOp;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace skiagm {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a GPU-backend specific test that exercises explicit and implicit attribute offsets and
|
||||||
|
* strides.
|
||||||
|
*/
|
||||||
|
class AttributesGM : public GpuGM {
|
||||||
|
SkString onShortName() override { return SkString("attributes"); }
|
||||||
|
SkISize onISize() override { return {120, 340}; }
|
||||||
|
DrawResult onDraw(GrRecordingContext*, SkCanvas*, SkString* errorMsg) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
DrawResult AttributesGM::onDraw(GrRecordingContext* rc, SkCanvas* canvas, SkString* errorMsg) {
|
||||||
|
auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);
|
||||||
|
if (!sdc) {
|
||||||
|
*errorMsg = kErrorMsg_DrawSkippedGpuOnly;
|
||||||
|
return DrawResult::kSkip;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdc->clear(SK_PMColor4fBLACK);
|
||||||
|
|
||||||
|
// Draw the test directly to the frame buffer.
|
||||||
|
auto r = SkRect::MakeXYWH(10, 10, 100, 100);
|
||||||
|
for (AttrMode m : {AttrMode::kAuto, AttrMode::kManual, AttrMode::kWacky}) {
|
||||||
|
sdc->addDrawOp(AttributeTestOp::Make(rc, m, r));
|
||||||
|
r.offset(0, 110);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DrawResult::kOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
DEF_GM( return new AttributesGM(); )
|
||||||
|
|
||||||
|
} // namespace skiagm
|
@ -84,7 +84,7 @@ private:
|
|||||||
ClockwiseTestProcessor(bool readSkFragCoord)
|
ClockwiseTestProcessor(bool readSkFragCoord)
|
||||||
: GrGeometryProcessor(kClockwiseTestProcessor_ClassID)
|
: GrGeometryProcessor(kClockwiseTestProcessor_ClassID)
|
||||||
, fReadSkFragCoord(readSkFragCoord) {
|
, fReadSkFragCoord(readSkFragCoord) {
|
||||||
this->setVertexAttributes(&gVertex, 1);
|
this->setVertexAttributesWithImplicitOffsets(&gVertex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool fReadSkFragCoord;
|
const bool fReadSkFragCoord;
|
||||||
|
@ -77,7 +77,7 @@ private:
|
|||||||
FwidthSquircleTestProcessor(const SkMatrix& viewMatrix)
|
FwidthSquircleTestProcessor(const SkMatrix& viewMatrix)
|
||||||
: GrGeometryProcessor(kFwidthSquircleTestProcessor_ClassID)
|
: GrGeometryProcessor(kFwidthSquircleTestProcessor_ClassID)
|
||||||
, fViewMatrix(viewMatrix) {
|
, fViewMatrix(viewMatrix) {
|
||||||
this->setVertexAttributes(&gVertex, 1);
|
this->setVertexAttributesWithImplicitOffsets(&gVertex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkMatrix fViewMatrix;
|
const SkMatrix fViewMatrix;
|
||||||
|
@ -55,7 +55,7 @@ class TessellationTestTriShader : public GrGeometryProcessor {
|
|||||||
public:
|
public:
|
||||||
TessellationTestTriShader(const SkMatrix& viewMatrix)
|
TessellationTestTriShader(const SkMatrix& viewMatrix)
|
||||||
: GrGeometryProcessor(kTessellationTestTriShader_ClassID), fViewMatrix(viewMatrix) {
|
: GrGeometryProcessor(kTessellationTestTriShader_ClassID), fViewMatrix(viewMatrix) {
|
||||||
this->setVertexAttributes(&kPositionAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kPositionAttrib, 1);
|
||||||
this->setWillUseTessellationShaders();
|
this->setWillUseTessellationShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ gm_sources = [
|
|||||||
"$_gm/arcto.cpp",
|
"$_gm/arcto.cpp",
|
||||||
"$_gm/arithmode.cpp",
|
"$_gm/arithmode.cpp",
|
||||||
"$_gm/asyncrescaleandread.cpp",
|
"$_gm/asyncrescaleandread.cpp",
|
||||||
|
"$_gm/attributes.cpp",
|
||||||
"$_gm/b_119394958.cpp",
|
"$_gm/b_119394958.cpp",
|
||||||
"$_gm/backdrop.cpp",
|
"$_gm/backdrop.cpp",
|
||||||
"$_gm/backdrop_imagefilter_croprect.cpp",
|
"$_gm/backdrop_imagefilter_croprect.cpp",
|
||||||
|
@ -223,7 +223,7 @@ private:
|
|||||||
if (fFlags & kCoverageAttribute_GPFlag) {
|
if (fFlags & kCoverageAttribute_GPFlag) {
|
||||||
fInCoverage = {"inCoverage", kFloat_GrVertexAttribType, kHalf_GrSLType};
|
fInCoverage = {"inCoverage", kFloat_GrVertexAttribType, kHalf_GrSLType};
|
||||||
}
|
}
|
||||||
this->setVertexAttributes(&fInPosition, 4);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute fInPosition;
|
Attribute fInPosition;
|
||||||
|
@ -486,3 +486,89 @@ void ProgramImpl::WriteLocalCoord(GrGLSLVertexBuilder* vertBuilder,
|
|||||||
&gpArgs->fLocalCoordVar,
|
&gpArgs->fLocalCoordVar,
|
||||||
localMatrixUniform);
|
localMatrixUniform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
using Attribute = GrGeometryProcessor::Attribute;
|
||||||
|
using AttributeSet = GrGeometryProcessor::AttributeSet;
|
||||||
|
|
||||||
|
GrGeometryProcessor::Attribute AttributeSet::Iter::operator*() const {
|
||||||
|
if (fCurr->offset().has_value()) {
|
||||||
|
return *fCurr;
|
||||||
|
}
|
||||||
|
return Attribute(fCurr->name(), fCurr->cpuType(), fCurr->gpuType(), fImplicitOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttributeSet::Iter::operator++() {
|
||||||
|
if (fRemaining) {
|
||||||
|
fRemaining--;
|
||||||
|
fImplicitOffset += Attribute::AlignOffset(fCurr->size());
|
||||||
|
fCurr++;
|
||||||
|
this->skipUninitialized();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttributeSet::Iter::skipUninitialized() {
|
||||||
|
if (!fRemaining) {
|
||||||
|
fCurr = nullptr;
|
||||||
|
} else {
|
||||||
|
while (!fCurr->isInitialized()) {
|
||||||
|
++fCurr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttributeSet::initImplicit(const Attribute* attrs, int count) {
|
||||||
|
fAttributes = attrs;
|
||||||
|
fRawCount = count;
|
||||||
|
fCount = 0;
|
||||||
|
fStride = 0;
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
if (attrs[i].isInitialized()) {
|
||||||
|
fCount++;
|
||||||
|
fStride += Attribute::AlignOffset(attrs[i].size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttributeSet::initExplicit(const Attribute* attrs, int count, size_t stride) {
|
||||||
|
fAttributes = attrs;
|
||||||
|
fRawCount = count;
|
||||||
|
fCount = count;
|
||||||
|
fStride = stride;
|
||||||
|
SkASSERT(Attribute::AlignOffset(fStride) == fStride);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
SkASSERT(attrs[i].isInitialized());
|
||||||
|
SkASSERT(attrs[i].offset().has_value());
|
||||||
|
SkASSERT(Attribute::AlignOffset(*attrs[i].offset()) == *attrs[i].offset());
|
||||||
|
SkASSERT(*attrs[i].offset() + attrs[i].size() <= fStride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttributeSet::addToKey(GrProcessorKeyBuilder* b) const {
|
||||||
|
int rawCount = SkAbs32(fRawCount);
|
||||||
|
b->addBits(16, SkToU16(this->stride()), "stride");
|
||||||
|
b->addBits(16, rawCount, "attribute count");
|
||||||
|
size_t implicitOffset = 0;
|
||||||
|
for (int i = 0; i < rawCount; ++i) {
|
||||||
|
const Attribute& attr = fAttributes[i];
|
||||||
|
b->appendComment(attr.isInitialized() ? attr.name() : "unusedAttr");
|
||||||
|
static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
|
||||||
|
static_assert(kGrSLTypeCount < (1 << 8), "");
|
||||||
|
b->addBits(8, attr.isInitialized() ? attr.cpuType() : 0xff, "attrType");
|
||||||
|
b->addBits(8 , attr.isInitialized() ? attr.gpuType() : 0xff, "attrGpuType");
|
||||||
|
int16_t offset = -1;
|
||||||
|
if (attr.isInitialized()) {
|
||||||
|
if (attr.offset().has_value()) {
|
||||||
|
offset = *attr.offset();
|
||||||
|
} else {
|
||||||
|
offset = implicitOffset;
|
||||||
|
implicitOffset += Attribute::AlignOffset(attr.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b->addBits(16, static_cast<uint16_t>(offset), "attrOffset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AttributeSet::Iter AttributeSet::begin() const { return Iter(fAttributes, fCount); }
|
||||||
|
AttributeSet::Iter AttributeSet::end() const { return Iter(); }
|
||||||
|
@ -63,98 +63,111 @@ public:
|
|||||||
/** Describes a vertex or instance attribute. */
|
/** Describes a vertex or instance attribute. */
|
||||||
class Attribute {
|
class Attribute {
|
||||||
public:
|
public:
|
||||||
|
static constexpr size_t AlignOffset(size_t offset) { return SkAlign4(offset); }
|
||||||
|
|
||||||
constexpr Attribute() = default;
|
constexpr Attribute() = default;
|
||||||
|
/**
|
||||||
|
* Makes an attribute whose offset will be implicitly determined by the types and ordering
|
||||||
|
* of an array attributes.
|
||||||
|
*/
|
||||||
constexpr Attribute(const char* name,
|
constexpr Attribute(const char* name,
|
||||||
GrVertexAttribType cpuType,
|
GrVertexAttribType cpuType,
|
||||||
GrSLType gpuType)
|
GrSLType gpuType)
|
||||||
: fName(name), fCPUType(cpuType), fGPUType(gpuType) {
|
: fName(name), fCPUType(cpuType), fGPUType(gpuType) {
|
||||||
SkASSERT(name && gpuType != kVoid_GrSLType);
|
SkASSERT(name && gpuType != kVoid_GrSLType);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Makes an attribute with an explicit offset.
|
||||||
|
*/
|
||||||
|
constexpr Attribute(const char* name,
|
||||||
|
GrVertexAttribType cpuType,
|
||||||
|
GrSLType gpuType,
|
||||||
|
size_t offset)
|
||||||
|
: fName(name), fCPUType(cpuType), fGPUType(gpuType), fOffset(SkToU32(offset)) {
|
||||||
|
SkASSERT(AlignOffset(offset) == offset);
|
||||||
|
SkASSERT(name && gpuType != kVoid_GrSLType);
|
||||||
|
}
|
||||||
constexpr Attribute(const Attribute&) = default;
|
constexpr Attribute(const Attribute&) = default;
|
||||||
|
|
||||||
Attribute& operator=(const Attribute&) = default;
|
Attribute& operator=(const Attribute&) = default;
|
||||||
|
|
||||||
constexpr bool isInitialized() const { return fGPUType != kVoid_GrSLType; }
|
constexpr bool isInitialized() const { return fGPUType != kVoid_GrSLType; }
|
||||||
|
|
||||||
constexpr const char* name() const { return fName; }
|
constexpr const char* name() const { return fName; }
|
||||||
constexpr GrVertexAttribType cpuType() const { return fCPUType; }
|
constexpr GrVertexAttribType cpuType() const { return fCPUType; }
|
||||||
constexpr GrSLType gpuType() const { return fGPUType; }
|
constexpr GrSLType gpuType() const { return fGPUType; }
|
||||||
|
/**
|
||||||
|
* Returns the offset if attributes were specified with explicit offsets. Otherwise,
|
||||||
|
* offsets (and total vertex stride) are implicitly determined from attribute order and
|
||||||
|
* types.
|
||||||
|
*/
|
||||||
|
skstd::optional<size_t> offset() const {
|
||||||
|
if (fOffset != kImplicitOffset) {
|
||||||
|
SkASSERT(AlignOffset(fOffset) == fOffset);
|
||||||
|
return {fOffset};
|
||||||
|
}
|
||||||
|
return skstd::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
inline constexpr size_t size() const;
|
inline constexpr size_t size() const;
|
||||||
constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
|
|
||||||
|
|
||||||
GrShaderVar asShaderVar() const {
|
GrShaderVar asShaderVar() const {
|
||||||
return {fName, fGPUType, GrShaderVar::TypeModifier::In};
|
return {fName, fGPUType, GrShaderVar::TypeModifier::In};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* fName = nullptr;
|
static constexpr uint32_t kImplicitOffset = 1; // 1 is not valid because it isn't aligned.
|
||||||
|
|
||||||
|
const char* fName = nullptr;
|
||||||
GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
|
GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
|
||||||
GrSLType fGPUType = kVoid_GrSLType;
|
GrSLType fGPUType = kVoid_GrSLType;
|
||||||
|
uint32_t fOffset = kImplicitOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Iter {
|
/**
|
||||||
public:
|
* A set of attributes that can iterated. The iterator handles hides two pieces of complexity:
|
||||||
Iter() : fCurr(nullptr), fRemaining(0) {}
|
* 1) It skips uninitialized attributes.
|
||||||
Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {}
|
* 2) It always returns an attribute with a known offset.
|
||||||
Iter& operator= (const Iter& iter) {
|
*/
|
||||||
fCurr = iter.fCurr;
|
class AttributeSet {
|
||||||
fRemaining = iter.fRemaining;
|
class Iter {
|
||||||
return *this;
|
public:
|
||||||
}
|
Iter() = default;
|
||||||
Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
|
Iter(const Iter& iter) = default;
|
||||||
this->skipUninitialized();
|
Iter& operator=(const Iter& iter) = default;
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
|
Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
|
||||||
const Attribute& operator*() const { return *fCurr; }
|
|
||||||
void operator++() {
|
|
||||||
if (fRemaining) {
|
|
||||||
fRemaining--;
|
|
||||||
fCurr++;
|
|
||||||
this->skipUninitialized();
|
this->skipUninitialized();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
|
||||||
void skipUninitialized() {
|
Attribute operator*() const;
|
||||||
if (!fRemaining) {
|
void operator++();
|
||||||
fCurr = nullptr;
|
|
||||||
} else {
|
|
||||||
while (!fCurr->isInitialized()) {
|
|
||||||
++fCurr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Attribute* fCurr;
|
private:
|
||||||
int fRemaining;
|
void skipUninitialized();
|
||||||
};
|
|
||||||
|
const Attribute* fCurr = nullptr;
|
||||||
|
int fRemaining = 0;
|
||||||
|
size_t fImplicitOffset = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class AttributeSet {
|
|
||||||
public:
|
public:
|
||||||
Iter begin() const { return Iter(fAttributes, fCount); }
|
Iter begin() const;
|
||||||
Iter end() const { return Iter(); }
|
Iter end() const;
|
||||||
|
|
||||||
int count() const { return fCount; }
|
int count() const { return fCount; }
|
||||||
size_t stride() const { return fStride; }
|
size_t stride() const { return fStride; }
|
||||||
|
|
||||||
|
// Init with implicit offsets and stride. No attributes can have a predetermined stride.
|
||||||
|
void initImplicit(const Attribute* attrs, int count);
|
||||||
|
// Init with explicit offsets and stride. All attributes must be initialized and have
|
||||||
|
// an explicit offset aligned to 4 bytes and with no attribute crossing stride boundaries.
|
||||||
|
void initExplicit(const Attribute* attrs, int count, size_t stride);
|
||||||
|
|
||||||
|
void addToKey(GrProcessorKeyBuilder* b) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GrGeometryProcessor;
|
|
||||||
|
|
||||||
void init(const Attribute* attrs, int count) {
|
|
||||||
fAttributes = attrs;
|
|
||||||
fRawCount = count;
|
|
||||||
fCount = 0;
|
|
||||||
fStride = 0;
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
if (attrs[i].isInitialized()) {
|
|
||||||
fCount++;
|
|
||||||
fStride += attrs[i].sizeAlign4();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Attribute* fAttributes = nullptr;
|
const Attribute* fAttributes = nullptr;
|
||||||
int fRawCount = 0;
|
int fRawCount = 0;
|
||||||
int fCount = 0;
|
int fCount = 0;
|
||||||
@ -165,21 +178,21 @@ public:
|
|||||||
|
|
||||||
int numTextureSamplers() const { return fTextureSamplerCnt; }
|
int numTextureSamplers() const { return fTextureSamplerCnt; }
|
||||||
const TextureSampler& textureSampler(int index) const;
|
const TextureSampler& textureSampler(int index) const;
|
||||||
int numVertexAttributes() const { return fVertexAttributes.fCount; }
|
int numVertexAttributes() const { return fVertexAttributes.count(); }
|
||||||
const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
|
const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
|
||||||
int numInstanceAttributes() const { return fInstanceAttributes.fCount; }
|
int numInstanceAttributes() const { return fInstanceAttributes.count(); }
|
||||||
const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
|
const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
|
||||||
|
|
||||||
bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); }
|
bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.count()); }
|
||||||
bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.fCount); }
|
bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.count()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A common practice is to populate the the vertex/instance's memory using an implicit array of
|
* A common practice is to populate the the vertex/instance's memory using an implicit array of
|
||||||
* structs. In this case, it is best to assert that:
|
* structs. In this case, it is best to assert that:
|
||||||
* stride == sizeof(struct)
|
* stride == sizeof(struct)
|
||||||
*/
|
*/
|
||||||
size_t vertexStride() const { return fVertexAttributes.fStride; }
|
size_t vertexStride() const { return fVertexAttributes.stride(); }
|
||||||
size_t instanceStride() const { return fInstanceAttributes.fStride; }
|
size_t instanceStride() const { return fInstanceAttributes.stride(); }
|
||||||
|
|
||||||
bool willUseTessellationShaders() const {
|
bool willUseTessellationShaders() const {
|
||||||
return fShaders & (kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag);
|
return fShaders & (kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag);
|
||||||
@ -200,23 +213,10 @@ public:
|
|||||||
virtual void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
|
virtual void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
|
||||||
|
|
||||||
void getAttributeKey(GrProcessorKeyBuilder* b) const {
|
void getAttributeKey(GrProcessorKeyBuilder* b) const {
|
||||||
// Ensure that our CPU and GPU type fields fit together in a 32-bit value, and we never
|
b->appendComment("vertex attributes");
|
||||||
// collide with the "uninitialized" value.
|
fVertexAttributes.addToKey(b);
|
||||||
static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
|
b->appendComment("instance attributes");
|
||||||
static_assert(kGrSLTypeCount < (1 << 8), "");
|
fInstanceAttributes.addToKey(b);
|
||||||
|
|
||||||
auto add_attributes = [=](const Attribute* attrs, int attrCount) {
|
|
||||||
for (int i = 0; i < attrCount; ++i) {
|
|
||||||
const Attribute& attr = attrs[i];
|
|
||||||
b->appendComment(attr.isInitialized() ? attr.name() : "unusedAttr");
|
|
||||||
b->addBits(8, attr.isInitialized() ? attr.cpuType() : 0xff, "attrType");
|
|
||||||
b->addBits(8, attr.isInitialized() ? attr.gpuType() : 0xff, "attrGpuType");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
b->add32(fVertexAttributes.fRawCount, "numVertexAttributes");
|
|
||||||
add_attributes(fVertexAttributes.fAttributes, fVertexAttributes.fRawCount);
|
|
||||||
b->add32(fInstanceAttributes.fRawCount, "numInstanceAttributes");
|
|
||||||
add_attributes(fInstanceAttributes.fAttributes, fInstanceAttributes.fRawCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,13 +233,20 @@ protected:
|
|||||||
wideColor ? kFloat4_GrVertexAttribType : kUByte4_norm_GrVertexAttribType,
|
wideColor ? kFloat4_GrVertexAttribType : kUByte4_norm_GrVertexAttribType,
|
||||||
kHalf4_GrSLType };
|
kHalf4_GrSLType };
|
||||||
}
|
}
|
||||||
|
void setVertexAttributes(const Attribute* attrs, int attrCount, size_t stride) {
|
||||||
void setVertexAttributes(const Attribute* attrs, int attrCount) {
|
fVertexAttributes.initExplicit(attrs, attrCount, stride);
|
||||||
fVertexAttributes.init(attrs, attrCount);
|
|
||||||
}
|
}
|
||||||
void setInstanceAttributes(const Attribute* attrs, int attrCount) {
|
void setInstanceAttributes(const Attribute* attrs, int attrCount, size_t stride) {
|
||||||
SkASSERT(attrCount >= 0);
|
SkASSERT(attrCount >= 0);
|
||||||
fInstanceAttributes.init(attrs, attrCount);
|
fInstanceAttributes.initExplicit(attrs, attrCount, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVertexAttributesWithImplicitOffsets(const Attribute* attrs, int attrCount) {
|
||||||
|
fVertexAttributes.initImplicit(attrs, attrCount);
|
||||||
|
}
|
||||||
|
void setInstanceAttributesWithImplicitOffsets(const Attribute* attrs, int attrCount) {
|
||||||
|
SkASSERT(attrCount >= 0);
|
||||||
|
fInstanceAttributes.initImplicit(attrs, attrCount);
|
||||||
}
|
}
|
||||||
void setWillUseTessellationShaders() {
|
void setWillUseTessellationShaders() {
|
||||||
fShaders |= kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag;
|
fShaders |= kTessControl_GrShaderFlag | kTessEvaluation_GrShaderFlag;
|
||||||
|
@ -32,6 +32,7 @@ public:
|
|||||||
enum ClassID {
|
enum ClassID {
|
||||||
kNull_ClassID, // Reserved ID for missing (null) processors
|
kNull_ClassID, // Reserved ID for missing (null) processors
|
||||||
|
|
||||||
|
kAttributeTestProcessor_ClassID,
|
||||||
kBigKeyProcessor_ClassID,
|
kBigKeyProcessor_ClassID,
|
||||||
kBlendFragmentProcessor_ClassID,
|
kBlendFragmentProcessor_ClassID,
|
||||||
kBlockInputFragmentProcessor_ClassID,
|
kBlockInputFragmentProcessor_ClassID,
|
||||||
|
@ -245,32 +245,26 @@ static void setup_vertex_input_layout(const GrGeometryProcessor& geomProc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int currentAttrib = 0;
|
unsigned int currentAttrib = 0;
|
||||||
unsigned int vertexAttributeOffset = 0;
|
|
||||||
|
|
||||||
for (const auto& attrib : geomProc.vertexAttributes()) {
|
for (auto attrib : geomProc.vertexAttributes()) {
|
||||||
// When using SPIRV-Cross it converts the location modifier in SPIRV to be
|
// When using SPIRV-Cross it converts the location modifier in SPIRV to be
|
||||||
// TEXCOORD<N> where N is the location value for eveery vertext attribute
|
// TEXCOORD<N> where N is the location value for eveery vertext attribute
|
||||||
inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
|
inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
|
||||||
attrib_type_to_format(attrib.cpuType()),
|
attrib_type_to_format(attrib.cpuType()),
|
||||||
vertexSlot, vertexAttributeOffset,
|
vertexSlot, SkToU32(*attrib.offset()),
|
||||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 };
|
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 };
|
||||||
vertexAttributeOffset += attrib.sizeAlign4();
|
|
||||||
currentAttrib++;
|
currentAttrib++;
|
||||||
}
|
}
|
||||||
SkASSERT(vertexAttributeOffset == geomProc.vertexStride());
|
|
||||||
|
|
||||||
unsigned int instanceAttributeOffset = 0;
|
for (auto attrib : geomProc.instanceAttributes()) {
|
||||||
for (const auto& attrib : geomProc.instanceAttributes()) {
|
|
||||||
// When using SPIRV-Cross it converts the location modifier in SPIRV to be
|
// When using SPIRV-Cross it converts the location modifier in SPIRV to be
|
||||||
// TEXCOORD<N> where N is the location value for eveery vertext attribute
|
// TEXCOORD<N> where N is the location value for eveery vertext attribute
|
||||||
inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
|
inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
|
||||||
attrib_type_to_format(attrib.cpuType()),
|
attrib_type_to_format(attrib.cpuType()),
|
||||||
instanceSlot, instanceAttributeOffset,
|
instanceSlot, SkToU32(*attrib.offset()),
|
||||||
D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 };
|
D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 };
|
||||||
instanceAttributeOffset += attrib.sizeAlign4();
|
|
||||||
currentAttrib++;
|
currentAttrib++;
|
||||||
}
|
}
|
||||||
SkASSERT(instanceAttributeOffset == geomProc.instanceStride());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) {
|
static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) {
|
||||||
|
@ -338,18 +338,16 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
|
|||||||
const GrGeometryProcessor& geomProc = programInfo.geomProc();
|
const GrGeometryProcessor& geomProc = programInfo.geomProc();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (geomProc.numVertexAttributes() > 0) {
|
if (geomProc.numVertexAttributes() > 0) {
|
||||||
size_t offset = 0;
|
for (auto attrib : geomProc.vertexAttributes()) {
|
||||||
for (const auto& attrib : geomProc.vertexAttributes()) {
|
|
||||||
wgpu::VertexAttribute attribute;
|
wgpu::VertexAttribute attribute;
|
||||||
attribute.shaderLocation = i;
|
attribute.shaderLocation = i;
|
||||||
attribute.offset = offset;
|
attribute.offset = *attrib.offset();
|
||||||
attribute.format = to_dawn_vertex_format(attrib.cpuType());
|
attribute.format = to_dawn_vertex_format(attrib.cpuType());
|
||||||
vertexAttributes.push_back(attribute);
|
vertexAttributes.push_back(attribute);
|
||||||
offset += attrib.sizeAlign4();
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
wgpu::VertexBufferLayout input;
|
wgpu::VertexBufferLayout input;
|
||||||
input.arrayStride = offset;
|
input.arrayStride = geomProc.vertexStride();
|
||||||
input.stepMode = wgpu::VertexStepMode::Vertex;
|
input.stepMode = wgpu::VertexStepMode::Vertex;
|
||||||
input.attributeCount = vertexAttributes.size();
|
input.attributeCount = vertexAttributes.size();
|
||||||
input.attributes = &vertexAttributes.front();
|
input.attributes = &vertexAttributes.front();
|
||||||
@ -357,18 +355,16 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
|
|||||||
}
|
}
|
||||||
std::vector<wgpu::VertexAttribute> instanceAttributes;
|
std::vector<wgpu::VertexAttribute> instanceAttributes;
|
||||||
if (geomProc.numInstanceAttributes() > 0) {
|
if (geomProc.numInstanceAttributes() > 0) {
|
||||||
size_t offset = 0;
|
for (auto attrib : geomProc.instanceAttributes()) {
|
||||||
for (const auto& attrib : geomProc.instanceAttributes()) {
|
|
||||||
wgpu::VertexAttribute attribute;
|
wgpu::VertexAttribute attribute;
|
||||||
attribute.shaderLocation = i;
|
attribute.shaderLocation = i;
|
||||||
attribute.offset = offset;
|
attribute.offset = *attrib.offset();
|
||||||
attribute.format = to_dawn_vertex_format(attrib.cpuType());
|
attribute.format = to_dawn_vertex_format(attrib.cpuType());
|
||||||
instanceAttributes.push_back(attribute);
|
instanceAttributes.push_back(attribute);
|
||||||
offset += attrib.sizeAlign4();
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
wgpu::VertexBufferLayout input;
|
wgpu::VertexBufferLayout input;
|
||||||
input.arrayStride = offset;
|
input.arrayStride = geomProc.instanceStride();
|
||||||
input.stepMode = wgpu::VertexStepMode::Instance;
|
input.stepMode = wgpu::VertexStepMode::Instance;
|
||||||
input.attributeCount = instanceAttributes.size();
|
input.attributeCount = instanceAttributes.size();
|
||||||
input.attributes = &instanceAttributes.front();
|
input.attributes = &instanceAttributes.front();
|
||||||
|
@ -175,7 +175,7 @@ GrConicEffect::GrConicEffect(const SkPMColor4f& color, const SkMatrix& viewMatri
|
|||||||
, fLocalMatrix(viewMatrix)
|
, fLocalMatrix(viewMatrix)
|
||||||
, fUsesLocalCoords(usesLocalCoords)
|
, fUsesLocalCoords(usesLocalCoords)
|
||||||
, fCoverageScale(coverage) {
|
, fCoverageScale(coverage) {
|
||||||
this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
|
this->setVertexAttributesWithImplicitOffsets(kAttributes, SK_ARRAY_COUNT(kAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -328,7 +328,7 @@ GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix,
|
|||||||
, fLocalMatrix(localMatrix)
|
, fLocalMatrix(localMatrix)
|
||||||
, fUsesLocalCoords(usesLocalCoords)
|
, fUsesLocalCoords(usesLocalCoords)
|
||||||
, fCoverageScale(coverage) {
|
, fCoverageScale(coverage) {
|
||||||
this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
|
this->setVertexAttributesWithImplicitOffsets(kAttributes, SK_ARRAY_COUNT(kAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -140,7 +140,7 @@ GrBitmapTextGeoProc::GrBitmapTextGeoProc(const GrShaderCaps& caps,
|
|||||||
|
|
||||||
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
||||||
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
|
|
||||||
if (numActiveViews) {
|
if (numActiveViews) {
|
||||||
fAtlasDimensions = views[0].proxy()->dimensions();
|
fAtlasDimensions = views[0].proxy()->dimensions();
|
||||||
|
@ -228,7 +228,7 @@ GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(const GrShaderCaps& c
|
|||||||
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType };
|
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType };
|
||||||
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
||||||
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
|
|
||||||
if (numViews) {
|
if (numViews) {
|
||||||
fAtlasDimensions = views[0].proxy()->dimensions();
|
fAtlasDimensions = views[0].proxy()->dimensions();
|
||||||
@ -494,7 +494,7 @@ GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(const GrShaderCaps& caps,
|
|||||||
fInColor = MakeColorAttribute("inColor", wideColor);
|
fInColor = MakeColorAttribute("inColor", wideColor);
|
||||||
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
||||||
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
|
|
||||||
if (numViews) {
|
if (numViews) {
|
||||||
fAtlasDimensions = views[0].proxy()->dimensions();
|
fAtlasDimensions = views[0].proxy()->dimensions();
|
||||||
@ -807,7 +807,7 @@ GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(const GrShaderCaps&
|
|||||||
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
||||||
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
|
||||||
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
|
|
||||||
if (numViews) {
|
if (numViews) {
|
||||||
fAtlasDimensions = views[0].proxy()->dimensions();
|
fAtlasDimensions = views[0].proxy()->dimensions();
|
||||||
|
@ -56,7 +56,7 @@ GrRRectShadowGeoProc::GrRRectShadowGeoProc(const GrSurfaceProxyView& lutView)
|
|||||||
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
||||||
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
||||||
fInShadowParams = {"inShadowParams", kFloat3_GrVertexAttribType, kHalf3_GrSLType};
|
fInShadowParams = {"inShadowParams", kFloat3_GrVertexAttribType, kHalf3_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
|
|
||||||
SkASSERT(lutView.proxy());
|
SkASSERT(lutView.proxy());
|
||||||
fLUTTextureSampler.reset(GrSamplerState::Filter::kLinear, lutView.proxy()->backendFormat(),
|
fLUTTextureSampler.reset(GrSamplerState::Filter::kLinear, lutView.proxy()->backendFormat(),
|
||||||
|
@ -123,25 +123,23 @@ void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID,
|
|||||||
fInstanceAttributeCnt = geomProc.numInstanceAttributes();
|
fInstanceAttributeCnt = geomProc.numInstanceAttributes();
|
||||||
fAttributes = std::make_unique<GrGLProgram::Attribute[]>(
|
fAttributes = std::make_unique<GrGLProgram::Attribute[]>(
|
||||||
fVertexAttributeCnt + fInstanceAttributeCnt);
|
fVertexAttributeCnt + fInstanceAttributeCnt);
|
||||||
auto addAttr = [&](int i, const auto& a, size_t* stride) {
|
auto addAttr = [&](int i, const auto& a) {
|
||||||
fAttributes[i].fCPUType = a.cpuType();
|
fAttributes[i].fCPUType = a.cpuType();
|
||||||
fAttributes[i].fGPUType = a.gpuType();
|
fAttributes[i].fGPUType = a.gpuType();
|
||||||
fAttributes[i].fOffset = *stride;
|
fAttributes[i].fOffset = *a.offset();
|
||||||
*stride += a.sizeAlign4();
|
|
||||||
fAttributes[i].fLocation = i;
|
fAttributes[i].fLocation = i;
|
||||||
if (bindAttribLocations) {
|
if (bindAttribLocations) {
|
||||||
GL_CALL(BindAttribLocation(programID, i, a.name()));
|
GL_CALL(BindAttribLocation(programID, i, a.name()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fVertexStride = 0;
|
fVertexStride = geomProc.vertexStride();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& attr : geomProc.vertexAttributes()) {
|
for (auto attr : geomProc.vertexAttributes()) {
|
||||||
addAttr(i++, attr, &fVertexStride);
|
addAttr(i++, attr);
|
||||||
}
|
}
|
||||||
SkASSERT(fVertexStride == geomProc.vertexStride());
|
fInstanceStride = geomProc.instanceStride();
|
||||||
fInstanceStride = 0;
|
for (auto attr : geomProc.instanceAttributes()) {
|
||||||
for (const auto& attr : geomProc.instanceAttributes()) {
|
addAttr(i++, attr);
|
||||||
addAttr(i++, attr, &fInstanceStride);
|
|
||||||
}
|
}
|
||||||
SkASSERT(fInstanceStride == geomProc.instanceStride());
|
SkASSERT(fInstanceStride == geomProc.instanceStride());
|
||||||
}
|
}
|
||||||
@ -192,10 +190,10 @@ void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs,
|
|||||||
meta.fSettings = settings;
|
meta.fSettings = settings;
|
||||||
meta.fHasCustomColorOutput = fFS.hasCustomColorOutput();
|
meta.fHasCustomColorOutput = fFS.hasCustomColorOutput();
|
||||||
meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
|
meta.fHasSecondaryColorOutput = fFS.hasSecondaryOutput();
|
||||||
for (const auto& attr : this->geometryProcessor().vertexAttributes()) {
|
for (auto attr : this->geometryProcessor().vertexAttributes()) {
|
||||||
meta.fAttributeNames.emplace_back(attr.name());
|
meta.fAttributeNames.emplace_back(attr.name());
|
||||||
}
|
}
|
||||||
for (const auto& attr : this->geometryProcessor().instanceAttributes()) {
|
for (auto attr : this->geometryProcessor().instanceAttributes()) {
|
||||||
meta.fAttributeNames.emplace_back(attr.name());
|
meta.fAttributeNames.emplace_back(attr.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +58,10 @@ void GrGLSLVaryingHandler::addVarying(const char* name, GrGLSLVarying* varying,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) {
|
void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) {
|
||||||
for (const auto& attr : gp.vertexAttributes()) {
|
for (auto attr : gp.vertexAttributes()) {
|
||||||
this->addAttribute(attr.asShaderVar());
|
this->addAttribute(attr.asShaderVar());
|
||||||
}
|
}
|
||||||
for (const auto& attr : gp.instanceAttributes()) {
|
for (auto attr : gp.instanceAttributes()) {
|
||||||
this->addAttribute(attr.asShaderVar());
|
this->addAttribute(attr.asShaderVar());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,33 +199,30 @@ static MTLVertexDescriptor* create_vertex_descriptor(const GrGeometryProcessor&
|
|||||||
if (writer) {
|
if (writer) {
|
||||||
writer->writeInt(vertexAttributeCount);
|
writer->writeInt(vertexAttributeCount);
|
||||||
}
|
}
|
||||||
size_t vertexAttributeOffset = 0;
|
for (auto attribute : geomProc.vertexAttributes()) {
|
||||||
for (const auto& attribute : geomProc.vertexAttributes()) {
|
|
||||||
MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
|
MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
|
||||||
MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
|
MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
|
||||||
SkASSERT(MTLVertexFormatInvalid != format);
|
SkASSERT(MTLVertexFormatInvalid != format);
|
||||||
mtlAttribute.format = format;
|
mtlAttribute.format = format;
|
||||||
mtlAttribute.offset = vertexAttributeOffset;
|
mtlAttribute.offset = *attribute.offset();
|
||||||
mtlAttribute.bufferIndex = vertexBinding;
|
mtlAttribute.bufferIndex = vertexBinding;
|
||||||
if (writer) {
|
if (writer) {
|
||||||
writer->writeInt(format);
|
writer->writeInt(format);
|
||||||
writer->writeUInt(vertexAttributeOffset);
|
writer->writeUInt(*attribute.offset());
|
||||||
writer->writeUInt(vertexBinding);
|
writer->writeUInt(vertexBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
vertexAttributeOffset += attribute.sizeAlign4();
|
|
||||||
attributeIndex++;
|
attributeIndex++;
|
||||||
}
|
}
|
||||||
SkASSERT(vertexAttributeOffset == geomProc.vertexStride());
|
|
||||||
|
|
||||||
if (vertexAttributeCount) {
|
if (vertexAttributeCount) {
|
||||||
MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
|
MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
|
||||||
vertexDescriptor.layouts[vertexBinding];
|
vertexDescriptor.layouts[vertexBinding];
|
||||||
vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
|
vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
|
||||||
vertexBufferLayout.stepRate = 1;
|
vertexBufferLayout.stepRate = 1;
|
||||||
vertexBufferLayout.stride = vertexAttributeOffset;
|
vertexBufferLayout.stride = geomProc.vertexStride();
|
||||||
if (writer) {
|
if (writer) {
|
||||||
writer->writeUInt(vertexAttributeOffset);
|
writer->writeUInt(geomProc.vertexStride());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,33 +230,30 @@ static MTLVertexDescriptor* create_vertex_descriptor(const GrGeometryProcessor&
|
|||||||
if (writer) {
|
if (writer) {
|
||||||
writer->writeInt(instanceAttributeCount);
|
writer->writeInt(instanceAttributeCount);
|
||||||
}
|
}
|
||||||
size_t instanceAttributeOffset = 0;
|
for (auto attribute : geomProc.instanceAttributes()) {
|
||||||
for (const auto& attribute : geomProc.instanceAttributes()) {
|
|
||||||
MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
|
MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
|
||||||
MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
|
MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
|
||||||
SkASSERT(MTLVertexFormatInvalid != format);
|
SkASSERT(MTLVertexFormatInvalid != format);
|
||||||
mtlAttribute.format = format;
|
mtlAttribute.format = format;
|
||||||
mtlAttribute.offset = instanceAttributeOffset;
|
mtlAttribute.offset = *attribute.offset();
|
||||||
mtlAttribute.bufferIndex = instanceBinding;
|
mtlAttribute.bufferIndex = instanceBinding;
|
||||||
if (writer) {
|
if (writer) {
|
||||||
writer->writeInt(format);
|
writer->writeInt(format);
|
||||||
writer->writeUInt(instanceAttributeOffset);
|
writer->writeUInt(*attribute.offset());
|
||||||
writer->writeUInt(instanceBinding);
|
writer->writeUInt(instanceBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceAttributeOffset += attribute.sizeAlign4();
|
|
||||||
attributeIndex++;
|
attributeIndex++;
|
||||||
}
|
}
|
||||||
SkASSERT(instanceAttributeOffset == geomProc.instanceStride());
|
|
||||||
|
|
||||||
if (instanceAttributeCount) {
|
if (instanceAttributeCount) {
|
||||||
MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
|
MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
|
||||||
vertexDescriptor.layouts[instanceBinding];
|
vertexDescriptor.layouts[instanceBinding];
|
||||||
instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
|
instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
|
||||||
instanceBufferLayout.stepRate = 1;
|
instanceBufferLayout.stepRate = 1;
|
||||||
instanceBufferLayout.stride = instanceAttributeOffset;
|
instanceBufferLayout.stride = geomProc.instanceStride();
|
||||||
if (writer) {
|
if (writer) {
|
||||||
writer->writeUInt(instanceAttributeOffset);
|
writer->writeUInt(geomProc.instanceStride());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vertexDescriptor;
|
return vertexDescriptor;
|
||||||
|
@ -577,7 +577,7 @@ private:
|
|||||||
fInColor = MakeColorAttribute("inColor", wideColor);
|
fInColor = MakeColorAttribute("inColor", wideColor);
|
||||||
// GL on iOS 14 needs more precision for the quadedge attributes
|
// GL on iOS 14 needs more precision for the quadedge attributes
|
||||||
fInQuadEdge = {"inQuadEdge", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
fInQuadEdge = {"inQuadEdge", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute fInPosition;
|
Attribute fInPosition;
|
||||||
|
@ -867,7 +867,7 @@ DashingCircleEffect::DashingCircleEffect(const SkPMColor4f& color,
|
|||||||
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
||||||
fInDashParams = {"inDashParams", kFloat3_GrVertexAttribType, kHalf3_GrSLType};
|
fInDashParams = {"inDashParams", kFloat3_GrVertexAttribType, kHalf3_GrSLType};
|
||||||
fInCircleParams = {"inCircleParams", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
fInCircleParams = {"inCircleParams", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingCircleEffect);
|
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingCircleEffect);
|
||||||
@ -1081,7 +1081,7 @@ DashingLineEffect::DashingLineEffect(const SkPMColor4f& color,
|
|||||||
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
||||||
fInDashParams = {"inDashParams", kFloat3_GrVertexAttribType, kHalf3_GrSLType};
|
fInDashParams = {"inDashParams", kFloat3_GrVertexAttribType, kHalf3_GrSLType};
|
||||||
fInRect = {"inRect", kFloat4_GrVertexAttribType, kHalf4_GrSLType};
|
fInRect = {"inRect", kFloat4_GrVertexAttribType, kHalf4_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingLineEffect);
|
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingLineEffect);
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
if (!shaderCaps.vertexIDSupport()) {
|
if (!shaderCaps.vertexIDSupport()) {
|
||||||
constexpr static Attribute kUnitCoordAttrib(
|
constexpr static Attribute kUnitCoordAttrib(
|
||||||
"unitCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
|
"unitCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
|
||||||
this->setVertexAttributes(&kUnitCoordAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kUnitCoordAttrib, 1);
|
||||||
}
|
}
|
||||||
fAttribs.emplace_back("fillBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
|
fAttribs.emplace_back("fillBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
|
||||||
if (fUsesLocalCoords) {
|
if (fUsesLocalCoords) {
|
||||||
@ -44,7 +44,7 @@ public:
|
|||||||
fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType);
|
fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType);
|
||||||
fAtlasHelper->appendInstanceAttribs(&fAttribs);
|
fAtlasHelper->appendInstanceAttribs(&fAttribs);
|
||||||
SkASSERT(fAttribs.count() <= kMaxInstanceAttribs);
|
SkASSERT(fAttribs.count() <= kMaxInstanceAttribs);
|
||||||
this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
|
this->setInstanceAttributesWithImplicitOffsets(fAttribs.data(), fAttribs.count());
|
||||||
this->setTextureSamplerCnt(1);
|
this->setTextureSamplerCnt(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ private:
|
|||||||
? Attribute{"inLocalCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType}
|
? Attribute{"inLocalCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType}
|
||||||
: missingAttr);
|
: missingAttr);
|
||||||
|
|
||||||
this->setVertexAttributes(fAttributes.data(), fAttributes.size());
|
this->setVertexAttributesWithImplicitOffsets(fAttributes.data(), fAttributes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -353,7 +353,8 @@ private:
|
|||||||
Processor(GrAAType aaType, ProcessorFlags flags)
|
Processor(GrAAType aaType, ProcessorFlags flags)
|
||||||
: GrGeometryProcessor(kGrFillRRectOp_Processor_ClassID)
|
: GrGeometryProcessor(kGrFillRRectOp_Processor_ClassID)
|
||||||
, fFlags(flags) {
|
, fFlags(flags) {
|
||||||
this->setVertexAttributes(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
|
this->setVertexAttributesWithImplicitOffsets(kVertexAttribs,
|
||||||
|
SK_ARRAY_COUNT(kVertexAttribs));
|
||||||
|
|
||||||
fInstanceAttribs.emplace_back("skew", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
|
fInstanceAttribs.emplace_back("skew", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
|
||||||
fInstanceAttribs.emplace_back("translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
|
fInstanceAttribs.emplace_back("translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
|
||||||
@ -366,7 +367,8 @@ private:
|
|||||||
"local_rect", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
|
"local_rect", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
|
||||||
}
|
}
|
||||||
SkASSERT(fInstanceAttribs.count() <= kMaxInstanceAttribs);
|
SkASSERT(fInstanceAttribs.count() <= kMaxInstanceAttribs);
|
||||||
this->setInstanceAttributes(fInstanceAttribs.begin(), fInstanceAttribs.count());
|
this->setInstanceAttributesWithImplicitOffsets(fInstanceAttribs.begin(),
|
||||||
|
fInstanceAttribs.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static constexpr Attribute kVertexAttribs[] = {
|
inline static constexpr Attribute kVertexAttribs[] = {
|
||||||
|
@ -118,7 +118,7 @@ private:
|
|||||||
fInRoundCapCenters =
|
fInRoundCapCenters =
|
||||||
{"inRoundCapCenters", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
{"inRoundCapCenters", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
||||||
}
|
}
|
||||||
this->setVertexAttributes(&fInPosition, 7);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Impl : public ProgramImpl {
|
class Impl : public ProgramImpl {
|
||||||
@ -298,7 +298,7 @@ private:
|
|||||||
fInColor = MakeColorAttribute("inColor", wideColor);
|
fInColor = MakeColorAttribute("inColor", wideColor);
|
||||||
fInCircleEdge = {"inCircleEdge", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
fInCircleEdge = {"inCircleEdge", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
||||||
fInDashParams = {"inDashParams", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
fInDashParams = {"inDashParams", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 4);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Impl : public ProgramImpl {
|
class Impl : public ProgramImpl {
|
||||||
@ -562,7 +562,7 @@ private:
|
|||||||
fInEllipseOffset = {"inEllipseOffset", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
fInEllipseOffset = {"inEllipseOffset", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
||||||
}
|
}
|
||||||
fInEllipseRadii = {"inEllipseRadii", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
fInEllipseRadii = {"inEllipseRadii", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 4);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Impl : public ProgramImpl {
|
class Impl : public ProgramImpl {
|
||||||
@ -761,7 +761,7 @@ private:
|
|||||||
kFloat2_GrSLType};
|
kFloat2_GrSLType};
|
||||||
}
|
}
|
||||||
fInEllipseOffsets1 = {"inEllipseOffsets1", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
fInEllipseOffsets1 = {"inEllipseOffsets1", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&fInPosition, 4);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Impl : public ProgramImpl {
|
class Impl : public ProgramImpl {
|
||||||
|
@ -111,7 +111,7 @@ private:
|
|||||||
fInTextureCoords = {"textureCoords", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
fInTextureCoords = {"textureCoords", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
|
||||||
fInTextureDomain = {"textureDomain", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
fInTextureDomain = {"textureDomain", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
||||||
fInColor = MakeColorAttribute("color", wideColor);
|
fInColor = MakeColorAttribute("color", wideColor);
|
||||||
this->setVertexAttributes(&fInPosition, 4);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
const TextureSampler& onTextureSampler(int) const override { return fSampler; }
|
const TextureSampler& onTextureSampler(int) const override { return fSampler; }
|
||||||
|
@ -36,13 +36,14 @@ public:
|
|||||||
// each patch that explicitly tells the shader what type of curve it is.
|
// each patch that explicitly tells the shader what type of curve it is.
|
||||||
fInstanceAttribs.emplace_back("curveType", kFloat_GrVertexAttribType, kFloat_GrSLType);
|
fInstanceAttribs.emplace_back("curveType", kFloat_GrVertexAttribType, kFloat_GrSLType);
|
||||||
}
|
}
|
||||||
this->setInstanceAttributes(fInstanceAttribs.data(), fInstanceAttribs.count());
|
this->setInstanceAttributesWithImplicitOffsets(fInstanceAttribs.data(),
|
||||||
|
fInstanceAttribs.count());
|
||||||
SkASSERT(fInstanceAttribs.count() <= kMaxInstanceAttribCount);
|
SkASSERT(fInstanceAttribs.count() <= kMaxInstanceAttribCount);
|
||||||
|
|
||||||
if (!shaderCaps.vertexIDSupport()) {
|
if (!shaderCaps.vertexIDSupport()) {
|
||||||
constexpr static Attribute kVertexIdxAttrib("vertexidx", kFloat_GrVertexAttribType,
|
constexpr static Attribute kVertexIdxAttrib("vertexidx", kFloat_GrVertexAttribType,
|
||||||
kFloat_GrSLType);
|
kFloat_GrSLType);
|
||||||
this->setVertexAttributes(&kVertexIdxAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kVertexIdxAttrib, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,14 +36,15 @@ public:
|
|||||||
if (!shaderCaps.vertexIDSupport()) {
|
if (!shaderCaps.vertexIDSupport()) {
|
||||||
constexpr static Attribute kUnitCoordAttrib("unitCoord", kFloat2_GrVertexAttribType,
|
constexpr static Attribute kUnitCoordAttrib("unitCoord", kFloat2_GrVertexAttribType,
|
||||||
kFloat2_GrSLType);
|
kFloat2_GrSLType);
|
||||||
this->setVertexAttributes(&kUnitCoordAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kUnitCoordAttrib, 1);
|
||||||
}
|
}
|
||||||
constexpr static Attribute kInstanceAttribs[] = {
|
constexpr static Attribute kInstanceAttribs[] = {
|
||||||
{"matrix2d", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
|
{"matrix2d", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
|
||||||
{"translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType},
|
{"translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType},
|
||||||
{"pathBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType}
|
{"pathBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType}
|
||||||
};
|
};
|
||||||
this->setInstanceAttributes(kInstanceAttribs, SK_ARRAY_COUNT(kInstanceAttribs));
|
this->setInstanceAttributesWithImplicitOffsets(kInstanceAttribs,
|
||||||
|
SK_ARRAY_COUNT(kInstanceAttribs));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -894,7 +894,7 @@ private:
|
|||||||
fTexSubset = {"texSubset", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
fTexSubset = {"texSubset", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
|
||||||
}
|
}
|
||||||
|
|
||||||
this->setVertexAttributes(&fPosition, 6);
|
this->setVertexAttributesWithImplicitOffsets(&fPosition, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
const TextureSampler& onTextureSampler(int) const override { return fSampler; }
|
const TextureSampler& onTextureSampler(int) const override { return fSampler; }
|
||||||
|
@ -25,7 +25,7 @@ public:
|
|||||||
PatchAttribs::kNone) {
|
PatchAttribs::kNone) {
|
||||||
constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
|
constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
|
||||||
kFloat2_GrSLType};
|
kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&kInputPointAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kInputPointAttrib, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxTessellationSegments(const GrShaderCaps&) const override { SkUNREACHABLE; }
|
int maxTessellationSegments(const GrShaderCaps&) const override { SkUNREACHABLE; }
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
GrPrimitiveType::kPatches, 5, viewMatrix, color, attribs) {
|
GrPrimitiveType::kPatches, 5, viewMatrix, color, attribs) {
|
||||||
constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
|
constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
|
||||||
kFloat2_GrSLType};
|
kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&kInputPointAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kInputPointAttrib, 1);
|
||||||
SkASSERT(this->vertexStride() * 5 ==
|
SkASSERT(this->vertexStride() * 5 ==
|
||||||
sizeof(SkPoint) * 4 + skgpu::PatchAttribsStride(fAttribs));
|
sizeof(SkPoint) * 4 + skgpu::PatchAttribsStride(fAttribs));
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ public:
|
|||||||
attribs) {
|
attribs) {
|
||||||
constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
|
constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
|
||||||
kFloat2_GrSLType};
|
kFloat2_GrSLType};
|
||||||
this->setVertexAttributes(&kInputPointAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kInputPointAttrib, 1);
|
||||||
SkASSERT(this->vertexStride() * 4 ==
|
SkASSERT(this->vertexStride() * 4 ==
|
||||||
sizeof(SkPoint) * 4 + skgpu::PatchAttribsStride(fAttribs));
|
sizeof(SkPoint) * 4 + skgpu::PatchAttribsStride(fAttribs));
|
||||||
}
|
}
|
||||||
|
@ -56,14 +56,15 @@ public:
|
|||||||
// each patch that explicitly tells the shader what type of curve it is.
|
// each patch that explicitly tells the shader what type of curve it is.
|
||||||
fInstanceAttribs.emplace_back("curveType", kFloat_GrVertexAttribType, kFloat_GrSLType);
|
fInstanceAttribs.emplace_back("curveType", kFloat_GrVertexAttribType, kFloat_GrSLType);
|
||||||
}
|
}
|
||||||
this->setInstanceAttributes(fInstanceAttribs.data(), fInstanceAttribs.count());
|
this->setInstanceAttributesWithImplicitOffsets(fInstanceAttribs.data(),
|
||||||
|
fInstanceAttribs.count());
|
||||||
SkASSERT(fInstanceAttribs.count() <= kMaxInstanceAttribCount);
|
SkASSERT(fInstanceAttribs.count() <= kMaxInstanceAttribCount);
|
||||||
SkASSERT(this->instanceStride() ==
|
SkASSERT(this->instanceStride() ==
|
||||||
sizeof(SkPoint) * 4 + skgpu::PatchAttribsStride(fAttribs));
|
sizeof(SkPoint) * 4 + skgpu::PatchAttribsStride(fAttribs));
|
||||||
|
|
||||||
constexpr static Attribute kVertexAttrib("resolveLevel_and_idx", kFloat2_GrVertexAttribType,
|
constexpr static Attribute kVertexAttrib("resolveLevel_and_idx", kFloat2_GrVertexAttribType,
|
||||||
kFloat2_GrSLType);
|
kFloat2_GrSLType);
|
||||||
this->setVertexAttributes(&kVertexAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kVertexAttrib, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxTessellationSegments(const GrShaderCaps&) const override {
|
int maxTessellationSegments(const GrShaderCaps&) const override {
|
||||||
|
@ -91,15 +91,15 @@ GrStrokeTessellationShader::GrStrokeTessellationShader(const GrShaderCaps& shade
|
|||||||
fAttribs.emplace_back("curveTypeAttr", kFloat_GrVertexAttribType, kFloat_GrSLType);
|
fAttribs.emplace_back("curveTypeAttr", kFloat_GrVertexAttribType, kFloat_GrSLType);
|
||||||
}
|
}
|
||||||
if (fMode == Mode::kHardwareTessellation) {
|
if (fMode == Mode::kHardwareTessellation) {
|
||||||
this->setVertexAttributes(fAttribs.data(), fAttribs.count());
|
this->setVertexAttributesWithImplicitOffsets(fAttribs.data(), fAttribs.count());
|
||||||
SkASSERT(this->vertexStride() == sizeof(SkPoint) * 5 + PatchAttribsStride(fPatchAttribs));
|
SkASSERT(this->vertexStride() == sizeof(SkPoint) * 5 + PatchAttribsStride(fPatchAttribs));
|
||||||
} else {
|
} else {
|
||||||
this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
|
this->setInstanceAttributesWithImplicitOffsets(fAttribs.data(), fAttribs.count());
|
||||||
SkASSERT(this->instanceStride() == sizeof(SkPoint) * 5 + PatchAttribsStride(fPatchAttribs));
|
SkASSERT(this->instanceStride() == sizeof(SkPoint) * 5 + PatchAttribsStride(fPatchAttribs));
|
||||||
if (!shaderCaps.vertexIDSupport()) {
|
if (!shaderCaps.vertexIDSupport()) {
|
||||||
constexpr static Attribute kVertexAttrib("edgeID", kFloat_GrVertexAttribType,
|
constexpr static Attribute kVertexAttrib("edgeID", kFloat_GrVertexAttribType,
|
||||||
kFloat_GrSLType);
|
kFloat_GrSLType);
|
||||||
this->setVertexAttributes(&kVertexAttrib, 1);
|
this->setVertexAttributesWithImplicitOffsets(&kVertexAttrib, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SkASSERT(fAttribs.count() <= kMaxAttribCount);
|
SkASSERT(fAttribs.count() <= kMaxAttribCount);
|
||||||
|
@ -100,39 +100,33 @@ static void setup_vertex_input_state(
|
|||||||
|
|
||||||
// setup attribute descriptions
|
// setup attribute descriptions
|
||||||
int attribIndex = 0;
|
int attribIndex = 0;
|
||||||
size_t vertexAttributeOffset = 0;
|
for (auto attrib : vertexAttribs) {
|
||||||
for (const auto& attrib : vertexAttribs) {
|
|
||||||
VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
|
VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
|
||||||
vkAttrib.location = attribIndex++; // for now assume location = attribIndex
|
vkAttrib.location = attribIndex++; // for now assume location = attribIndex
|
||||||
vkAttrib.binding = vertexBinding;
|
vkAttrib.binding = vertexBinding;
|
||||||
vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
|
vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
|
||||||
vkAttrib.offset = vertexAttributeOffset;
|
vkAttrib.offset = *attrib.offset();
|
||||||
vertexAttributeOffset += attrib.sizeAlign4();
|
|
||||||
}
|
}
|
||||||
SkASSERT(vertexAttributeOffset == vertexAttribs.stride());
|
|
||||||
|
|
||||||
size_t instanceAttributeOffset = 0;
|
for (auto attrib : instanceAttribs) {
|
||||||
for (const auto& attrib : instanceAttribs) {
|
|
||||||
VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
|
VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex];
|
||||||
vkAttrib.location = attribIndex++; // for now assume location = attribIndex
|
vkAttrib.location = attribIndex++; // for now assume location = attribIndex
|
||||||
vkAttrib.binding = instanceBinding;
|
vkAttrib.binding = instanceBinding;
|
||||||
vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
|
vkAttrib.format = attrib_type_to_vkformat(attrib.cpuType());
|
||||||
vkAttrib.offset = instanceAttributeOffset;
|
vkAttrib.offset = *attrib.offset();
|
||||||
instanceAttributeOffset += attrib.sizeAlign4();
|
|
||||||
}
|
}
|
||||||
SkASSERT(instanceAttributeOffset == instanceAttribs.stride());
|
|
||||||
|
|
||||||
if (vaCount) {
|
if (vaCount) {
|
||||||
bindingDescs->push_back() = {
|
bindingDescs->push_back() = {
|
||||||
vertexBinding,
|
vertexBinding,
|
||||||
(uint32_t) vertexAttributeOffset,
|
(uint32_t) vertexAttribs.stride(),
|
||||||
VK_VERTEX_INPUT_RATE_VERTEX
|
VK_VERTEX_INPUT_RATE_VERTEX
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (iaCount) {
|
if (iaCount) {
|
||||||
bindingDescs->push_back() = {
|
bindingDescs->push_back() = {
|
||||||
instanceBinding,
|
instanceBinding,
|
||||||
(uint32_t) instanceAttributeOffset,
|
(uint32_t) instanceAttribs.stride(),
|
||||||
VK_VERTEX_INPUT_RATE_INSTANCE
|
VK_VERTEX_INPUT_RATE_INSTANCE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -469,15 +469,15 @@ private:
|
|||||||
if (instanced) {
|
if (instanced) {
|
||||||
fInstanceLocation = {"location", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
fInstanceLocation = {"location", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
||||||
fInstanceColor = {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
fInstanceColor = {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
||||||
this->setInstanceAttributes(&fInstanceLocation, 2);
|
this->setInstanceAttributesWithImplicitOffsets(&fInstanceLocation, 2);
|
||||||
if (hasVertexBuffer) {
|
if (hasVertexBuffer) {
|
||||||
fVertexPosition = {"vertex", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
fVertexPosition = {"vertex", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
||||||
this->setVertexAttributes(&fVertexPosition, 1);
|
this->setVertexAttributesWithImplicitOffsets(&fVertexPosition, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fVertexPosition = {"vertex", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
fVertexPosition = {"vertex", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
|
||||||
fVertexColor = {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
fVertexColor = {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
|
||||||
this->setVertexAttributes(&fVertexPosition, 2);
|
this->setVertexAttributesWithImplicitOffsets(&fVertexPosition, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
PipelineDynamicStateTestProcessor() : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) {
|
PipelineDynamicStateTestProcessor() : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) {
|
||||||
this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
|
this->setVertexAttributesWithImplicitOffsets(kAttributes, SK_ARRAY_COUNT(kAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Attribute& inVertex() const { return kAttributes[0]; }
|
const Attribute& inVertex() const { return kAttributes[0]; }
|
||||||
|
@ -115,7 +115,7 @@ private:
|
|||||||
kFloat2_GrSLType};
|
kFloat2_GrSLType};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->setVertexAttributes(fAttributes.get(), numAttribs);
|
this->setVertexAttributesWithImplicitOffsets(fAttributes.get(), numAttribs);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fNumAttribs;
|
int fNumAttribs;
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
GP(const SkMatrix& localMatrix, bool wideColor)
|
GP(const SkMatrix& localMatrix, bool wideColor)
|
||||||
: GrGeometryProcessor(kTestRectOp_ClassID), fLocalMatrix(localMatrix) {
|
: GrGeometryProcessor(kTestRectOp_ClassID), fLocalMatrix(localMatrix) {
|
||||||
fInColor = MakeColorAttribute("color", wideColor);
|
fInColor = MakeColorAttribute("color", wideColor);
|
||||||
this->setVertexAttributes(&fInPosition, 3);
|
this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* name() const override { return "TestRectOp::GP"; }
|
const char* name() const override { return "TestRectOp::GP"; }
|
||||||
|
Loading…
Reference in New Issue
Block a user