Revert "Revert "New approach to GrProcessor uniforms.""
This reverts commit ae59426ea6e9b351d9d52f2a9c12d05023351994.
Bug: skia:12182
Change-Id: I591a0a89ffad1a3d5d867dd247ceeec71b6041a4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/449516
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index 89dbb83..b11cb25 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -11,6 +11,7 @@
#include "include/private/SkSLSampleUsage.h"
#include "include/private/SkSLString.h"
#include "src/gpu/GrProcessor.h"
+#include "src/gpu/GrUniformAggregator.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
#include <tuple>
@@ -372,7 +373,7 @@
}
explicit GrFragmentProcessor(const GrFragmentProcessor& src)
- : INHERITED(src.classID()), fFlags(src.fFlags) {
+ : INHERITED(src), fFlags(src.fFlags) {
this->cloneAndRegisterAllChildProcessors(src);
}
@@ -506,6 +507,7 @@
stages.
@param fragBuilder Interface used to emit code in the shaders.
+ @param uniforms Used to get names of uniforms added by GrProcessor::uniforms().
@param uniformHandler Interface used for accessing information about our uniforms
@param caps The capabilities of the GPU which will render this FP
@param fp The processor that generated this program stage.
@@ -523,6 +525,7 @@
*/
struct EmitArgs {
EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
+ GrUniformAggregator::ProcessorUniforms uniforms,
GrGLSLUniformHandler* uniformHandler,
const GrShaderCaps* caps,
const GrFragmentProcessor& fp,
@@ -530,6 +533,7 @@
const char* destColor,
const char* sampleCoord)
: fFragBuilder(fragBuilder)
+ , fUniforms(std::move(uniforms))
, fUniformHandler(uniformHandler)
, fShaderCaps(caps)
, fFp(fp)
@@ -537,6 +541,7 @@
, fDestColor(destColor)
, fSampleCoord(sampleCoord) {}
GrGLSLFPFragmentBuilder* fFragBuilder;
+ GrUniformAggregator::ProcessorUniforms fUniforms;
GrGLSLUniformHandler* fUniformHandler;
const GrShaderCaps* fShaderCaps;
const GrFragmentProcessor& fFp;
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index 31667b4..1964416 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -14,6 +14,7 @@
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrShaderVar.h"
#include "src/gpu/GrSwizzle.h"
+#include "src/gpu/GrUniformAggregator.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
@@ -209,8 +210,8 @@
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->addBits(8, attr.isInitialized() ? (int)attr.cpuType() : 0xff, "attrType");
+ b->addBits(8, attr.isInitialized() ? (int)attr.gpuType() : 0xff, "attrGpuType");
}
};
b->add32(fVertexAttributes.fRawCount, "numVertexAttributes");
@@ -261,6 +262,8 @@
inline static const TextureSampler& IthTextureSampler(int i);
private:
+ GrGeometryProcessor(const GrGeometryProcessor&) = delete;
+
virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
GrShaderFlags fShaders = kVertex_GrShaderFlag | kFragment_GrShaderFlag;
@@ -292,6 +295,7 @@
EmitArgs(GrGLSLVertexBuilder* vertBuilder,
GrGLSLFPFragmentBuilder* fragBuilder,
GrGLSLVaryingHandler* varyingHandler,
+ GrUniformAggregator::ProcessorUniforms uniforms,
GrGLSLUniformHandler* uniformHandler,
const GrShaderCaps* caps,
const GrGeometryProcessor& geomProc,
@@ -301,6 +305,7 @@
: fVertBuilder(vertBuilder)
, fFragBuilder(fragBuilder)
, fVaryingHandler(varyingHandler)
+ , fUniforms(std::move(uniforms))
, fUniformHandler(uniformHandler)
, fShaderCaps(caps)
, fGeomProc(geomProc)
@@ -310,6 +315,7 @@
GrGLSLVertexBuilder* fVertBuilder;
GrGLSLFPFragmentBuilder* fFragBuilder;
GrGLSLVaryingHandler* fVaryingHandler;
+ GrUniformAggregator::ProcessorUniforms fUniforms;
GrGLSLUniformHandler* fUniformHandler;
const GrShaderCaps* fShaderCaps;
const GrGeometryProcessor& fGeomProc;
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index ee1a7eb..2cc3412 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -12,6 +12,7 @@
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrDrawOpAtlas.h"
+#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrProgramInfo.h"
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 104537b..f71f2b2 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -9,6 +9,7 @@
#define GrProcessor_DEFINED
#include "include/core/SkMath.h"
+#include "include/core/SkSpan.h"
#include "include/core/SkString.h"
#include "src/gpu/GrColor.h"
#include "src/gpu/GrGpuBuffer.h"
@@ -144,12 +145,139 @@
ClassID classID() const { return fClassID; }
+ /**
+ * Describes a uniform. Uniforms consist of:
+ * type: The type of the values in the shader
+ * count: Number of elements of 'type' in the array or GrShaderVar::kNonArray if not an
+ * array.
+ * offset: byte offset of the data within the GrProcessor class (no relation to uniform
+ * buffer offset).
+ * ctype: specifies the way the data at the 'offset' is represented. See CType enum
+ * comments.
+ * visibility: specifies in which shader stage(s) the uniform is declared.
+ */
+ class Uniform {
+ public:
+ enum class CType : unsigned {
+ // Any float/half, vector of floats/half, or matrices of floats/halfs are a tightly
+ // packed array of floats. Similarly, any bool/shorts/ints are a tightly packed array
+ // of int32_t.
+ kDefault,
+ // Can be used with kFloat3x3 or kHalf3x3
+ kSkMatrix,
+
+ kLast = kSkMatrix
+ };
+ static constexpr int kCTypeCount = static_cast<int>(CType::kLast) + 1;
+
+ constexpr Uniform()
+ : fType (static_cast<unsigned>(kVoid_GrSLType))
+ , fCount (static_cast<unsigned>(GrShaderVar::kNonArray))
+ , fVisibility(static_cast<unsigned>(GrShaderFlags::kNone_GrShaderFlags))
+ , fCType (static_cast<unsigned>(CType::kDefault))
+ , fOffset (0) {}
+
+ constexpr Uniform(GrSLType type,
+ ptrdiff_t offset,
+ GrShaderFlags visibility = kFragment_GrShaderFlag,
+ CType ctype = CType::kDefault)
+ : Uniform(type, GrShaderVar::kNonArray, offset, visibility, ctype) {}
+
+ constexpr Uniform(GrSLType type,
+ int arrayCount,
+ size_t offset,
+ GrShaderFlags visibility = kFragment_GrShaderFlag,
+ CType ctype = CType::kDefault)
+ : fType (static_cast<unsigned>(type ))
+ , fCount (static_cast<unsigned>(arrayCount))
+ , fVisibility(static_cast<unsigned>(visibility))
+ , fCType (static_cast<unsigned>(ctype ))
+ , fOffset (static_cast<unsigned>(offset )) {
+ SkASSERT(CTypeCompatibleWithType(ctype, type));
+
+ SkASSERT(this->type() == type );
+ SkASSERT(this->count() == arrayCount);
+ SkASSERT(this->offset() == offset );
+ SkASSERT(this->visibility() == visibility);
+ SkASSERT(this->ctype() == ctype );
+ }
+
+ constexpr Uniform(const Uniform&) = default;
+
+ Uniform& operator=(const Uniform&) = default;
+
+ constexpr bool isInitialized() const { return this->type() != kVoid_GrSLType; }
+
+ constexpr GrSLType type () const { return static_cast<GrSLType> (fType); }
+ constexpr int count () const { return static_cast<int> (fCount); }
+ constexpr CType ctype () const { return static_cast<CType> (fCType); }
+ constexpr size_t offset () const { return static_cast<GrShaderFlags>(fOffset); }
+ constexpr GrShaderFlags visibility() const {
+ return static_cast<GrShaderFlags>(fVisibility);
+ }
+
+ static constexpr bool CTypeCompatibleWithType(CType, GrSLType);
+
+ private:
+ unsigned fType : 6;
+ unsigned fCount : 8;
+ unsigned fVisibility : 4;
+ unsigned fCType : 1;
+ unsigned fOffset : 32 - (6 + 8 + 4 + 1);
+
+ static_assert(kGrSLTypeCount <= (1 << 6));
+ static_assert(kCTypeCount <= (1 << 1));
+ };
+
+ /** Returns the array of uniforms inserted into the program by this processor. */
+ SkSpan<const Uniform> uniforms() const { return fUniforms; }
+
+ template <typename T = void> const T* uniformData(size_t index) const {
+ SkASSERT(fUniforms[index].isInitialized());
+ return SkTAddOffset<const T>(this, fUniforms[index].offset());
+ }
+
protected:
GrProcessor(ClassID classID) : fClassID(classID) {}
- GrProcessor(const GrProcessor&) = delete;
+ GrProcessor(const GrProcessor&) = default;
GrProcessor& operator=(const GrProcessor&) = delete;
+ /**
+ * Specifies the uniforms used by this processor. Should be called when the processor is made
+ * (i.e. constructor or factory function). Any uniforms with type void are ignored. This allows
+ * a processor to have a contiguous array of data member uniforms where some are conditionally
+ * initialized.
+ */
+ void setUniforms(SkSpan<const Uniform> uniforms) { fUniforms = uniforms; }
+
const ClassID fClassID;
+
+private:
+ SkSpan<const Uniform> fUniforms;
};
+constexpr bool GrProcessor::Uniform::CTypeCompatibleWithType(CType ctype, GrSLType type) {
+ switch (ctype) {
+ case CType::kDefault:
+ return true;
+ case CType::kSkMatrix:
+ return type == kHalf3x3_GrSLType || type == kFloat3x3_GrSLType;
+ }
+ SkUNREACHABLE;
+}
+
+/**
+ * GCC, and clang sometimes but less often for reason, warns if offset_of or__builtin_offsetof is
+ * used on non-standard layout classes. This is because it is not required to be supported by the
+ * compiler (conditionally supported by c++17). clang, GCC, and MSVC all support it, however.
+ */
+#if defined(__GNUC__) || defined(__clang__)
+# define GR_BEGIN_UNIFORM_DEFINITIONS _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
+# define GR_END_UNIFORM_DEFINITIONS _Pragma("GCC diagnostic pop")
+#else
+# define GR_BEGIN_UNIFORM_DEFINITIONS
+# define GR_END_UNIFORM_DEFINITIONS
+#endif
+
#endif
diff --git a/src/gpu/GrProgramInfo.cpp b/src/gpu/GrProgramInfo.cpp
index 091d113..de394aa 100644
--- a/src/gpu/GrProgramInfo.cpp
+++ b/src/gpu/GrProgramInfo.cpp
@@ -20,6 +20,25 @@
return stencil;
}
+static void visit_fp_tree(const GrFragmentProcessor& fp,
+ const std::function<void(const GrProcessor&)>& f) {
+ f(fp);
+ for (int i = 0; i < fp.numChildProcessors(); ++i) {
+ if (const GrFragmentProcessor* child = fp.childProcessor(i)) {
+ visit_fp_tree(*child, f);
+ }
+ }
+}
+
+void GrProgramInfo::visitProcessors(const std::function<void(const GrProcessor&)>& f) const {
+ f(*fGeomProc);
+
+ for (int i = 0; i < fPipeline->numFragmentProcessors(); ++i) {
+ visit_fp_tree(fPipeline->getFragmentProcessor(i), f);
+ }
+ f(fPipeline->getXferProcessor());
+}
+
#ifdef SK_DEBUG
#include "src/gpu/GrTexture.h"
diff --git a/src/gpu/GrProgramInfo.h b/src/gpu/GrProgramInfo.h
index 9f1f602..29d97d5 100644
--- a/src/gpu/GrProgramInfo.h
+++ b/src/gpu/GrProgramInfo.h
@@ -93,6 +93,9 @@
// to call the visitor on its own primProc proxies.
void visitFPProxies(const GrVisitProxyFunc& func) const { fPipeline->visitProxies(func); }
+ /** Visits the GP, then each root FP in a pre-order traversal, and finally the XP. */
+ void visitProcessors(const std::function<void(const GrProcessor&)>&) const;
+
#ifdef SK_DEBUG
void validate(bool flushTime) const;
void checkAllInstantiated() const;
diff --git a/src/gpu/GrSPIRVUniformHandler.cpp b/src/gpu/GrSPIRVUniformHandler.cpp
index f073496..90505e6 100644
--- a/src/gpu/GrSPIRVUniformHandler.cpp
+++ b/src/gpu/GrSPIRVUniformHandler.cpp
@@ -293,7 +293,37 @@
return fSamplerSwizzles[handle.toIndex()];
}
-void GrSPIRVUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
+GrUniformDataManager::ProgramUniforms GrSPIRVUniformHandler::getNewProgramUniforms(
+ const GrUniformAggregator& aggregator) {
+ GrUniformDataManager::ProgramUniforms result;
+ result.reserve(aggregator.numProcessors());
+ for (int p = 0; p < aggregator.numProcessors(); ++p) {
+ GrUniformDataManager::ProcessorUniforms uniforms;
+ auto records = aggregator.processorRecords(p);
+ uniforms.reserve(records.size());
+ for (const GrUniformAggregator::Record& record : records) {
+ const GrProcessor::Uniform& u = record.uniform();
+ uint32_t offset = get_ubo_offset(&fCurrentUBOOffset, u.type(), u.count());
+ uniforms.push_back({record.indexInProcessor, u.type(), u.count(), offset});
+
+ // Add to fNewUniforms so that these get declared.
+ SPIRVUniformInfo& info = fNewUniforms.push_back();
+ GrShaderVar var(record.name, u.type(), u.count());
+ SkString qualifier = SkStringPrintf("offset = %d", offset);
+ var.addLayoutQualifier(qualifier.c_str());
+ info.fUBOOffset = offset;
+ info.fVariable = var;
+ info.fVisibility = u.visibility();
+ info.fOwner = nullptr;
+ }
+ result.push_back(std::move(uniforms));
+ }
+ return result;
+}
+
+void GrSPIRVUniformHandler::appendUniformDecls(const GrUniformAggregator&,
+ GrShaderFlags visibility,
+ SkString* out) const {
auto textures = fTextures.items().begin();
for (const SPIRVUniformInfo& sampler : fSamplers.items()) {
if (sampler.fVisibility & visibility) {
@@ -311,6 +341,12 @@
uniformsString.append(";\n");
}
}
+ for (const UniformInfo& uniform : fNewUniforms.items()) {
+ if (uniform.fVisibility & visibility) {
+ uniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), &uniformsString);
+ uniformsString.append(";\n");
+ }
+ }
if (!uniformsString.isEmpty()) {
out->appendf("layout (set = %d, binding = %d) uniform UniformBuffer\n{\n",
kUniformDescriptorSet, kUniformBinding);
diff --git a/src/gpu/GrSPIRVUniformHandler.h b/src/gpu/GrSPIRVUniformHandler.h
index 5cb1aaa..44475c5 100644
--- a/src/gpu/GrSPIRVUniformHandler.h
+++ b/src/gpu/GrSPIRVUniformHandler.h
@@ -9,6 +9,7 @@
#define GrSPIRVUniformHandler_DEFINED
#include "src/core/SkTBlockList.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
/*
@@ -46,6 +47,14 @@
return fUniforms.item(idx);
}
+ /**
+ * Call after all legacy style uniforms have been added to assign offsets to new style uniforms
+ * and create the data structure needed to transfer new style uniforms to GrUniformDataManager.
+ * This must be called before appendUniformDecls() in order to ensure new style uniforms get
+ * declared. It must be called only once.
+ */
+ GrUniformDataManager::ProgramUniforms getNewProgramUniforms(const GrUniformAggregator&);
+
private:
explicit GrSPIRVUniformHandler(GrGLSLProgramBuilder* program);
@@ -53,7 +62,9 @@
const char* name, const GrShaderCaps*) override;
const char* samplerVariable(SamplerHandle handle) const override;
GrSwizzle samplerSwizzle(SamplerHandle handle) const override;
- void appendUniformDecls(GrShaderFlags visibility, SkString*) const override;
+ void appendUniformDecls(const GrUniformAggregator&,
+ GrShaderFlags visibility,
+ SkString*) const override;
UniformHandle internalAddUniformArray(const GrFragmentProcessor* owner,
uint32_t visibility,
GrSLType type,
@@ -63,6 +74,7 @@
const char** outName) override;
UniformInfoArray fUniforms;
+ UniformInfoArray fNewUniforms;
UniformInfoArray fSamplers;
UniformInfoArray fTextures;
SkTArray<GrSwizzle> fSamplerSwizzles;
diff --git a/src/gpu/GrUniformAggregator.cpp b/src/gpu/GrUniformAggregator.cpp
new file mode 100644
index 0000000..8e2d6bf
--- /dev/null
+++ b/src/gpu/GrUniformAggregator.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "src/gpu/GrUniformAggregator.h"
+
+using ProcessorUniforms = GrUniformAggregator::ProcessorUniforms;
+
+ProcessorUniforms GrUniformAggregator::addUniforms(const GrProcessor& p,
+ const SkString& mangleSuffix) {
+ Processor processor{
+ &p,
+ fUniforms.size(),
+ fUniforms.size(),
+ };
+ for (size_t i = 0; i < p.uniforms().size(); ++i) {
+ if (!p.uniforms()[i].isInitialized()) {
+ continue;
+ }
+ // We give every uniform an initial name so it always can be validly declared. When code is
+ // emitted the processor can give it a more meaningful name. The actual name doesn't matter,
+ // other than for readability.
+ SkString unusedName = SkStringPrintf("default_%zu%s", i, mangleSuffix.c_str());
+ fUniforms.push_back(Record{std::move(unusedName), &p, i});
+ ++processor.end;
+ }
+ fProcessors.push_back(processor);
+ return ProcessorUniforms(p, mangleSuffix, this);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+ProcessorUniforms::ProcessorUniforms(const GrProcessor& p,
+ const SkString& mangleSuffix,
+ GrUniformAggregator* aggregator)
+ : fAgg(aggregator), fMangleSuffix(mangleSuffix) {
+ for (size_t i = 0; i < fAgg->fProcessors.size(); ++i) {
+ if (fAgg->fProcessors[i].processor == &p) {
+ fBegin = fAgg->fProcessors[i].begin;
+ fEnd = fAgg->fProcessors[i].end;
+ return;
+ }
+ }
+}
+
+const char* ProcessorUniforms::getUniformName(size_t index, const char* newBaseName) const {
+ for (size_t i = fBegin; i < fEnd; ++i) {
+ if (fAgg->fUniforms[i].indexInProcessor == index) {
+ GrUniformAggregator::Record& r = fAgg->fUniforms[i];
+ if (newBaseName) {
+ SkString mangledName = SkStringPrintf("%s%s", newBaseName, fMangleSuffix.c_str());
+ r.name = mangledName;
+ }
+ return r.name.c_str();
+ } else if (fAgg->fUniforms[i].indexInProcessor > index) {
+ break;
+ }
+ }
+ return nullptr;
+}
diff --git a/src/gpu/GrUniformAggregator.h b/src/gpu/GrUniformAggregator.h
new file mode 100644
index 0000000..af4f7fd
--- /dev/null
+++ b/src/gpu/GrUniformAggregator.h
@@ -0,0 +1,106 @@
+/*
+ * 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 GrUniformAggregator_DEFINED
+#define GrUniformAggregator_DEFINED
+
+#include "include/core/SkString.h"
+#include "include/private/SkChecksum.h"
+#include "src/gpu/GrProcessor.h"
+
+#include <vector>
+
+/** Collects the uniforms from various processors comprising the shaders of a pipeline/program. */
+class GrUniformAggregator {
+public:
+ class ProcessorUniforms {
+ public:
+ ProcessorUniforms(ProcessorUniforms&&) = default;
+ ProcessorUniforms& operator=(ProcessorUniforms&&) = default;
+
+ /**
+ * Finds a uniform name by index. The uniform initially has a generic name. It can
+ * optionally be given a descriptive name via the newBaseName param. However, the caller
+ * must use the returned name because even if a name is passed the final uniform name will
+ * be mangled to be unique.
+ */
+ const char* getUniformName(size_t index, const char* newBaseName = nullptr) const;
+
+ private:
+ ProcessorUniforms(const GrProcessor& p,
+ const SkString& mangleSuffix,
+ GrUniformAggregator* aggregator);
+
+ ProcessorUniforms(const ProcessorUniforms&) = delete;
+ ProcessorUniforms& operator=(const ProcessorUniforms&) = delete;
+
+ GrUniformAggregator* fAgg;
+
+ SkString fMangleSuffix;
+
+ size_t fBegin = 0;
+ size_t fEnd = 0;
+
+ friend class GrUniformAggregator;
+ };
+
+ struct Record {
+ SkString name;
+ const GrProcessor* processor = nullptr;
+ size_t indexInProcessor = -1;
+
+ const GrProcessor::Uniform& uniform() const {
+ return processor->uniforms()[indexInProcessor];
+ }
+ };
+
+ GrUniformAggregator() = default;
+
+ /**
+ * Aggregates the uniforms for a processor. This must be called for all processors in a
+ * program and must be called in this order: GP, FP0-T, FP1-T, ... XP. FPi-T is a pre-order
+ * traversal of the ith FP in the GrPipeline.
+ */
+ ProcessorUniforms addUniforms(const GrProcessor&, const SkString& mangleSuffix);
+
+ /**
+ * Iterable range of all uniform Records across all processors added.
+ */
+ SkSpan<const Record> records() const {
+ return SkSpan<const Record>(fUniforms.data(), fUniforms.size());
+ }
+
+ /**
+ * Iterable range of Records for a given processor index.
+ */
+ SkSpan<const Record> processorRecords(size_t processorIndex) const {
+ SkASSERT(processorIndex < fProcessors.size());
+ size_t size = fProcessors[processorIndex].end - fProcessors[processorIndex].begin;
+ return SkSpan<const Record>(fUniforms.data() + fProcessors[processorIndex].begin, size);
+ }
+
+ int uniformCount() const { return fUniforms.size(); }
+
+ /**
+ * The number of processors whose uniforms have been added to the aggregator, including
+ * processors that had no valid uniforms.
+ */
+ int numProcessors() const { return fProcessors.size(); }
+
+private:
+ struct Processor {
+ const GrProcessor* processor;
+ size_t begin; // index of first uniform owned by processor in fUniforms.
+ size_t end; // index of last uniform + 1 owned by processor in fUniforms.
+ };
+ std::vector<Processor> fProcessors;
+ using Records = std::vector<Record>;
+
+ Records fUniforms;
+};
+
+#endif
diff --git a/src/gpu/GrUniformDataManager.cpp b/src/gpu/GrUniformDataManager.cpp
index 69842d0..859ff1d 100644
--- a/src/gpu/GrUniformDataManager.cpp
+++ b/src/gpu/GrUniformDataManager.cpp
@@ -7,18 +7,295 @@
#include "src/gpu/GrUniformDataManager.h"
+#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrShaderVar.h"
// ensure that these types are the sizes the uniform data is expecting
static_assert(sizeof(int32_t) == 4);
static_assert(sizeof(float) == 4);
-GrUniformDataManager::GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize)
- : fUniformSize(uniformSize)
- , fUniformsDirty(false) {
+//////////////////////////////////////////////////////////////////////////////
+
+GrUniformDataManager::UniformManager::UniformManager(ProgramUniforms uniforms, Layout layout)
+ : fUniforms(std::move(uniforms)), fLayout(layout) {}
+
+template <typename BaseType> static constexpr size_t tight_vec_size(int vecLength) {
+ return sizeof(BaseType) * vecLength;
+}
+
+/**
+ * From Section 7.6.2.2 "Standard Uniform Block Layout":
+ * 1. If the member is a scalar consuming N basic machine units, the base alignment is N.
+ * 2. If the member is a two- or four-component vector with components consuming N basic machine
+ * units, the base alignment is 2N or 4N, respectively.
+ * 3. If the member is a three-component vector with components consuming N
+ * basic machine units, the base alignment is 4N.
+ * 4. If the member is an array of scalars or vectors, the base alignment and array
+ * stride are set to match the base alignment of a single array element, according
+ * to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The
+ * array may have padding at the end; the base offset of the member following
+ * the array is rounded up to the next multiple of the base alignment.
+ * 5. If the member is a column-major matrix with C columns and R rows, the
+ * matrix is stored identically to an array of C column vectors with R components each,
+ * according to rule (4).
+ * 6. If the member is an array of S column-major matrices with C columns and
+ * R rows, the matrix is stored identically to a row of S × C column vectors
+ * with R components each, according to rule (4).
+ * 7. If the member is a row-major matrix with C columns and R rows, the matrix
+ * is stored identically to an array of R row vectors with C components each,
+ * according to rule (4).
+ * 8. If the member is an array of S row-major matrices with C columns and R
+ * rows, the matrix is stored identically to a row of S × R row vectors with C
+ * components each, according to rule (4).
+ * 9. If the member is a structure, the base alignment of the structure is N, where
+ * N is the largest base alignment value of any of its members, and rounded
+ * up to the base alignment of a vec4. The individual members of this substructure are then
+ * assigned offsets by applying this set of rules recursively,
+ * where the base offset of the first member of the sub-structure is equal to the
+ * aligned offset of the structure. The structure may have padding at the end;
+ * the base offset of the member following the sub-structure is rounded up to
+ * the next multiple of the base alignment of the structure.
+ * 10. If the member is an array of S structures, the S elements of the array are laid
+ * out in order, according to rule (9).
+ */
+template <typename BaseType, int RowsOrVecLength = 1, int Cols = 1>
+struct Rules140 {
+ /**
+ * For an array of scalars or vectors this returns the stride between array elements. For
+ * matrices or arrays of matrices this returns the stride between columns of the matrix. Note
+ * that for single (non-array) scalars or vectors we don't require a stride.
+ */
+ static constexpr size_t Stride(int count) {
+ SkASSERT(count >= 1 || count == GrShaderVar::kNonArray);
+ static_assert(RowsOrVecLength >= 1 && RowsOrVecLength <= 4);
+ static_assert(Cols >= 1 && Cols <= 4);
+ if (Cols != 1) {
+ // This is a matrix or array of matrices. We return the stride between columns.
+ SkASSERT(RowsOrVecLength > 1);
+ return Rules140<BaseType, RowsOrVecLength>::Stride(1);
+ }
+ if (count == 0) {
+ // Stride doesn't matter for a non-array.
+ return 0;
+ }
+
+ // Rule 4.
+
+ // Alignment of vec4 by Rule 2.
+ constexpr size_t kVec4Alignment = tight_vec_size<float>(4);
+ // Get alignment of a single vector of BaseType by Rule 1, 2, or 3
+ int n = RowsOrVecLength == 3 ? 4 : RowsOrVecLength;
+ size_t kElementAlignment = tight_vec_size<BaseType>(n);
+ // Round kElementAlignment up to multiple of kVec4Alignment.
+ size_t m = (kElementAlignment + kVec4Alignment - 1)/kVec4Alignment;
+ return m*kVec4Alignment;
+ }
+};
+
+/**
+ * When using the std430 storage layout, shader storage blocks will be laid out in buffer storage
+ * identically to uniform and shader storage blocks using the std140 layout, except that the base
+ * alignment and stride of arrays of scalars and vectors in rule 4 and of structures in rule 9 are
+ * not rounded up a multiple of the base alignment of a vec4.
+ */
+template <typename BaseType, int RowsOrVecLength = 1, int Cols = 1>
+struct Rules430 {
+ static constexpr size_t Stride(int count) {
+ SkASSERT(count >= 1 || count == GrShaderVar::kNonArray);
+ static_assert(RowsOrVecLength >= 1 && RowsOrVecLength <= 4);
+ static_assert(Cols >= 1 && Cols <= 4);
+
+ if (Cols != 1) {
+ // This is a matrix or array of matrices. We return the stride between columns.
+ SkASSERT(RowsOrVecLength > 1);
+ return Rules430<BaseType, RowsOrVecLength>::Stride(1);
+ }
+ if (count == 0) {
+ // Stride doesn't matter for a non-array.
+ return 0;
+ }
+ // Rule 4 without the round up to a multiple of align-of vec4.
+ return tight_vec_size<BaseType>(RowsOrVecLength == 3 ? 4 : RowsOrVecLength);
+ }
+};
+
+// The strides used here were derived from the rules we've imposed on ourselves in
+// GrMtlPipelineStateDataManger. Everything is tight except 3-component which have the stride of
+// their 4-component equivalents.
+template <typename BaseType, int RowsOrVecLength = 1, int Cols = 1>
+struct RulesMetal {
+ static constexpr size_t Stride(int count) {
+ SkASSERT(count >= 1 || count == GrShaderVar::kNonArray);
+ static_assert(RowsOrVecLength >= 1 && RowsOrVecLength <= 4);
+ static_assert(Cols >= 1 && Cols <= 4);
+ if (Cols != 1) {
+ // This is a matrix or array of matrices. We return the stride between columns.
+ SkASSERT(RowsOrVecLength > 1);
+ return RulesMetal<BaseType, RowsOrVecLength>::Stride(1);
+ }
+ if (count == 0) {
+ // Stride doesn't matter for a non-array.
+ return 0;
+ }
+ return tight_vec_size<BaseType>(RowsOrVecLength == 3 ? 4 : RowsOrVecLength);
+ }
+};
+
+template <template <typename BaseType, int RowsOrVecLength, int Cols> class Rules>
+class Writer {
+private:
+ using CType = GrProcessor::Uniform::CType;
+
+ template<typename BaseType, int RowsOrVecLength = 1, int Cols = 1>
+ static void Write(void* dst, int n, const BaseType v[]) {
+ if (dst) {
+ size_t stride = Rules<BaseType, RowsOrVecLength, Cols>::Stride(n);
+ n = (n == GrShaderVar::kNonArray) ? 1 : n;
+ n *= Cols;
+ if (stride == RowsOrVecLength*sizeof(BaseType)) {
+ std::memcpy(dst, v, n*stride);
+ } else {
+ for (int i = 0; i < n; ++i) {
+ std::memcpy(dst, v, RowsOrVecLength*sizeof(BaseType));
+ v += RowsOrVecLength;
+ dst = SkTAddOffset<void>(dst, stride);
+ }
+ }
+ }
+ }
+
+ static void WriteSkMatrices(void* d, int n, const SkMatrix m[]) {
+ size_t offset = 0;
+ for (int i = 0; i < std::max(n, 1); ++i) {
+ float mt[] = {
+ m[i].get(SkMatrix::kMScaleX),
+ m[i].get(SkMatrix::kMSkewY),
+ m[i].get(SkMatrix::kMPersp0),
+ m[i].get(SkMatrix::kMSkewX),
+ m[i].get(SkMatrix::kMScaleY),
+ m[i].get(SkMatrix::kMPersp1),
+ m[i].get(SkMatrix::kMTransX),
+ m[i].get(SkMatrix::kMTransY),
+ m[i].get(SkMatrix::kMPersp2),
+ };
+ Write<float, 3, 3>(SkTAddOffset<void>(d, offset), 1, mt);
+ // Stride() will give us the stride of each column, so mul by 3 to get matrix stride.
+ offset += 3*Rules<float, 3, 3>::Stride(1);
+ }
+ }
+
+public:
+ static void WriteUniform(GrSLType type, CType ctype, void* d, int n, const void* v) {
+ SkASSERT(d);
+ SkASSERT(n >= 1 || n == GrShaderVar::kNonArray);
+ switch (type) {
+ case kInt_GrSLType:
+ return Write<int32_t>(d, n, static_cast<const int32_t*>(v));
+
+ case kInt2_GrSLType:
+ return Write<int32_t, 2>(d, n, static_cast<const int32_t*>(v));
+
+ case kInt3_GrSLType:
+ return Write<int32_t, 3>(d, n, static_cast<const int32_t*>(v));
+
+ case kInt4_GrSLType:
+ return Write<int32_t, 4>(d, n, static_cast<const int32_t*>(v));
+
+ case kHalf_GrSLType:
+ case kFloat_GrSLType:
+ return Write<float>(d, n, static_cast<const float*>(v));
+
+ case kHalf2_GrSLType:
+ case kFloat2_GrSLType:
+ return Write<float, 2>(d, n, static_cast<const float*>(v));
+
+ case kHalf3_GrSLType:
+ case kFloat3_GrSLType:
+ return Write<float, 3>(d, n, static_cast<const float*>(v));
+
+ case kHalf4_GrSLType:
+ case kFloat4_GrSLType:
+ return Write<float, 4>(d, n, static_cast<const float*>(v));
+
+ case kHalf2x2_GrSLType:
+ case kFloat2x2_GrSLType:
+ return Write<float, 2, 2>(d, n, static_cast<const float*>(v));
+
+ case kHalf3x3_GrSLType:
+ case kFloat3x3_GrSLType: {
+ switch (ctype) {
+ case CType::kDefault:
+ return Write<float, 3, 3>(d, n, static_cast<const float*>(v));
+ case CType::kSkMatrix:
+ return WriteSkMatrices(d, n, static_cast<const SkMatrix*>(v));
+ }
+ SkUNREACHABLE;
+ }
+
+ case kHalf4x4_GrSLType:
+ case kFloat4x4_GrSLType:
+ return Write<float, 4, 4>(d, n, static_cast<const float*>(v));
+
+ default:
+ SK_ABORT("Unexpect uniform type");
+ }
+ }
+};
+
+bool GrUniformDataManager::UniformManager::writeUniforms(const GrProgramInfo& info, void* buffer) {
+ decltype(&Writer<Rules140>::WriteUniform) write;
+ switch (fLayout) {
+ case Layout::kStd140:
+ write = Writer<Rules140>::WriteUniform;
+ break;
+ case Layout::kStd430:
+ write = Writer<Rules430>::WriteUniform;
+ break;
+ case Layout::kMetal:
+ write = Writer<RulesMetal>::WriteUniform;
+ break;
+ }
+
+ bool wrote = false;
+ auto set = [&, processorIndex = 0](const GrProcessor& p) mutable {
+ SkASSERT(buffer);
+ const ProcessorUniforms& uniforms = fUniforms[processorIndex];
+ for (const NewUniform& u : uniforms) {
+ if (u.type != kVoid_GrSLType) {
+ SkASSERT(u.count >= 0);
+ static_assert(GrShaderVar::kNonArray == 0);
+ void* d = SkTAddOffset<void>(buffer, u.offset);
+ size_t index = u.indexInProcessor;
+ const void* v = p.uniformData(index);
+ write(u.type, p.uniforms()[index].ctype(), d, u.count, v);
+ wrote = true;
+ }
+ }
+ ++processorIndex;
+ };
+
+ info.visitProcessors(set);
+ return wrote;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrUniformDataManager::GrUniformDataManager(ProgramUniforms uniforms,
+ Layout layout,
+ uint32_t uniformCount,
+ uint32_t uniformSize)
+ : fUniformSize(uniformSize)
+ , fUniformsDirty(false)
+ , fUniformManager(std::move(uniforms), layout) {
fUniformData.reset(uniformSize);
fUniforms.push_back_n(uniformCount);
- // subclasses fill in the uniforms in their constructor
+ // subclasses fill in the legacy uniforms in their constructor
+}
+
+void GrUniformDataManager::setUniforms(const GrProgramInfo& info) {
+ if (fUniformManager.writeUniforms(info, fUniformData.get())) {
+ this->markDirty();
+ }
}
void* GrUniformDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
diff --git a/src/gpu/GrUniformDataManager.h b/src/gpu/GrUniformDataManager.h
index b418960..9bb3539 100644
--- a/src/gpu/GrUniformDataManager.h
+++ b/src/gpu/GrUniformDataManager.h
@@ -8,20 +8,41 @@
#ifndef GrUniformDataManager_DEFINED
#define GrUniformDataManager_DEFINED
-#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
-
#include "include/private/GrTypesPriv.h"
#include "include/private/SkTArray.h"
#include "src/core/SkAutoMalloc.h"
+#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
+
+#include <vector>
+
+class GrProgramInfo;
/**
* Subclass of GrGLSLProgramDataManager used to store uniforms for a program in a CPU buffer that
- * can be uploaded to a UBO. This currently assumes uniform layouts that are compatible with
- * Vulkan, Dawn, and D3D12. It could be used more broadly if this aspect was made configurable.
+ * can be uploaded to a UBO.
*/
class GrUniformDataManager : public GrGLSLProgramDataManager {
public:
- GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize);
+ enum class Layout {
+ kStd140,
+ kStd430,
+ kMetal, /** This is our own self-imposed layout we use for Metal. */
+ };
+
+ struct NewUniform {
+ size_t indexInProcessor = ~0;
+ GrSLType type = kVoid_GrSLType;
+ int count = 0;
+ uint32_t offset = 0;
+ };
+
+ using ProcessorUniforms = std::vector<NewUniform>;
+ using ProgramUniforms = std::vector<ProcessorUniforms>;
+
+ GrUniformDataManager(ProgramUniforms,
+ Layout layout,
+ uint32_t uniformCount,
+ uint32_t uniformSize);
void set1i(UniformHandle, int32_t) const override;
void set1iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
@@ -51,6 +72,8 @@
// For the uniform data to be dirty so that we will reupload on the next use.
void markDirty() { fUniformsDirty = true; }
+ void setUniforms(const GrProgramInfo& info);
+
protected:
struct Uniform {
uint32_t fOffset;
@@ -71,6 +94,19 @@
mutable SkAutoMalloc fUniformData;
mutable bool fUniformsDirty;
+
+private:
+ class UniformManager {
+ public:
+ UniformManager(ProgramUniforms, Layout layout);
+ bool writeUniforms(const GrProgramInfo& info, void* buffer);
+
+ private:
+ ProgramUniforms fUniforms;
+ Layout fLayout;
+ };
+
+ UniformManager fUniformManager;
};
#endif
diff --git a/src/gpu/GrXferProcessor.h b/src/gpu/GrXferProcessor.h
index 439895d..36b3272 100644
--- a/src/gpu/GrXferProcessor.h
+++ b/src/gpu/GrXferProcessor.h
@@ -14,6 +14,7 @@
#include "src/gpu/GrProcessor.h"
#include "src/gpu/GrProcessorAnalysis.h"
#include "src/gpu/GrSurfaceProxyView.h"
+#include "src/gpu/GrUniformAggregator.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
class GrGLSLXPFragmentBuilder;
@@ -144,6 +145,8 @@
GrXferProcessor(ClassID classID, bool willReadDstColor, GrProcessorAnalysisCoverage);
private:
+ GrXferProcessor(const GrXferProcessor&) = delete;
+
/**
* Adds a key on the GrProcessorKeyBuilder that reflects any variety in the code that may be
* emitted by the xfer processor subclass.
@@ -287,6 +290,7 @@
struct EmitArgs {
EmitArgs(GrGLSLXPFragmentBuilder* fragBuilder,
+ GrUniformAggregator::ProcessorUniforms uniforms,
GrGLSLUniformHandler* uniformHandler,
const GrShaderCaps* caps,
const GrXferProcessor& xp,
@@ -298,6 +302,7 @@
GrSurfaceOrigin dstTextureOrigin,
const GrSwizzle& writeSwizzle)
: fXPFragBuilder(fragBuilder)
+ , fUniforms(std::move(uniforms))
, fUniformHandler(uniformHandler)
, fShaderCaps(caps)
, fXP(xp)
@@ -309,6 +314,7 @@
, fDstTextureOrigin(dstTextureOrigin)
, fWriteSwizzle(writeSwizzle) {}
GrGLSLXPFragmentBuilder* fXPFragBuilder;
+ GrUniformAggregator::ProcessorUniforms fUniforms;
GrGLSLUniformHandler* fUniformHandler;
const GrShaderCaps* fShaderCaps;
const GrXferProcessor& fXP;
diff --git a/src/gpu/d3d/GrD3DPipelineState.cpp b/src/gpu/d3d/GrD3DPipelineState.cpp
index 9db5ddf..1412f2a 100644
--- a/src/gpu/d3d/GrD3DPipelineState.cpp
+++ b/src/gpu/d3d/GrD3DPipelineState.cpp
@@ -23,6 +23,7 @@
GrD3DPipelineState::GrD3DPipelineState(
sk_sp<GrD3DPipeline> pipeline,
sk_sp<GrD3DRootSignature> rootSignature,
+ GrUniformDataManager::ProgramUniforms programUniforms,
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t uniformSize,
@@ -38,7 +39,7 @@
, fGPImpl(std::move(gpImpl))
, fXPImpl(std::move(xpImpl))
, fFPImpls(std::move(fpImpls))
- , fDataManager(uniforms, uniformSize)
+ , fDataManager(std::move(programUniforms), uniforms, uniformSize)
, fNumSamplers(numSamplers)
, fVertexStride(vertexStride)
, fInstanceStride(instanceStride) {}
@@ -46,6 +47,8 @@
void GrD3DPipelineState::setAndBindConstants(GrD3DGpu* gpu,
const GrRenderTarget* renderTarget,
const GrProgramInfo& programInfo) {
+ fDataManager.setUniforms(programInfo);
+
this->setRenderTargetState(renderTarget, programInfo.origin());
fGPImpl->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc());
diff --git a/src/gpu/d3d/GrD3DPipelineState.h b/src/gpu/d3d/GrD3DPipelineState.h
index 9cd9ca5..0e3b0ff 100644
--- a/src/gpu/d3d/GrD3DPipelineState.h
+++ b/src/gpu/d3d/GrD3DPipelineState.h
@@ -12,6 +12,7 @@
#include "include/gpu/GrTypes.h"
#include "include/gpu/d3d/GrD3DTypes.h"
#include "src/gpu/GrManagedResource.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "src/gpu/d3d/GrD3DPipelineStateDataManager.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
@@ -29,6 +30,7 @@
GrD3DPipelineState(sk_sp<GrD3DPipeline> pipeline,
sk_sp<GrD3DRootSignature> rootSignature,
+ GrUniformDataManager::ProgramUniforms,
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t uniformSize,
diff --git a/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp b/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
index 738d36f..ee09735 100644
--- a/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
+++ b/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
@@ -561,6 +561,8 @@
std::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
TRACE_EVENT0("skia.shaders", TRACE_FUNC);
+ GrUniformDataManager::ProgramUniforms uniforms =
+ fUniformHandler.getNewProgramUniforms(fUniformAggregator);
this->finalizeShaders();
SkSL::Program::Settings settings;
@@ -655,6 +657,7 @@
return std::unique_ptr<GrD3DPipelineState>(
new GrD3DPipelineState(std::move(pipeline),
std::move(rootSig),
+ std::move(uniforms),
fUniformHandles,
fUniformHandler.fUniforms,
fUniformHandler.fCurrentUBOOffset,
diff --git a/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp b/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp
index a902bdd..ee6873d 100644
--- a/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp
+++ b/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp
@@ -10,9 +10,11 @@
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DResourceProvider.h"
-GrD3DPipelineStateDataManager::GrD3DPipelineStateDataManager(const UniformInfoArray& uniforms,
- uint32_t uniformSize)
- : INHERITED(uniforms.count(), uniformSize) {
+GrD3DPipelineStateDataManager::GrD3DPipelineStateDataManager(
+ GrUniformDataManager::ProgramUniforms programUniforms,
+ const UniformInfoArray& uniforms,
+ uint32_t uniformSize)
+ : INHERITED(std::move(programUniforms), Layout::kStd140, uniforms.count(), uniformSize) {
// We must add uniforms in same order as the UniformInfoArray so that UniformHandles already
// owned by other objects will still match up here.
int i = 0;
diff --git a/src/gpu/d3d/GrD3DPipelineStateDataManager.h b/src/gpu/d3d/GrD3DPipelineStateDataManager.h
index 18e8278..2e3fe80 100644
--- a/src/gpu/d3d/GrD3DPipelineStateDataManager.h
+++ b/src/gpu/d3d/GrD3DPipelineStateDataManager.h
@@ -8,10 +8,9 @@
#ifndef GrD3DPipelineStateDataManager_DEFINED
#define GrD3DPipelineStateDataManager_DEFINED
-#include "src/gpu/GrUniformDataManager.h"
-
#include "include/gpu/d3d/GrD3DTypes.h"
#include "src/gpu/GrSPIRVUniformHandler.h"
+#include "src/gpu/GrUniformDataManager.h"
class GrD3DConstantRingBuffer;
class GrD3DGpu;
@@ -20,7 +19,8 @@
public:
typedef GrSPIRVUniformHandler::UniformInfoArray UniformInfoArray;
- GrD3DPipelineStateDataManager(const UniformInfoArray&,
+ GrD3DPipelineStateDataManager(GrUniformDataManager::ProgramUniforms,
+ const UniformInfoArray&,
uint32_t uniformSize);
D3D12_GPU_VIRTUAL_ADDRESS uploadConstants(GrD3DGpu* gpu);
diff --git a/src/gpu/dawn/GrDawnProgramBuilder.cpp b/src/gpu/dawn/GrDawnProgramBuilder.cpp
index 1852286..c7137ca 100644
--- a/src/gpu/dawn/GrDawnProgramBuilder.cpp
+++ b/src/gpu/dawn/GrDawnProgramBuilder.cpp
@@ -263,6 +263,8 @@
return nullptr;
}
+ GrUniformDataManager::ProgramUniforms uniforms =
+ builder.fUniformHandler.getNewProgramUniforms(builder.fUniformAggregator);
builder.finalizeShaders();
SkSL::Program::Inputs vertInputs, fragInputs;
@@ -271,9 +273,11 @@
&vertInputs);
auto fsModule = builder.createShaderModule(builder.fFS, SkSL::ProgramKind::kFragment, flipY,
&fragInputs);
- GrSPIRVUniformHandler::UniformInfoArray& uniforms = builder.fUniformHandler.fUniforms;
+ GrSPIRVUniformHandler::UniformInfoArray& legacyUniforms = builder.fUniformHandler.fUniforms;
uint32_t uniformBufferSize = builder.fUniformHandler.fCurrentUBOOffset;
- sk_sp<GrDawnProgram> result(new GrDawnProgram(uniforms, uniformBufferSize));
+ sk_sp<GrDawnProgram> result(new GrDawnProgram(std::move(uniforms),
+ legacyUniforms,
+ uniformBufferSize));
result->fGPImpl = std::move(builder.fGPImpl);
result->fXPImpl = std::move(builder.fXPImpl);
result->fFPImpls = std::move(builder.fFPImpls);
@@ -494,6 +498,7 @@
if (0 == fDataManager.uniformBufferSize()) {
return nullptr;
}
+ fDataManager.setUniforms(programInfo);
this->setRenderTargetState(renderTarget, programInfo.origin());
const GrPipeline& pipeline = programInfo.pipeline();
const GrGeometryProcessor& geomProc = programInfo.geomProc();
diff --git a/src/gpu/dawn/GrDawnProgramBuilder.h b/src/gpu/dawn/GrDawnProgramBuilder.h
index 4845ae2..32cf077 100644
--- a/src/gpu/dawn/GrDawnProgramBuilder.h
+++ b/src/gpu/dawn/GrDawnProgramBuilder.h
@@ -32,10 +32,10 @@
}
};
typedef GrGLSLBuiltinUniformHandles BuiltinUniformHandles;
- GrDawnProgram(const GrSPIRVUniformHandler::UniformInfoArray& uniforms,
+ GrDawnProgram(GrUniformDataManager::ProgramUniforms programUniforms,
+ const GrSPIRVUniformHandler::UniformInfoArray& uniforms,
uint32_t uniformBufferSize)
- : fDataManager(uniforms, uniformBufferSize) {
- }
+ : fDataManager(std::move(programUniforms), uniforms, uniformBufferSize) {}
std::unique_ptr<GrGeometryProcessor::ProgramImpl> fGPImpl;
std::unique_ptr<GrXferProcessor::ProgramImpl> fXPImpl;
std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fFPImpls;
diff --git a/src/gpu/dawn/GrDawnProgramDataManager.cpp b/src/gpu/dawn/GrDawnProgramDataManager.cpp
index 36280ab..5869187 100644
--- a/src/gpu/dawn/GrDawnProgramDataManager.cpp
+++ b/src/gpu/dawn/GrDawnProgramDataManager.cpp
@@ -9,9 +9,13 @@
#include "src/gpu/dawn/GrDawnGpu.h"
-GrDawnProgramDataManager::GrDawnProgramDataManager(const UniformInfoArray& uniforms,
+GrDawnProgramDataManager::GrDawnProgramDataManager(ProgramUniforms programUniforms,
+ const UniformInfoArray& uniforms,
uint32_t uniformBufferSize)
- : GrUniformDataManager(uniforms.count(), uniformBufferSize) {
+ : GrUniformDataManager(std::move(programUniforms),
+ Layout::kStd140,
+ uniforms.count(),
+ uniformBufferSize) {
memset(fUniformData.get(), 0, uniformBufferSize);
// We must add uniforms in same order is the UniformInfoArray so that UniformHandles already
// owned by other objects will still match up here.
diff --git a/src/gpu/dawn/GrDawnProgramDataManager.h b/src/gpu/dawn/GrDawnProgramDataManager.h
index f9a17ff..f3d6a99 100644
--- a/src/gpu/dawn/GrDawnProgramDataManager.h
+++ b/src/gpu/dawn/GrDawnProgramDataManager.h
@@ -8,9 +8,8 @@
#ifndef GrDawnProgramDataManager_DEFINED
#define GrDawnProgramDataManager_DEFINED
-#include "src/gpu/GrUniformDataManager.h"
-
#include "src/gpu/GrSPIRVUniformHandler.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "src/gpu/dawn/GrDawnRingBuffer.h"
#include "dawn/webgpu_cpp.h"
@@ -23,7 +22,7 @@
public:
typedef GrSPIRVUniformHandler::UniformInfoArray UniformInfoArray;
- GrDawnProgramDataManager(const UniformInfoArray&, uint32_t uniformBufferSize);
+ GrDawnProgramDataManager(ProgramUniforms, const UniformInfoArray&, uint32_t uniformBufferSize);
uint32_t uniformBufferSize() const { return fUniformSize; }
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index d9da5aa..83f59ed 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -14,6 +14,7 @@
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/GrProcessorAnalysis.h"
+#include "src/gpu/GrUniformAggregator.h"
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/glsl/GrGLSLBlend.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -573,6 +574,10 @@
GrProcessorAnalysisCoverage::kLCD)
, fBlendConstant(blendConstant)
, fAlpha(alpha) {
+GR_BEGIN_UNIFORM_DEFINITIONS
+ static constexpr Uniform kAlphaU{kHalf_GrSLType, offsetof(PDLCDXferProcessor, fAlpha)};
+GR_END_UNIFORM_DEFINITIONS
+ this->setUniforms(SkMakeSpan(&kAlphaU, 1));
}
sk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode,
@@ -594,12 +599,7 @@
class Impl : public ProgramImpl {
private:
void emitOutputsForBlendState(const EmitArgs& args) override {
- const char* alpha;
- fAlphaUniform = args.fUniformHandler->addUniform(nullptr,
- kFragment_GrShaderFlag,
- kHalf_GrSLType,
- "alpha",
- &alpha);
+ const char* alpha = args.fUniforms.getUniformName(0, "alpha");
GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
// We want to force our primary output to be alpha * Coverage, where alpha is the alpha
// value of the src color. We know that there are no color stages (or we wouldn't have
@@ -611,16 +611,7 @@
alpha, args.fInputCoverage);
}
- void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override {
- float alpha = xp.cast<PDLCDXferProcessor>().fAlpha;
- if (fLastAlpha != alpha) {
- pdm.set1f(fAlphaUniform, alpha);
- fLastAlpha = alpha;
- }
- }
-
- GrGLSLUniformHandler::UniformHandle fAlphaUniform;
- float fLastAlpha = SK_FloatNaN;
+ void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override {}
};
return std::make_unique<Impl>();
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 7b8258c..3ba1b14 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -11,6 +11,7 @@
#include "src/core/SkTLazy.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrShaderCaps.h"
+#include "src/gpu/GrUniformAggregator.h"
#include "src/gpu/effects/GrConvexPolyEffect.h"
#include "src/gpu/effects/GrOvalEffect.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -66,9 +67,10 @@
bool onIsEqual(const GrFragmentProcessor& other) const override;
- SkRRect fRRect;
- GrClipEdgeType fEdgeType;
- uint32_t fCircularCornerFlags;
+ SkRect fRect;
+ float fRadiusAndInverse[2];
+ GrClipEdgeType fEdgeType;
+ uint32_t fCircularCornerFlags;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
@@ -93,17 +95,92 @@
: INHERITED(kCircularRRectEffect_ClassID,
ProcessorOptimizationFlags(inputFP.get()) &
kCompatibleWithCoverageAsAlpha_OptimizationFlag)
- , fRRect(rrect)
, fEdgeType(edgeType)
, fCircularCornerFlags(circularCornerFlags) {
this->registerChild(std::move(inputFP));
+
+ fRect = rrect.rect();
+ float radius;
+ switch (fCircularCornerFlags) {
+ case CircularRRectEffect::kAll_CornerFlags:
+ SkASSERT(SkRRectPriv::IsSimpleCircular(rrect));
+ radius = SkRRectPriv::GetSimpleRadii(rrect).fX;
+ SkASSERT(radius >= kRadiusMin);
+ fRect.inset(radius, radius);
+ break;
+ case CircularRRectEffect::kTopLeft_CornerFlag:
+ radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
+ fRect.fLeft += radius;
+ fRect.fTop += radius;
+ fRect.fRight += 0.5f;
+ fRect.fBottom += 0.5f;
+ break;
+ case CircularRRectEffect::kTopRight_CornerFlag:
+ radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
+ fRect.fLeft -= 0.5f;
+ fRect.fTop += radius;
+ fRect.fRight -= radius;
+ fRect.fBottom += 0.5f;
+ break;
+ case CircularRRectEffect::kBottomRight_CornerFlag:
+ radius = rrect.radii(SkRRect::kLowerRight_Corner).fX;
+ fRect.fLeft -= 0.5f;
+ fRect.fTop -= 0.5f;
+ fRect.fRight -= radius;
+ fRect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kBottomLeft_CornerFlag:
+ radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
+ fRect.fLeft += radius;
+ fRect.fTop -= 0.5f;
+ fRect.fRight += 0.5f;
+ fRect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kLeft_CornerFlags:
+ radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
+ fRect.fLeft += radius;
+ fRect.fTop += radius;
+ fRect.fRight += 0.5f;
+ fRect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kTop_CornerFlags:
+ radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
+ fRect.fLeft += radius;
+ fRect.fTop += radius;
+ fRect.fRight -= radius;
+ fRect.fBottom += 0.5f;
+ break;
+ case CircularRRectEffect::kRight_CornerFlags:
+ radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
+ fRect.fLeft -= 0.5f;
+ fRect.fTop += radius;
+ fRect.fRight -= radius;
+ fRect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kBottom_CornerFlags:
+ radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
+ fRect.fLeft += radius;
+ fRect.fTop -= 0.5f;
+ fRect.fRight -= radius;
+ fRect.fBottom -= radius;
+ break;
+ default:
+ SkUNREACHABLE;
+ }
+ radius += 0.5f;
+ fRadiusAndInverse[0] = radius;
+ fRadiusAndInverse[1] = 1.f/ radius;
+
+GR_BEGIN_UNIFORM_DEFINITIONS
+ static constexpr Uniform kUniforms[2] {
+ {kFloat4_GrSLType, offsetof(CircularRRectEffect, fRect )}, // inner rect
+ {kHalf2_GrSLType , offsetof(CircularRRectEffect, fRadiusAndInverse)}, // r, 1/r
+ };
+GR_END_UNIFORM_DEFINITIONS
+ this->setUniforms(SkMakeSpan(kUniforms));
}
-CircularRRectEffect::CircularRRectEffect(const CircularRRectEffect& that)
- : INHERITED(that)
- , fRRect(that.fRRect)
- , fEdgeType(that.fEdgeType)
- , fCircularCornerFlags(that.fCircularCornerFlags) {}
+CircularRRectEffect::CircularRRectEffect(const CircularRRectEffect& that) = default;
std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new CircularRRectEffect(*this));
@@ -112,7 +189,9 @@
bool CircularRRectEffect::onIsEqual(const GrFragmentProcessor& other) const {
const CircularRRectEffect& crre = other.cast<CircularRRectEffect>();
// The corner flags are derived from fRRect, so no need to check them.
- return fEdgeType == crre.fEdgeType && fRRect == crre.fRRect;
+ return fEdgeType == crre.fEdgeType &&
+ fRect == crre.fRect &&
+ fRadiusAndInverse[0] == crre.fRadiusAndInverse[0];
}
//////////////////////////////////////////////////////////////////////////////
@@ -145,36 +224,28 @@
void emitCode(EmitArgs&) override;
private:
- void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
-
- GrGLSLProgramDataManager::UniformHandle fInnerRectUniform;
- GrGLSLProgramDataManager::UniformHandle fRadiusPlusHalfUniform;
SkRRect fPrevRRect;
};
void CircularRRectEffect::Impl::emitCode(EmitArgs& args) {
const CircularRRectEffect& crre = args.fFp.cast<CircularRRectEffect>();
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
- const char *rectName;
- const char *radiusPlusHalfName;
+ const char* rect = args.fUniforms.getUniformName(0, "rect" );
+ const char* radiusPlusHalf = args.fUniforms.getUniformName(1, "radiusPlusHalf");
+
// The inner rect is the rrect bounds inset by the radius. Its left, top, right, and bottom
// edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
// only rectangular corners, that side's value corresponds to the rect edge's value outset by
// half a pixel.
- fInnerRectUniform = uniformHandler->addUniform(&crre, kFragment_GrShaderFlag, kFloat4_GrSLType,
- "innerRect", &rectName);
+
// x is (r + .5) and y is 1/(r + .5)
- fRadiusPlusHalfUniform = uniformHandler->addUniform(&crre, kFragment_GrShaderFlag,
- kHalf2_GrSLType, "radiusPlusHalf",
- &radiusPlusHalfName);
// If we're on a device where float != fp32 then the length calculation could overflow.
SkString clampedCircleDistance;
if (!args.fShaderCaps->floatIs32Bits()) {
clampedCircleDistance.printf("saturate(%s.x * (1.0 - length(dxy * %s.y)))",
- radiusPlusHalfName, radiusPlusHalfName);
+ radiusPlusHalf, radiusPlusHalf);
} else {
- clampedCircleDistance.printf("saturate(%s.x - length(dxy))", radiusPlusHalfName);
+ clampedCircleDistance.printf("saturate(%s.x - length(dxy))", radiusPlusHalf);
}
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -195,86 +266,86 @@
// alphas together.
switch (crre.fCircularCornerFlags) {
case CircularRRectEffect::kAll_CornerFlags:
- fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
- fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
+ fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rect);
+ fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rect);
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
fragBuilder->codeAppendf("half alpha = half(%s);", clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kTopLeft_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(%s.LT - sk_FragCoord.xy, 0.0);",
- rectName);
+ rect);
fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = bottomAlpha * rightAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kTopRight_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.R, "
"%s.T - sk_FragCoord.y), 0.0);",
- rectName, rectName);
+ rect, rect);
fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = bottomAlpha * leftAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kBottomRight_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.RB, 0.0);",
- rectName);
+ rect);
fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = topAlpha * leftAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kBottomLeft_CornerFlag:
fragBuilder->codeAppendf("float2 dxy = max(float2(%s.L - sk_FragCoord.x, "
"sk_FragCoord.y - %s.B), 0.0);",
- rectName, rectName);
+ rect, rect);
fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = topAlpha * rightAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kLeft_CornerFlags:
- fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
- fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.B;", rectName);
+ fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rect);
+ fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.B;", rect);
fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = rightAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kTop_CornerFlags:
- fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
- fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.R;", rectName);
+ fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rect);
+ fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.R;", rect);
fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);");
fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = bottomAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kRight_CornerFlags:
- fragBuilder->codeAppendf("float dy0 = %s.T - sk_FragCoord.y;", rectName);
- fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
+ fragBuilder->codeAppendf("float dy0 = %s.T - sk_FragCoord.y;", rect);
+ fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rect);
fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = leftAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kBottom_CornerFlags:
- fragBuilder->codeAppendf("float dx0 = %s.L - sk_FragCoord.x;", rectName);
- fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
+ fragBuilder->codeAppendf("float dx0 = %s.L - sk_FragCoord.x;", rect);
+ fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rect);
fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);");
fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
- rectName);
+ rect);
fragBuilder->codeAppendf("half alpha = topAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
@@ -289,86 +360,6 @@
fragBuilder->codeAppendf("return %s * alpha;", inputSample.c_str());
}
-void CircularRRectEffect::Impl::onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& processor) {
- const CircularRRectEffect& crre = processor.cast<CircularRRectEffect>();
- const SkRRect& rrect = crre.fRRect;
- if (rrect != fPrevRRect) {
- SkRect rect = rrect.getBounds();
- SkScalar radius = 0;
- switch (crre.fCircularCornerFlags) {
- case CircularRRectEffect::kAll_CornerFlags:
- SkASSERT(SkRRectPriv::IsSimpleCircular(rrect));
- radius = SkRRectPriv::GetSimpleRadii(rrect).fX;
- SkASSERT(radius >= kRadiusMin);
- rect.inset(radius, radius);
- break;
- case CircularRRectEffect::kTopLeft_CornerFlag:
- radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
- rect.fLeft += radius;
- rect.fTop += radius;
- rect.fRight += 0.5f;
- rect.fBottom += 0.5f;
- break;
- case CircularRRectEffect::kTopRight_CornerFlag:
- radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
- rect.fLeft -= 0.5f;
- rect.fTop += radius;
- rect.fRight -= radius;
- rect.fBottom += 0.5f;
- break;
- case CircularRRectEffect::kBottomRight_CornerFlag:
- radius = rrect.radii(SkRRect::kLowerRight_Corner).fX;
- rect.fLeft -= 0.5f;
- rect.fTop -= 0.5f;
- rect.fRight -= radius;
- rect.fBottom -= radius;
- break;
- case CircularRRectEffect::kBottomLeft_CornerFlag:
- radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
- rect.fLeft += radius;
- rect.fTop -= 0.5f;
- rect.fRight += 0.5f;
- rect.fBottom -= radius;
- break;
- case CircularRRectEffect::kLeft_CornerFlags:
- radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
- rect.fLeft += radius;
- rect.fTop += radius;
- rect.fRight += 0.5f;
- rect.fBottom -= radius;
- break;
- case CircularRRectEffect::kTop_CornerFlags:
- radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
- rect.fLeft += radius;
- rect.fTop += radius;
- rect.fRight -= radius;
- rect.fBottom += 0.5f;
- break;
- case CircularRRectEffect::kRight_CornerFlags:
- radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
- rect.fLeft -= 0.5f;
- rect.fTop += radius;
- rect.fRight -= radius;
- rect.fBottom -= radius;
- break;
- case CircularRRectEffect::kBottom_CornerFlags:
- radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
- rect.fLeft += radius;
- rect.fTop -= 0.5f;
- rect.fRight -= radius;
- rect.fBottom -= radius;
- break;
- default:
- SK_ABORT("Should have been one of the above cases.");
- }
- pdman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
- radius += 0.5f;
- pdman.set2f(fRadiusPlusHalfUniform, radius, 1.f / radius);
- fPrevRRect = rrect;
- }
-}
-
////////////////////////////////////////////////////////////////////////////////////////////////////
void CircularRRectEffect::onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index b590d8c..530775b 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -22,14 +22,14 @@
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
sk_sp<GrGLProgram> GrGLProgram::Make(
GrGLGpu* gpu,
const GrGLSLBuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
+ const GrUniformAggregator& uniformAggregator,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
+ bool usedProgramBinaries,
std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
@@ -41,8 +41,10 @@
sk_sp<GrGLProgram> program(new GrGLProgram(gpu,
builtinUniforms,
programID,
+ std::move(uniformAggregator),
uniforms,
textureSamplers,
+ usedProgramBinaries,
std::move(gpImpl),
std::move(xpImpl),
std::move(fpImpls),
@@ -60,8 +62,10 @@
GrGLProgram::GrGLProgram(GrGLGpu* gpu,
const GrGLSLBuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
+ const GrUniformAggregator& uniformAggregator,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
+ bool usedProgramBinaries,
std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
@@ -81,7 +85,12 @@
, fVertexStride(vertexStride)
, fInstanceStride(instanceStride)
, fGpu(gpu)
- , fProgramDataManager(gpu, uniforms)
+ , fProgramDataManager(gpu,
+ uniforms,
+ textureSamplers,
+ programID,
+ usedProgramBinaries,
+ uniformAggregator)
, fNumTextureSamplers(textureSamplers.count()) {}
GrGLProgram::~GrGLProgram() {
@@ -98,6 +107,8 @@
void GrGLProgram::updateUniforms(const GrRenderTarget* renderTarget,
const GrProgramInfo& programInfo) {
+ fProgramDataManager.setUniforms(programInfo);
+
this->setRenderTargetState(renderTarget, programInfo.origin(), programInfo.geomProc());
// we set the uniforms for installed processors in a generic way, but subclasses of GLProgram
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index b07c78a..7b5c39e 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -23,6 +23,7 @@
class GrProgramInfo;
class GrRenderTarget;
class GrTextureProxy;
+class GrUniformAggregator;
/**
* This class manages a GPU program and records per-program information. It also records the vertex
@@ -54,8 +55,10 @@
GrGLGpu*,
const GrGLSLBuiltinUniformHandles&,
GrGLuint programID,
+ const GrUniformAggregator&,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
+ bool usedProgramBinaries,
std::unique_ptr<GrGeometryProcessor::ProgramImpl>,
std::unique_ptr<GrXferProcessor::ProgramImpl>,
std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fps,
@@ -127,8 +130,10 @@
GrGLProgram(GrGLGpu*,
const GrGLSLBuiltinUniformHandles&,
GrGLuint programID,
+ const GrUniformAggregator&,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
+ bool usedProgramBinaries,
std::unique_ptr<GrGeometryProcessor::ProgramImpl>,
std::unique_ptr<GrXferProcessor::ProgramImpl>,
std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index 9e3abea..16e57b6 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -5,17 +5,193 @@
* found in the LICENSE file.
*/
-#include "include/core/SkMatrix.h"
-#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLProgramDataManager.h"
+
+#include "include/core/SkMatrix.h"
+#include "src/gpu/GrProgramInfo.h"
+#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
+GrGLProgramDataManager::UniformManager::UniformManager(const GrUniformAggregator& uniformAggregator,
+ GrGLuint programID,
+ GrGLint firstUniformLocation,
+ const GrGLContext& ctx) {
+ GrGLint location = firstUniformLocation;
+ fUniforms.reserve(uniformAggregator.uniformCount());
+ for (int p = 0; p < uniformAggregator.numProcessors(); ++p) {
+ fUniforms.push_back({});
+ for (const GrUniformAggregator::Record& record : uniformAggregator.processorRecords(p)) {
+ const GrProcessor::Uniform& u = record.uniform();
+ if (ctx.caps()->bindUniformLocationSupport() && firstUniformLocation >= 0) {
+ GR_GL_CALL(ctx.glInterface(),
+ BindUniformLocation(programID, location, record.name.c_str()));
+ } else {
+ GR_GL_CALL_RET(ctx.glInterface(),
+ location,
+ GetUniformLocation(programID, record.name.c_str()));
+ }
+ fUniforms.back().push_back({
+ record.indexInProcessor,
+ u.type(),
+ u.count(),
+ location,
+ });
+ location++;
+ }
+ }
+}
+
+void GrGLProgramDataManager::UniformManager::setUniforms(const GrGLInterface* gl,
+ const GrProgramInfo& info) {
+ auto set = [&, processorIndex = 0](const GrProcessor& p) mutable {
+ const ProcessorUniforms& uniforms = fUniforms[processorIndex];
+ for (const Uniform& u : uniforms) {
+ if (u.location < 0) {
+ // Presumably this got optimized out.
+ continue;
+ }
+ size_t index = u.indexInProcessor;
+ SkASSERT(u.count >= 0);
+ static_assert(GrShaderVar::kNonArray == 0);
+ int n = std::max(1, u.count);
+ switch (u.type) {
+ case kInt_GrSLType: {
+ const int32_t* values = p.uniformData<int32_t>(index);
+ GR_GL_CALL(gl, Uniform1iv(u.location, n, values));
+ break;
+ }
+
+ case kInt2_GrSLType: {
+ const int32_t* values = p.uniformData<int32_t>(index);
+ GR_GL_CALL(gl, Uniform2iv(u.location, n, values));
+ break;
+ }
+
+ case kInt3_GrSLType: {
+ const int32_t* values = p.uniformData<int32_t>(index);
+ GR_GL_CALL(gl, Uniform3iv(u.location, n, values));
+ break;
+ }
+
+ case kInt4_GrSLType: {
+ const int32_t* values = p.uniformData<int32_t>(index);
+ GR_GL_CALL(gl, Uniform4iv(u.location, n, values));
+ break;
+ }
+
+ case kHalf_GrSLType:
+ case kFloat_GrSLType: {
+ const float* values = p.uniformData<float>(index);
+ GR_GL_CALL(gl, Uniform1fv(u.location, n, values));
+ break;
+ }
+
+ case kHalf2_GrSLType:
+ case kFloat2_GrSLType: {
+ const float* values = p.uniformData<float>(index);
+ GR_GL_CALL(gl, Uniform2fv(u.location, n, values));
+ break;
+ }
+
+ case kHalf3_GrSLType:
+ case kFloat3_GrSLType: {
+ const float* values = p.uniformData<float>(index);
+ GR_GL_CALL(gl, Uniform3fv(u.location, n, values));
+ break;
+ }
+
+ case kHalf4_GrSLType:
+ case kFloat4_GrSLType: {
+ const float* values = p.uniformData<float>(index);
+ GR_GL_CALL(gl, Uniform4fv(u.location, n, values));
+ break;
+ }
+
+ case kHalf2x2_GrSLType:
+ case kFloat2x2_GrSLType: {
+ const float* values = p.uniformData<float>(index);
+ GR_GL_CALL(gl, UniformMatrix2fv(u.location, n, false, values));
+ break;
+ }
+
+ case kHalf3x3_GrSLType:
+ case kFloat3x3_GrSLType: {
+ switch (p.uniforms()[index].ctype()) {
+ case GrProcessor::Uniform::CType::kDefault: {
+ const float* values = p.uniformData<float>(index);
+ GR_GL_CALL(gl, UniformMatrix3fv(u.location, n, false, values));
+ break;
+ }
+ case GrProcessor::Uniform::CType::kSkMatrix: {
+ const SkMatrix* matrix = p.uniformData<SkMatrix>(index);
+ int location = u.location;
+ for (int i = 0; i < n; ++i, ++matrix, ++location) {
+ float mt[] = {
+ matrix->get(SkMatrix::kMScaleX),
+ matrix->get(SkMatrix::kMSkewY),
+ matrix->get(SkMatrix::kMPersp0),
+ matrix->get(SkMatrix::kMSkewX),
+ matrix->get(SkMatrix::kMScaleY),
+ matrix->get(SkMatrix::kMPersp1),
+ matrix->get(SkMatrix::kMTransX),
+ matrix->get(SkMatrix::kMTransY),
+ matrix->get(SkMatrix::kMPersp2),
+ };
+ GR_GL_CALL(gl, UniformMatrix3fv(location, 1, false, mt));
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ case kHalf4x4_GrSLType:
+ case kFloat4x4_GrSLType: {
+ const float* values = p.uniformData<float>(index);
+ GR_GL_CALL(gl, UniformMatrix4fv(u.location, n, false, values));
+ break;
+ }
+
+ default:
+ SK_ABORT("Unexpect uniform type");
+ }
+ }
+ ++processorIndex;
+ };
+
+ info.visitProcessors(set);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
#define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, COUNT) \
SkASSERT((COUNT) <= (UNI).fArrayCount || \
(1 == (COUNT) && GrShaderVar::kNonArray == (UNI).fArrayCount))
-GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, const UniformInfoArray& uniforms)
- : fGpu(gpu) {
+GrGLint get_first_unused_uniform_location(
+ const GrGLProgramDataManager::UniformInfoArray& uniforms,
+ const GrGLProgramDataManager::UniformInfoArray& samplers) {
+ GrGLint id = -1;
+ for (int i = 0; i < uniforms.count(); ++i) {
+ id = std::max(id, uniforms.item(i).fLocation);
+ }
+ for (int i = 0; i < samplers.count(); ++i) {
+ id = std::max(id, samplers.item(i).fLocation);
+ }
+ return id + 1;
+}
+
+GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu,
+ const UniformInfoArray& uniforms,
+ const UniformInfoArray& samplers,
+ GrGLuint programID,
+ bool usedProgramBinaries,
+ const GrUniformAggregator& uniformAggregator)
+ : fGpu(gpu)
+ , fManager(uniformAggregator,
+ programID,
+ usedProgramBinaries ? -1 : get_first_unused_uniform_location(uniforms, samplers),
+ gpu->glContext()) {
fUniforms.push_back_n(uniforms.count());
int i = 0;
for (const GLUniformInfo& builderUniform : uniforms.items()) {
@@ -30,6 +206,10 @@
}
}
+void GrGLProgramDataManager::setUniforms(const GrProgramInfo& info) {
+ fManager.setUniforms(fGpu->glInterface(), info);
+}
+
void GrGLProgramDataManager::setSamplerUniforms(const UniformInfoArray& samplers,
int startUnit) const {
int i = 0;
diff --git a/src/gpu/gl/GrGLProgramDataManager.h b/src/gpu/gl/GrGLProgramDataManager.h
index c01006c..4625c51 100644
--- a/src/gpu/gl/GrGLProgramDataManager.h
+++ b/src/gpu/gl/GrGLProgramDataManager.h
@@ -9,16 +9,21 @@
#define GrGLProgramDataManager_DEFINED
#include "include/gpu/gl/GrGLTypes.h"
+#include "include/private/SkTArray.h"
#include "src/core/SkTBlockList.h"
#include "src/gpu/GrShaderVar.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
-#include "include/private/SkTArray.h"
+#include <vector>
class GrGLGpu;
class SkMatrix;
class GrGLProgram;
+class GrGLContext;
+struct GrGLInterface;
+class GrProgramInfo;
+class GrUniformAggregator;
/** Manages the resources used by a shader program.
* The resources are objects the program uses to communicate with the
@@ -41,7 +46,12 @@
typedef SkTBlockList<GLUniformInfo> UniformInfoArray;
typedef SkTBlockList<VaryingInfo> VaryingInfoArray;
- GrGLProgramDataManager(GrGLGpu*, const UniformInfoArray&);
+ GrGLProgramDataManager(GrGLGpu*,
+ const UniformInfoArray& uniforms,
+ const UniformInfoArray& samplers,
+ GrGLuint programID,
+ bool usedProgramBinaries,
+ const GrUniformAggregator& aggregator);
void setSamplerUniforms(const UniformInfoArray& samplers, int startUnit) const;
@@ -73,6 +83,8 @@
void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override;
void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override;
+ void setUniforms(const GrProgramInfo& info);
+
private:
enum {
kUnusedUniform = -1,
@@ -92,6 +104,29 @@
SkTArray<Uniform, true> fUniforms;
GrGLGpu* fGpu;
+ class UniformManager {
+ public:
+ UniformManager(const GrUniformAggregator&,
+ GrGLuint programID,
+ // used for BindUniformLocation, negative means get the locations, don't bind
+ GrGLint firstUnusedUniformID,
+ const GrGLContext& ctx);
+
+ void setUniforms(const GrGLInterface* gl, const GrProgramInfo& info);
+
+ private:
+ struct Uniform {
+ size_t indexInProcessor = -1;
+ GrSLType type = kVoid_GrSLType;
+ int count = 0;
+ GrGLint location = -1;
+ };
+ using ProcessorUniforms = std::vector<Uniform>;
+ std::vector<ProcessorUniforms> fUniforms;
+ };
+
+ UniformManager fManager;
+
using INHERITED = GrGLSLProgramDataManager;
};
diff --git a/src/gpu/gl/GrGLUniformHandler.cpp b/src/gpu/gl/GrGLUniformHandler.cpp
index 49865d4..b96eb44 100644
--- a/src/gpu/gl/GrGLUniformHandler.cpp
+++ b/src/gpu/gl/GrGLUniformHandler.cpp
@@ -86,7 +86,9 @@
return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
}
-void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
+void GrGLUniformHandler::appendUniformDecls(const GrUniformAggregator& aggregator,
+ GrShaderFlags visibility,
+ SkString* out) const {
for (const UniformInfo& uniform : fUniforms.items()) {
if (uniform.fVisibility & visibility) {
uniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
@@ -99,6 +101,14 @@
out->append(";\n");
}
}
+ for (const auto& record : aggregator.records()) {
+ const GrProcessor::Uniform& u = record.uniform();
+ if (u.visibility() & visibility) {
+ GrShaderVar var(record.name, u.type(), GrShaderVar::TypeModifier::Uniform, u.count());
+ var.appendDecl(fProgramBuilder->shaderCaps(), out);
+ out->append(";\n");
+ }
+ }
}
void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
diff --git a/src/gpu/gl/GrGLUniformHandler.h b/src/gpu/gl/GrGLUniformHandler.h
index 76e8e3c..b9d6de3 100644
--- a/src/gpu/gl/GrGLUniformHandler.h
+++ b/src/gpu/gl/GrGLUniformHandler.h
@@ -63,7 +63,9 @@
return fSamplerSwizzles[handle.toIndex()];
}
- void appendUniformDecls(GrShaderFlags visibility, SkString*) const override;
+ void appendUniformDecls(const GrUniformAggregator&,
+ GrShaderFlags visibility,
+ SkString*) const override;
// Manually set uniform locations for all our uniforms.
void bindUniformLocations(GrGLuint programID, const GrGLCaps& caps);
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index d58e863..2ae5fa1 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -447,7 +447,7 @@
}
this->storeShaderInCache(inputs, programID, glsl, isSkSL, &settings);
}
- return this->createProgram(programID);
+ return this->createProgram(programID, usedProgramBinaries);
}
void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
@@ -497,12 +497,14 @@
fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
}
-sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
+sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID, bool usedProgramBinaries) {
return GrGLProgram::Make(fGpu,
fUniformHandles,
programID,
+ fUniformAggregator,
fUniformHandler.fUniforms,
fUniformHandler.fSamplers,
+ usedProgramBinaries,
std::move(fGPImpl),
std::move(fXPImpl),
std::move(fFPImpls),
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index 67b88b6..e1fb4799 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -79,8 +79,7 @@
SkSL::String* sksl[], const SkSL::String glsl[]);
void resolveProgramResourceLocations(GrGLuint programID, bool force);
- // Subclasses create different programs
- sk_sp<GrGLProgram> createProgram(GrGLuint programID);
+ sk_sp<GrGLProgram> createProgram(GrGLuint programID, bool usedProgramBinaries);
GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; }
const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; }
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 04f54a6..efc05e0 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -77,6 +77,9 @@
this->nameExpression(outputColor, "outputColor");
this->nameExpression(outputCoverage, "outputCoverage");
+ GrUniformAggregator::ProcessorUniforms uniforms =
+ fUniformAggregator.addUniforms(geomProc, this->getMangleSuffix());
+
SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
GrShaderFlags rtAdjustVisibility;
if (geomProc.willUseTessellationShaders()) {
@@ -110,6 +113,7 @@
GrGeometryProcessor::ProgramImpl::EmitArgs args(&fVS,
&fFS,
this->varyingHandler(),
+ std::move(uniforms),
this->uniformHandler(),
this->shaderCaps(),
geomProc,
@@ -215,6 +219,9 @@
const char* const inputColor = fp.isBlendFunction() ? "_src" : "_input";
const char* sampleCoords = "_coords";
fFS.nextStage();
+ GrUniformAggregator::ProcessorUniforms uniforms =
+ fUniformAggregator.addUniforms(fp, this->getMangleSuffix());
+
// Conceptually, an FP is always sampled at a particular coordinate. However, if it is only
// sampled by a chain of uniform matrix expressions (or legacy coord transforms), the value that
// would have been passed to _coords is lifted to the vertex shader and
@@ -268,7 +275,9 @@
// First, emit every child's function. This needs to happen (even for children that aren't
// sampled), so that all of the expected uniforms are registered.
this->writeChildFPFunctions(fp, impl);
+
GrFragmentProcessor::ProgramImpl::EmitArgs args(&fFS,
+ std::move(uniforms),
this->uniformHandler(),
this->shaderCaps(),
fp,
@@ -353,6 +362,8 @@
SkASSERT(!fXPImpl);
const GrXferProcessor& xp = this->pipeline().getXferProcessor();
+ GrUniformAggregator::ProcessorUniforms uniforms =
+ fUniformAggregator.addUniforms(xp, this->getMangleSuffix());
fXPImpl = xp.makeProgramImpl();
// Enable dual source secondary output if we have one
@@ -372,6 +383,7 @@
GrXferProcessor::ProgramImpl::EmitArgs args(
&fFS,
+ std::move(uniforms),
this->uniformHandler(),
this->shaderCaps(),
xp,
@@ -462,7 +474,7 @@
}
void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
- this->uniformHandler()->appendUniformDecls(visibility, out);
+ this->uniformHandler()->appendUniformDecls(fUniformAggregator, visibility, out);
}
void GrGLSLProgramBuilder::addRTFlipUniform(const char* name) {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 994af71..3eec13f 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -12,6 +12,7 @@
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrProgramInfo.h"
+#include "src/gpu/GrUniformAggregator.h"
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
@@ -111,6 +112,8 @@
GrSurfaceOrigin fDstTextureOrigin;
protected:
+ GrUniformAggregator fUniformAggregator;
+
explicit GrGLSLProgramBuilder(const GrProgramDesc&, const GrProgramInfo&);
void addFeature(GrShaderFlags shaders, uint32_t featureBit, const char* extensionName);
diff --git a/src/gpu/glsl/GrGLSLUniformHandler.h b/src/gpu/glsl/GrGLSLUniformHandler.h
index af0a930..e58eb3e 100644
--- a/src/gpu/glsl/GrGLSLUniformHandler.h
+++ b/src/gpu/glsl/GrGLSLUniformHandler.h
@@ -19,6 +19,7 @@
class GrGLSLShaderBuilder;
class GrSamplerState;
class GrSurfaceProxy;
+class GrUniformAggregator;
// Handles for program uniforms (other than per-effect uniforms)
struct GrGLSLBuiltinUniformHandles {
@@ -134,7 +135,9 @@
int arrayCount,
const char** outName) = 0;
- virtual void appendUniformDecls(GrShaderFlags visibility, SkString*) const = 0;
+ virtual void appendUniformDecls(const GrUniformAggregator&,
+ GrShaderFlags visibility,
+ SkString*) const = 0;
friend class GrGLSLProgramBuilder;
};
diff --git a/src/gpu/mtl/GrMtlPipelineState.h b/src/gpu/mtl/GrMtlPipelineState.h
index 4cd8ed4..931a8d8 100644
--- a/src/gpu/mtl/GrMtlPipelineState.h
+++ b/src/gpu/mtl/GrMtlPipelineState.h
@@ -10,6 +10,7 @@
#include "include/private/GrTypesPriv.h"
#include "src/gpu/GrStencilSettings.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/gpu/mtl/GrMtlBuffer.h"
#include "src/gpu/mtl/GrMtlPipeline.h"
@@ -38,6 +39,7 @@
GrMtlPipelineState(GrMtlGpu*,
sk_sp<GrMtlRenderPipeline> pipeline,
MTLPixelFormat,
+ GrUniformDataManager::ProgramUniforms,
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t uniformBufferSize,
diff --git a/src/gpu/mtl/GrMtlPipelineState.mm b/src/gpu/mtl/GrMtlPipelineState.mm
index f3ee0cf..601ffcb 100644
--- a/src/gpu/mtl/GrMtlPipelineState.mm
+++ b/src/gpu/mtl/GrMtlPipelineState.mm
@@ -40,6 +40,7 @@
GrMtlGpu* gpu,
sk_sp<GrMtlRenderPipeline> pipeline,
MTLPixelFormat pixelFormat,
+ GrUniformDataManager::ProgramUniforms programUniforms,
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t uniformBufferSize,
@@ -55,12 +56,13 @@
, fGPImpl(std::move(gpImpl))
, fXPImpl(std::move(xpImpl))
, fFPImpls(std::move(fpImpls))
- , fDataManager(uniforms, uniformBufferSize) {
+ , fDataManager(std::move(programUniforms), uniforms, uniformBufferSize) {
(void) fPixelFormat; // Suppress unused-var warning.
}
void GrMtlPipelineState::setData(GrMtlFramebuffer* framebuffer,
const GrProgramInfo& programInfo) {
+ fDataManager.setUniforms(programInfo);
SkISize colorAttachmentDimensions = framebuffer->colorAttachment()->dimensions();
this->setRenderTargetState(colorAttachmentDimensions, programInfo.origin());
diff --git a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
index 70132e0..64dfda0 100644
--- a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
+++ b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
@@ -531,6 +531,8 @@
SkASSERT(pipelineDescriptor.vertexDescriptor);
SkASSERT(pipelineDescriptor.colorAttachments[0]);
+ GrUniformDataManager::ProgramUniforms uniforms =
+ fUniformHandler.getNewProgramUniforms(fUniformAggregator);
if (precompiledLibs) {
SkASSERT(precompiledLibs->fVertexLibrary);
SkASSERT(precompiledLibs->fFragmentLibrary);
@@ -724,6 +726,7 @@
return new GrMtlPipelineState(fGpu,
std::move(renderPipeline),
pipelineDescriptor.colorAttachments[0].pixelFormat,
+ std::move(uniforms),
fUniformHandles,
fUniformHandler.fUniforms,
bufferSize,
diff --git a/src/gpu/mtl/GrMtlPipelineStateDataManager.h b/src/gpu/mtl/GrMtlPipelineStateDataManager.h
index 4a4ddda..bdcde1c 100644
--- a/src/gpu/mtl/GrMtlPipelineStateDataManager.h
+++ b/src/gpu/mtl/GrMtlPipelineStateDataManager.h
@@ -22,7 +22,8 @@
public:
typedef GrMtlUniformHandler::UniformInfoArray UniformInfoArray;
- GrMtlPipelineStateDataManager(const UniformInfoArray&,
+ GrMtlPipelineStateDataManager(GrUniformDataManager::ProgramUniforms,
+ const UniformInfoArray&,
uint32_t uniformSize);
void set1iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
diff --git a/src/gpu/mtl/GrMtlPipelineStateDataManager.mm b/src/gpu/mtl/GrMtlPipelineStateDataManager.mm
index 47e9f10..196503d 100644
--- a/src/gpu/mtl/GrMtlPipelineStateDataManager.mm
+++ b/src/gpu/mtl/GrMtlPipelineStateDataManager.mm
@@ -17,9 +17,11 @@
GR_NORETAIN_BEGIN
-GrMtlPipelineStateDataManager::GrMtlPipelineStateDataManager(const UniformInfoArray& uniforms,
- uint32_t uniformSize)
- : INHERITED(uniforms.count(), uniformSize) {
+GrMtlPipelineStateDataManager::GrMtlPipelineStateDataManager(
+ GrUniformDataManager::ProgramUniforms programUniforms,
+ const UniformInfoArray& uniforms,
+ uint32_t uniformSize)
+ : INHERITED(std::move(programUniforms), Layout::kMetal, uniforms.count(), uniformSize) {
// We must add uniforms in same order is the UniformInfoArray so that UniformHandles already
// owned by other objects will still match up here.
int i = 0;
diff --git a/src/gpu/mtl/GrMtlUniformHandler.h b/src/gpu/mtl/GrMtlUniformHandler.h
index 88e2b08..f17e03f 100644
--- a/src/gpu/mtl/GrMtlUniformHandler.h
+++ b/src/gpu/mtl/GrMtlUniformHandler.h
@@ -10,6 +10,7 @@
#include "src/core/SkTBlockList.h"
#include "src/gpu/GrShaderVar.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
#include <vector>
@@ -53,6 +54,14 @@
return fUniforms.item(idx);
}
+ /**
+ * Call after all legacy style uniforms have been added to assign offsets to new style uniforms
+ * and create the data structure needed to transfer new style uniforms to GrUniformDataManager.
+ * This must be called before appendUniformDecls() in order to ensure new style uniforms get
+ * declared. It must be called only once.
+ */
+ GrUniformDataManager::ProgramUniforms getNewProgramUniforms(const GrUniformAggregator&);
+
private:
explicit GrMtlUniformHandler(GrGLSLProgramBuilder* program)
: INHERITED(program)
@@ -87,18 +96,19 @@
return fSamplers.item(handle.toIndex()).fVisibility;
}
- void appendUniformDecls(GrShaderFlags, SkString*) const override;
+ void appendUniformDecls(const GrUniformAggregator&, GrShaderFlags, SkString*) const override;
const UniformInfo& getUniformInfo(UniformHandle u) const {
return fUniforms.item(u.toIndex());
}
UniformInfoArray fUniforms;
+ UniformInfoArray fNewUniforms;
UniformInfoArray fSamplers;
SkTArray<GrSwizzle> fSamplerSwizzles;
- uint32_t fCurrentUBOOffset;
- uint32_t fCurrentUBOMaxAlignment;
+ uint32_t fCurrentUBOOffset;
+ uint32_t fCurrentUBOMaxAlignment;
friend class GrMtlPipelineStateBuilder;
diff --git a/src/gpu/mtl/GrMtlUniformHandler.mm b/src/gpu/mtl/GrMtlUniformHandler.mm
index 77b2a80..45ac29c 100644
--- a/src/gpu/mtl/GrMtlUniformHandler.mm
+++ b/src/gpu/mtl/GrMtlUniformHandler.mm
@@ -284,7 +284,43 @@
return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
}
-void GrMtlUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
+GrUniformDataManager::ProgramUniforms GrMtlUniformHandler::getNewProgramUniforms(
+ const GrUniformAggregator& aggregator) {
+ GrUniformDataManager::ProgramUniforms result;
+ result.reserve(aggregator.numProcessors());
+ for (int p = 0; p < aggregator.numProcessors(); ++p) {
+ GrUniformDataManager::ProcessorUniforms uniforms;
+ auto records = aggregator.processorRecords(p);
+ uniforms.reserve(records.size());
+ for (const GrUniformAggregator::Record& record : records) {
+ const GrProcessor::Uniform& u = record.uniform();
+ uint32_t offset = get_ubo_aligned_offset(&fCurrentUBOOffset,
+ &fCurrentUBOMaxAlignment,
+ u.type(),
+ u.count());
+ uniforms.push_back({record.indexInProcessor, u.type(), u.count(), offset});
+
+ // Add to fNewUniforms so that these get declared.
+ MtlUniformInfo info;
+ GrShaderVar var(record.name, u.type(), u.count());
+ SkString qualifier = SkStringPrintf("offset = %d", offset);
+ var.addLayoutQualifier(qualifier.c_str());
+ info.fUBOffset = offset;
+ info.fVariable = var;
+ info.fVisibility = u.visibility();
+ info.fOwner = nullptr;
+
+ fNewUniforms.emplace_back(info);
+ }
+ result.push_back(std::move(uniforms));
+ }
+
+ return result;
+}
+
+void GrMtlUniformHandler::appendUniformDecls(const GrUniformAggregator& aggregator,
+ GrShaderFlags visibility,
+ SkString* out) const {
for (const UniformInfo& sampler : fSamplers.items()) {
SkASSERT(sampler.fVariable.getType() == kTexture2DSampler_GrSLType);
if (visibility == sampler.fVisibility) {
@@ -315,6 +351,16 @@
}
}
+ for (const UniformInfo& localUniform : fNewUniforms.items()) {
+ // We don't check the visibility here. We want the same uniform block declaration in each
+ // shader. Note that internalAddUniform() sets both fragment and vertex visibility for all
+ // the legacy uniforms for the same reason.
+ if (GrSLTypeCanBeUniformValue(localUniform.fVariable.getType())) {
+ localUniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), &uniformsString);
+ uniformsString.append(";\n");
+ }
+ }
+
if (!uniformsString.isEmpty()) {
out->appendf("layout (binding=%d) uniform uniformBuffer\n{\n", kUniformBinding);
out->appendf("%s\n};\n", uniformsString.c_str());
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 5bff43b..ec050bb 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -19,6 +19,7 @@
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrStyle.h"
+#include "src/gpu/GrUniformAggregator.h"
#include "src/gpu/GrVertexWriter.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
@@ -732,9 +733,7 @@
void addToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
b->addBits(2, static_cast<uint32_t>(fStyle), "style");
- b->addBits(ProgramImpl::kMatrixKeyBits,
- ProgramImpl::ComputeMatrixKey(caps, fViewMatrix),
- "viewMatrixType");
+ b->addBool(fViewMatrix.hasPerspective(), "matrix_perspective");
}
std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override {
@@ -742,41 +741,22 @@
}
private:
- DIEllipseGeometryProcessor(bool wideColor, bool useScale, const SkMatrix& viewMatrix,
- DIEllipseStyle style)
- : INHERITED(kDIEllipseGeometryProcessor_ClassID)
- , fViewMatrix(viewMatrix)
- , fUseScale(useScale)
- , fStyle(style) {
- fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
- fInColor = MakeColorAttribute("inColor", wideColor);
- if (useScale) {
- fInEllipseOffsets0 = {"inEllipseOffsets0", kFloat3_GrVertexAttribType,
- kFloat3_GrSLType};
- } else {
- fInEllipseOffsets0 = {"inEllipseOffsets0", kFloat2_GrVertexAttribType,
- kFloat2_GrSLType};
- }
- fInEllipseOffsets1 = {"inEllipseOffsets1", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
- this->setVertexAttributes(&fInPosition, 4);
- }
+ DIEllipseGeometryProcessor(bool wideColor,
+ bool useScale,
+ const SkMatrix& viewMatrix,
+ DIEllipseStyle style);
class Impl : public ProgramImpl {
public:
- void setData(const GrGLSLProgramDataManager& pdman,
- const GrShaderCaps& shaderCaps,
- const GrGeometryProcessor& geomProc) override {
- const auto& diegp = geomProc.cast<DIEllipseGeometryProcessor>();
-
- SetTransform(pdman, shaderCaps, fViewMatrixUniform, diegp.fViewMatrix, &fViewMatrix);
- }
+ void setData(const GrGLSLProgramDataManager&,
+ const GrShaderCaps&,
+ const GrGeometryProcessor&) override {}
private:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const auto& diegp = args.fGeomProc.cast<DIEllipseGeometryProcessor>();
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
// emit attributes
varyingHandler->emitAttributes(diegp);
@@ -795,14 +775,27 @@
varyingHandler->addPassThroughAttribute(diegp.fInColor.asShaderVar(),
args.fOutputColor);
- // Setup position
- WriteOutputPosition(vertBuilder,
- uniformHandler,
- *args.fShaderCaps,
- gpArgs,
- diegp.fInPosition.name(),
- diegp.fViewMatrix,
- &fViewMatrixUniform);
+ const char* vm = args.fUniforms.getUniformName(0, "viewMatrix");
+
+ auto posType = diegp.fViewMatrix.hasPerspective() ? kFloat3_GrSLType : kFloat2_GrSLType;
+ gpArgs->fPositionVar = GrShaderVar("outpos", posType);
+ vertBuilder->declAppend(gpArgs->fPositionVar);
+ if (posType == kFloat3_GrSLType) {
+ vertBuilder->codeAppendf("%s = %s * %s.xy1;\n",
+ gpArgs->fPositionVar.c_str(),
+ vm,
+ diegp.fInPosition.name());
+ } else if (args.fShaderCaps->nonsquareMatrixSupport()) {
+ vertBuilder->codeAppendf("%s = float3x2(%s) * %s.xy1;\n",
+ gpArgs->fPositionVar.c_str(),
+ vm,
+ diegp.fInPosition.name());
+ } else {
+ vertBuilder->codeAppendf("%s = (%s * %s.xy1).xy;\n",
+ gpArgs->fPositionVar.c_str(),
+ vm,
+ diegp.fInPosition.name());
+ }
gpArgs->fLocalCoordVar = diegp.fInPosition.asShaderVar();
// for outer curve
@@ -863,9 +856,6 @@
fragBuilder->codeAppendf("half4 %s = half4(half(edgeAlpha));", args.fOutputCoverage);
}
-
- SkMatrix fViewMatrix = SkMatrix::InvalidMatrix();
- UniformHandle fViewMatrixUniform;
};
Attribute fInPosition;
@@ -884,6 +874,32 @@
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor);
+DIEllipseGeometryProcessor::DIEllipseGeometryProcessor(bool wideColor,
+ bool useScale,
+ const SkMatrix& viewMatrix,
+ DIEllipseStyle style)
+ : INHERITED(kDIEllipseGeometryProcessor_ClassID)
+ , fViewMatrix(viewMatrix)
+ , fUseScale(useScale)
+ , fStyle(style) {
+ fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
+ fInColor = MakeColorAttribute("inColor", wideColor);
+ if (useScale) {
+ fInEllipseOffsets0 = {"inEllipseOffsets0", kFloat3_GrVertexAttribType, kFloat3_GrSLType};
+ } else {
+ fInEllipseOffsets0 = {"inEllipseOffsets0", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
+ }
+ fInEllipseOffsets1 = {"inEllipseOffsets1", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
+ this->setVertexAttributes(&fInPosition, 4);
+GR_BEGIN_UNIFORM_DEFINITIONS
+ static constexpr Uniform kViewMatrixU{kFloat3x3_GrSLType,
+ offsetof(DIEllipseGeometryProcessor, fViewMatrix),
+ kVertex_GrShaderFlag,
+ Uniform::CType::kSkMatrix};
+GR_END_UNIFORM_DEFINITIONS
+ this->setUniforms(SkMakeSpan(&kViewMatrixU, 1));
+}
+
#if GR_TEST_UTILS
GrGeometryProcessor* DIEllipseGeometryProcessor::TestCreate(GrProcessorTestData* d) {
bool wideColor = d->fRandom->nextBool();
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 73d0043..e7269e5 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -31,6 +31,7 @@
GrVkGpu* gpu,
sk_sp<const GrVkPipeline> pipeline,
const GrVkDescriptorSetManager::Handle& samplerDSHandle,
+ GrUniformDataManager::ProgramUniforms programUniforms,
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t uniformSize,
@@ -45,7 +46,7 @@
, fGPImpl(std::move(gpImpl))
, fXPImpl(std::move(xpImpl))
, fFPImpls(std::move(fpImpls))
- , fDataManager(uniforms, uniformSize, usePushConstants) {
+ , fDataManager(std::move(programUniforms), uniforms, uniformSize, usePushConstants) {
fNumSamplers = samplers.count();
for (const auto& sampler : samplers.items()) {
// We store the immutable samplers here and take a ref on the sampler. Once we switch to
@@ -77,6 +78,8 @@
SkISize colorAttachmentDimensions,
const GrProgramInfo& programInfo,
GrVkCommandBuffer* commandBuffer) {
+ fDataManager.setUniforms(programInfo);
+
this->setRenderTargetState(colorAttachmentDimensions, programInfo.origin());
fGPImpl->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc());
diff --git a/src/gpu/vk/GrVkPipelineState.h b/src/gpu/vk/GrVkPipelineState.h
index 3a70512..25862d0 100644
--- a/src/gpu/vk/GrVkPipelineState.h
+++ b/src/gpu/vk/GrVkPipelineState.h
@@ -42,6 +42,7 @@
GrVkPipelineState(GrVkGpu*,
sk_sp<const GrVkPipeline>,
const GrVkDescriptorSetManager::Handle& samplerDSHandle,
+ GrUniformDataManager::ProgramUniforms,
const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t uniformSize,
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index 51c8a47..bc7dbbc 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -182,6 +182,8 @@
dsLayout[GrVkUniformHandler::kInputDescSet] = resourceProvider.getInputDSLayout();
+ GrUniformDataManager::ProgramUniforms uniforms =
+ fUniformHandler.getNewProgramUniforms(fUniformAggregator);
this->finalizeShaders();
bool usePushConstants = fUniformHandler.usePushConstants();
@@ -344,6 +346,7 @@
return new GrVkPipelineState(fGpu,
std::move(pipeline),
samplerDSHandle,
+ std::move(uniforms),
fUniformHandles,
fUniformHandler.fUniforms,
fUniformHandler.currentOffset(),
diff --git a/src/gpu/vk/GrVkPipelineStateDataManager.cpp b/src/gpu/vk/GrVkPipelineStateDataManager.cpp
index c230113..3d7f170 100644
--- a/src/gpu/vk/GrVkPipelineStateDataManager.cpp
+++ b/src/gpu/vk/GrVkPipelineStateDataManager.cpp
@@ -14,16 +14,27 @@
#include "src/gpu/vk/GrVkCommandBuffer.h"
#include "src/gpu/vk/GrVkGpu.h"
-GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(const UniformInfoArray& uniforms,
- uint32_t uniformSize,
- bool usePushConstants)
- : INHERITED(uniforms.count(), uniformSize)
- , fUsePushConstants(usePushConstants) {
+static GrUniformDataManager::Layout get_layout(bool usePushConstants) {
+ return usePushConstants ? GrUniformDataManager::Layout::kStd430
+ : GrUniformDataManager::Layout::kStd140;
+}
+
+GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(
+ GrUniformDataManager::ProgramUniforms programUniforms,
+ const UniformInfoArray& uniforms,
+ uint32_t uniformSize,
+ bool usePushConstants)
+ : INHERITED(std::move(programUniforms),
+ get_layout(usePushConstants),
+ uniforms.count(),
+ uniformSize)
+ , fUsePushConstants(usePushConstants) {
// We must add uniforms in same order as the UniformInfoArray so that UniformHandles already
// owned by other objects will still match up here.
int i = 0;
GrVkUniformHandler::Layout memLayout = usePushConstants ? GrVkUniformHandler::kStd430Layout
: GrVkUniformHandler::kStd140Layout;
+
for (const auto& uniformInfo : uniforms.items()) {
Uniform& uniform = fUniforms[i];
SkASSERT(GrShaderVar::kNonArray == uniformInfo.fVariable.getArrayCount() ||
diff --git a/src/gpu/vk/GrVkPipelineStateDataManager.h b/src/gpu/vk/GrVkPipelineStateDataManager.h
index cf4451e..416d55b 100644
--- a/src/gpu/vk/GrVkPipelineStateDataManager.h
+++ b/src/gpu/vk/GrVkPipelineStateDataManager.h
@@ -8,9 +8,8 @@
#ifndef GrVkPipelineStateDataManager_DEFINED
#define GrVkPipelineStateDataManager_DEFINED
-#include "src/gpu/GrUniformDataManager.h"
-
#include "include/gpu/vk/GrVkTypes.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "src/gpu/vk/GrVkUniformHandler.h"
class GrGpuBuffer;
@@ -21,7 +20,9 @@
public:
typedef GrVkUniformHandler::UniformInfoArray UniformInfoArray;
- GrVkPipelineStateDataManager(const UniformInfoArray&, uint32_t uniformSize,
+ GrVkPipelineStateDataManager(ProgramUniforms programUniforms,
+ const UniformInfoArray&,
+ uint32_t uniformSize,
bool usePushConstants);
// Returns the uniform buffer that holds all the uniform data. If there are no uniforms it
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp
index a0a5fd4..88f9462 100644
--- a/src/gpu/vk/GrVkUniformHandler.cpp
+++ b/src/gpu/vk/GrVkUniformHandler.cpp
@@ -324,7 +324,57 @@
return GrGLSLUniformHandler::SamplerHandle(0);
}
-void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
+GrUniformDataManager::ProgramUniforms GrVkUniformHandler::getNewProgramUniforms(
+ const GrUniformAggregator& aggregator) {
+ // First get all the offsets for both layouts, decide which layout will be used, and then
+ // build the result based on the decision.
+ std::vector<uint32_t> offsets[kLayoutCount];
+ for (int i = 0; i < kLayoutCount; ++i) {
+ offsets[i].reserve(aggregator.uniformCount());
+ }
+ for (const auto& record : aggregator.records()) {
+ const GrProcessor::Uniform& u = record.uniform();
+ for (int l = 0; l < kLayoutCount; ++l) {
+ offsets[l].push_back(get_aligned_offset(&fCurrentOffsets[l], u.type(), u.count(), l));
+ }
+ }
+
+ // At this point we determine whether we'll be using push constants based on the
+ // uniforms set so far. Later checks will use the internal bool we set here to
+ // keep things consistent.
+ this->determineIfUsePushConstants();
+
+ auto chosenOffsets = fUsePushConstants ? offsets[kStd430Layout] : offsets[kStd140Layout];
+ int idx = 0;
+ GrUniformDataManager::ProgramUniforms result;
+ result.reserve(aggregator.numProcessors());
+ for (int p = 0; p < aggregator.numProcessors(); ++p) {
+ GrUniformDataManager::ProcessorUniforms uniforms;
+ auto records = aggregator.processorRecords(p);
+ uniforms.reserve(records.size());
+ for (const GrUniformAggregator::Record& record : records) {
+ const GrProcessor::Uniform& u = record.uniform();
+ uint32_t offset = chosenOffsets[idx];
+ uniforms.push_back({record.indexInProcessor, u.type(), u.count(), offset});
+
+ // Add to fNewUniforms so that these get declared.
+ UniformInfo& info = fNewUniforms.push_back();
+ GrShaderVar var(record.name, u.type(), u.count());
+ SkString qualifier = SkStringPrintf("offset = %d", offset);
+ var.addLayoutQualifier(qualifier.c_str());
+ info.fVariable = var;
+ info.fVisibility = u.visibility();
+ info.fOwner = nullptr;
+ ++idx;
+ }
+ result.push_back(std::move(uniforms));
+ }
+ return result;
+}
+
+void GrVkUniformHandler::appendUniformDecls(const GrUniformAggregator& aggregator,
+ GrShaderFlags visibility,
+ SkString* out) const {
for (const VkUniformInfo& sampler : fSamplers.items()) {
SkASSERT(sampler.fVariable.getType() == kTexture2DSampler_GrSLType ||
sampler.fVariable.getType() == kTextureExternalSampler_GrSLType);
@@ -347,17 +397,22 @@
if (!firstOffsetCheck) {
// Check to make sure we are starting our offset at 0 so the offset qualifier we
// set on each variable in the uniform block is valid.
- SkASSERT(0 == localUniform.fOffsets[kStd140Layout] &&
- 0 == localUniform.fOffsets[kStd430Layout]);
+ SkASSERT(localUniform.fOffsets[kStd140Layout] == 0 &&
+ localUniform.fOffsets[kStd430Layout] == 0);
+ firstOffsetCheck = true;
+ }
+ }
+ for (const VkUniformInfo& localUniform : fNewUniforms.items()) {
+ if (!firstOffsetCheck) {
+ // Check to make sure we are starting our offset at 0 so the offset qualifier we
+ // set on each variable in the uniform block is valid.
+ SkASSERT(localUniform.fOffsets[kStd140Layout] == 0 &&
+ localUniform.fOffsets[kStd430Layout] == 0);
firstOffsetCheck = true;
}
}
#endif
- // At this point we determine whether we'll be using push constants based on the
- // uniforms set so far. Later checks will use the internal bool we set here to
- // keep things consistent.
- this->determineIfUsePushConstants();
SkString uniformsString;
for (const VkUniformInfo& localUniform : fUniforms.items()) {
if (visibility & localUniform.fVisibility) {
@@ -369,7 +424,15 @@
}
}
}
-
+ SkASSERT(fNewUniforms.count() == aggregator.uniformCount());
+ for (const VkUniformInfo& localUniform : fNewUniforms.items()) {
+ if (visibility & localUniform.fVisibility) {
+ if (GrSLTypeCanBeUniformValue(localUniform.fVariable.getType())) {
+ localUniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), &uniformsString);
+ uniformsString.append(";\n");
+ }
+ }
+ }
if (!uniformsString.isEmpty()) {
if (fUsePushConstants) {
out->append("layout (push_constant) ");
@@ -388,7 +451,7 @@
return get_aligned_offset(¤tOffset, kFloat2_GrSLType, 0, layout);
}
-void GrVkUniformHandler::determineIfUsePushConstants() const {
+void GrVkUniformHandler::determineIfUsePushConstants() {
// We may insert a uniform for flipping origin-sensitive language features (e.g. sk_FragCoord).
// We won't know that for sure until then but we need to make this determination now,
// so assume we will need it.
diff --git a/src/gpu/vk/GrVkUniformHandler.h b/src/gpu/vk/GrVkUniformHandler.h
index 3328780..284dfb3 100644
--- a/src/gpu/vk/GrVkUniformHandler.h
+++ b/src/gpu/vk/GrVkUniformHandler.h
@@ -12,6 +12,7 @@
#include "src/core/SkTBlockList.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrShaderVar.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
#include "src/gpu/vk/GrVkSampler.h"
@@ -93,6 +94,14 @@
return fUsePushConstants ? fCurrentOffsets[kStd430Layout] : fCurrentOffsets[kStd140Layout];
}
+ /**
+ * Call after all legacy style uniforms have been added to assign offsets to new style uniforms
+ * and create the data structure needed to transfer new style uniforms to GrUniformDataManager.
+ * This must be called before appendUniformDecls() in order to ensure new style uniforms get
+ * declared. It must be called only once.
+ */
+ GrUniformDataManager::ProgramUniforms getNewProgramUniforms(const GrUniformAggregator&);
+
private:
explicit GrVkUniformHandler(GrGLSLProgramBuilder* program)
: INHERITED(program)
@@ -145,20 +154,21 @@
return fInputSwizzle;
}
- void appendUniformDecls(GrShaderFlags, SkString*) const override;
+ void appendUniformDecls(const GrUniformAggregator&, GrShaderFlags, SkString*) const override;
const VkUniformInfo& getUniformInfo(UniformHandle u) const {
return fUniforms.item(u.toIndex());
}
- void determineIfUsePushConstants() const;
+ void determineIfUsePushConstants();
UniformInfoArray fUniforms;
+ UniformInfoArray fNewUniforms;
UniformInfoArray fSamplers;
SkTArray<GrSwizzle> fSamplerSwizzles;
UniformInfo fInputUniform;
GrSwizzle fInputSwizzle;
- mutable bool fUsePushConstants;
+ bool fUsePushConstants;
uint32_t fCurrentOffsets[kLayoutCount];