[graphite] Plumb through the BlendInfo
The general flow of the blendInfo is: It is created/filled in during the PaintParamsKey creation - it is currently stored on the SkPipelineData to get it out of the creation phase Ownership is "transferred" to the ShaderCodeDictionary::Entry when the PaintParamsKey is converted to a uniqueKey - this makes sense bc the blendInfo depends pretty directly on the PaintParamsKey When a FS is generated by a backend the BlendInfo is retrieved (from the SCD::Entry) and placed in the SkShaderInfo - the backend can then use the BlendInfo to set up the fixed-function blending Note: The duplication of the BlendInfo in the SkPipelineData and the SCD::Entry is unfortunate but may go away in the future. We are faced with the general problem of the pre-compilation pass needing to get both the structure of the uniforms a program requires and the BlendInfo but _not_ the uniforms. So, in the future, an SkPipelineData may always be passed in to collect data but then disassembled (e.g., the uniformBlock is cached, the blendInfo goes into the SCD::Entry, etc.) Bug: skia:12701 Change-Id: I5571809981cefa6770f69a4c1b8361db14afc44b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/517876 Reviewed-by: Jim Van Verth <jvanverth@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
88f90513a9
commit
5891d67871
@ -29,7 +29,7 @@ std::tuple<SkUniquePaintParamsID, std::unique_ptr<SkPipelineData>> ExtractPaintD
|
||||
|
||||
SkPaintParamsKey key = builder->lockAsKey();
|
||||
|
||||
auto entry = dict->findOrCreate(key);
|
||||
auto entry = dict->findOrCreate(key, pipelineData->blendInfo());
|
||||
|
||||
return { entry->uniqueID(), std::move(pipelineData) };
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "include/core/SkSpan.h"
|
||||
#include "include/gpu/ShaderErrorHandler.h"
|
||||
#include "include/private/SkSLString.h"
|
||||
#include "src/core/SkPipelineData.h"
|
||||
#include "src/core/SkShaderCodeDictionary.h"
|
||||
|
||||
namespace skgpu::mtl {
|
||||
@ -179,9 +180,9 @@ std::string get_sksl_vs(const GraphicsPipelineDesc& desc) {
|
||||
|
||||
std::string get_sksl_fs(SkShaderCodeDictionary* dict,
|
||||
const GraphicsPipelineDesc& desc,
|
||||
bool* writesColor) {
|
||||
SkPipelineData::BlendInfo* blendInfo) {
|
||||
if (!desc.paintParamsID().isValid()) {
|
||||
*writesColor = false;
|
||||
// TODO: we should return the error shader code here
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -189,7 +190,7 @@ std::string get_sksl_fs(SkShaderCodeDictionary* dict,
|
||||
|
||||
dict->getShaderInfo(desc.paintParamsID(), &shaderInfo);
|
||||
|
||||
*writesColor = shaderInfo.writesColor();
|
||||
*blendInfo = shaderInfo.blendInfo();
|
||||
#if SK_SUPPORT_GPU
|
||||
return shaderInfo.toSkSL();
|
||||
#else
|
||||
@ -327,6 +328,23 @@ MTLVertexDescriptor* create_vertex_descriptor(const RenderStep* step) {
|
||||
return vertexDescriptor;
|
||||
}
|
||||
|
||||
static MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment(
|
||||
MTLPixelFormat format,
|
||||
const SkPipelineData::BlendInfo& blendInfo) {
|
||||
|
||||
// TODO: I *think* this gets cleaned up by the pipelineDescriptor?
|
||||
auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
|
||||
|
||||
mtlColorAttachment.pixelFormat = format;
|
||||
|
||||
mtlColorAttachment.blendingEnabled = FALSE;
|
||||
|
||||
mtlColorAttachment.writeMask = blendInfo.fWritesColor ? MTLColorWriteMaskAll
|
||||
: MTLColorWriteMaskNone;
|
||||
|
||||
return mtlColorAttachment;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::string GetMtlUniforms(int bufferID,
|
||||
@ -382,10 +400,10 @@ sk_sp<GraphicsPipeline> GraphicsPipeline::Make(ResourceProvider* resourceProvide
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool writesColor;
|
||||
SkPipelineData::BlendInfo blendInfo;
|
||||
auto dict = resourceProvider->shaderCodeDictionary();
|
||||
if (!SkSLToMSL(gpu,
|
||||
get_sksl_fs(dict, pipelineDesc, &writesColor),
|
||||
get_sksl_fs(dict, pipelineDesc, &blendInfo),
|
||||
SkSL::ProgramKind::kFragment,
|
||||
settings,
|
||||
&msl[kFragment_ShaderType],
|
||||
@ -416,17 +434,11 @@ sk_sp<GraphicsPipeline> GraphicsPipeline::Make(ResourceProvider* resourceProvide
|
||||
// TODO: I *think* this gets cleaned up by the pipelineDescriptor?
|
||||
(*psoDescriptor).vertexDescriptor = create_vertex_descriptor(pipelineDesc.renderStep());
|
||||
|
||||
// TODO: I *think* this gets cleaned up by the pipelineDescriptor as well?
|
||||
auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
|
||||
|
||||
mtl::TextureInfo mtlTexInfo;
|
||||
renderPassDesc.fColorAttachment.fTextureInfo.getMtlTextureInfo(&mtlTexInfo);
|
||||
|
||||
mtlColorAttachment.pixelFormat = (MTLPixelFormat)mtlTexInfo.fFormat;
|
||||
|
||||
mtlColorAttachment.blendingEnabled = FALSE;
|
||||
|
||||
mtlColorAttachment.writeMask = writesColor ? MTLColorWriteMaskAll : MTLColorWriteMaskNone;
|
||||
auto mtlColorAttachment = create_color_attachment((MTLPixelFormat)mtlTexInfo.fFormat,
|
||||
blendInfo);
|
||||
|
||||
(*psoDescriptor).colorAttachments[0] = mtlColorAttachment;
|
||||
|
||||
|
@ -488,6 +488,11 @@ void AddToKey(SkShaderCodeDictionary* dict,
|
||||
validate_block_header(builder,
|
||||
SkBuiltInCodeSnippetID::kShaderBasedBlender,
|
||||
kBlockDataSize);
|
||||
|
||||
if (pipelineData) {
|
||||
// TODO: set up the correct blend info
|
||||
pipelineData->setBlendInfo(SkPipelineData::BlendInfo());
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif// SK_GRAPHITE_ENABLED
|
||||
@ -534,10 +539,12 @@ SkUniquePaintParamsID CreateKey(SkShaderCodeDictionary* dict,
|
||||
break;
|
||||
}
|
||||
|
||||
BlendModeBlock::AddToKey(dict, builder, nullptr, bm);
|
||||
// TODO: the blendInfo should be filled in by BlendModeBlock::AddToKey
|
||||
SkPipelineData::BlendInfo blendInfo;
|
||||
BlendModeBlock::AddToKey(dict, builder, /* pipelineData*/ nullptr, bm);
|
||||
SkPaintParamsKey key = builder->lockAsKey();
|
||||
|
||||
const SkShaderCodeDictionary::Entry* entry = dict->findOrCreate(key);
|
||||
auto entry = dict->findOrCreate(key, blendInfo);
|
||||
|
||||
return entry->uniqueID();
|
||||
}
|
||||
|
@ -230,10 +230,6 @@ void SkPaintParamsKey::AddBlockToShaderInfo(SkShaderCodeDictionary* dict,
|
||||
|
||||
AddBlockToShaderInfo(dict, childReader, result);
|
||||
}
|
||||
|
||||
if (reader.codeSnippetId() != SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw) {
|
||||
result->setWritesColor();
|
||||
}
|
||||
}
|
||||
|
||||
void SkPaintParamsKey::toShaderInfo(SkShaderCodeDictionary* dict, SkShaderInfo* result) const {
|
||||
|
@ -10,9 +10,12 @@
|
||||
|
||||
#include <vector>
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/SkColorData.h"
|
||||
#include "src/core/SkUniformData.h"
|
||||
|
||||
class SkUniformData;
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
#include "src/gpu/Blend.h"
|
||||
#endif
|
||||
|
||||
// TODO: The current plan for fixing uniform padding is for the SkPipelineData to hold a
|
||||
// persistent uniformManager. A stretch goal for this system would be for this combination
|
||||
@ -20,9 +23,34 @@ class SkUniformData;
|
||||
// obviously, vastly complicate uniform accumulation.
|
||||
class SkPipelineData {
|
||||
public:
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
struct BlendInfo {
|
||||
bool operator==(const BlendInfo& other) const {
|
||||
return fEquation == other.fEquation &&
|
||||
fSrcBlend == other.fSrcBlend &&
|
||||
fDstBlend == other.fDstBlend &&
|
||||
fBlendConstant == other.fBlendConstant &&
|
||||
fWritesColor == other.fWritesColor;
|
||||
}
|
||||
|
||||
skgpu::BlendEquation fEquation = skgpu::BlendEquation::kAdd;
|
||||
skgpu::BlendCoeff fSrcBlend = skgpu::BlendCoeff::kOne;
|
||||
skgpu::BlendCoeff fDstBlend = skgpu::BlendCoeff::kZero;
|
||||
SkPMColor4f fBlendConstant = SK_PMColor4fTRANSPARENT;
|
||||
bool fWritesColor = true;
|
||||
};
|
||||
#endif
|
||||
|
||||
SkPipelineData() = default;
|
||||
SkPipelineData(sk_sp<SkUniformData> initial);
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
void setBlendInfo(const SkPipelineData::BlendInfo& blendInfo) {
|
||||
fBlendInfo = blendInfo;
|
||||
}
|
||||
const BlendInfo& blendInfo() const { return fBlendInfo; }
|
||||
#endif
|
||||
|
||||
void add(sk_sp<SkUniformData>);
|
||||
|
||||
bool empty() const { return fUniformData.empty(); }
|
||||
@ -45,6 +73,10 @@ public:
|
||||
private:
|
||||
// TODO: SkUniformData should be held uniquely
|
||||
std::vector<sk_sp<SkUniformData>> fUniformData;
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
BlendInfo fBlendInfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SkPipelineData_DEFINED
|
||||
|
@ -125,12 +125,21 @@ std::string SkShaderInfo::toSkSL() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::makeEntry(const SkPaintParamsKey& key) {
|
||||
SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::makeEntry(
|
||||
const SkPaintParamsKey& key
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
, const SkPipelineData::BlendInfo& blendInfo
|
||||
#endif
|
||||
) {
|
||||
uint8_t* newKeyData = fArena.makeArray<uint8_t>(key.sizeInBytes());
|
||||
memcpy(newKeyData, key.data(), key.sizeInBytes());
|
||||
|
||||
SkSpan<const uint8_t> newKeyAsSpan = SkMakeSpan(newKeyData, key.sizeInBytes());
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
return fArena.make([&](void *ptr) { return new(ptr) Entry(newKeyAsSpan, blendInfo); });
|
||||
#else
|
||||
return fArena.make([&](void *ptr) { return new(ptr) Entry(newKeyAsSpan); });
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t SkShaderCodeDictionary::Hash::operator()(const SkPaintParamsKey* key) const {
|
||||
@ -138,7 +147,11 @@ size_t SkShaderCodeDictionary::Hash::operator()(const SkPaintParamsKey* key) con
|
||||
}
|
||||
|
||||
const SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::findOrCreate(
|
||||
const SkPaintParamsKey& key) {
|
||||
const SkPaintParamsKey& key
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
, const SkPipelineData::BlendInfo& blendInfo
|
||||
#endif
|
||||
) {
|
||||
SkAutoSpinlock lock{fSpinLock};
|
||||
|
||||
auto iter = fHash.find(&key);
|
||||
@ -147,7 +160,11 @@ const SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::findOrCreate(
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
Entry* newEntry = this->makeEntry(key, blendInfo);
|
||||
#else
|
||||
Entry* newEntry = this->makeEntry(key);
|
||||
#endif
|
||||
newEntry->setUniqueID(fEntryVector.size());
|
||||
fHash.insert(std::make_pair(&newEntry->paintParamsKey(), newEntry));
|
||||
fEntryVector.push_back(newEntry);
|
||||
@ -198,6 +215,10 @@ void SkShaderCodeDictionary::getShaderInfo(SkUniquePaintParamsID uniqueID, SkSha
|
||||
auto entry = this->lookup(uniqueID);
|
||||
|
||||
entry->paintParamsKey().toShaderInfo(this, info);
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
info->setBlendInfo(entry->blendInfo());
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "include/private/SkUniquePaintParamsID.h"
|
||||
#include "src/core/SkArenaAlloc.h"
|
||||
#include "src/core/SkPaintParamsKey.h"
|
||||
#include "src/core/SkPipelineData.h"
|
||||
#include "src/core/SkUniform.h"
|
||||
|
||||
|
||||
@ -53,16 +54,19 @@ struct SkShaderSnippet {
|
||||
SkSpan<const SkPaintParamsKey::DataPayloadField> fDataPayloadExpectations;
|
||||
};
|
||||
|
||||
// This is just a simple collection object that gathers together all the information needed
|
||||
// for program creation and its invocation.
|
||||
class SkShaderInfo {
|
||||
public:
|
||||
void add(const SkShaderSnippet& entry) {
|
||||
fEntries.push_back(entry);
|
||||
}
|
||||
|
||||
// TODO: writing to color should be a property of the SnippetEntries and accumulated as the
|
||||
// entries are added. _Not_ set manually via 'setWritesColor'.
|
||||
void setWritesColor() { fWritesColor = true; }
|
||||
bool writesColor() const { return fWritesColor; }
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
void setBlendInfo(const SkPipelineData::BlendInfo& blendInfo) {
|
||||
fBlendInfo = blendInfo;
|
||||
}
|
||||
const SkPipelineData::BlendInfo& blendInfo() const { return fBlendInfo; }
|
||||
#endif
|
||||
|
||||
#if SK_SUPPORT_GPU && defined(SK_GRAPHITE_ENABLED) && defined(SK_METAL)
|
||||
std::string toSkSL() const;
|
||||
@ -75,7 +79,12 @@ private:
|
||||
int indent) const;
|
||||
|
||||
std::vector<SkShaderSnippet> fEntries;
|
||||
bool fWritesColor = false;
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
// The blendInfo doesn't actually contribute to the program's creation but, it contains the
|
||||
// matching fixed-function settings that the program's caller needs to set up.
|
||||
SkPipelineData::BlendInfo fBlendInfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
class SkShaderCodeDictionary {
|
||||
@ -89,11 +98,21 @@ public:
|
||||
return fUniqueID;
|
||||
}
|
||||
const SkPaintParamsKey& paintParamsKey() const { return fKey; }
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
const SkPipelineData::BlendInfo& blendInfo() const { return fBlendInfo; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class SkShaderCodeDictionary;
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
Entry(const SkPaintParamsKey& key, const SkPipelineData::BlendInfo& blendInfo)
|
||||
: fKey(key.asSpan())
|
||||
, fBlendInfo(blendInfo) {
|
||||
}
|
||||
#else
|
||||
Entry(const SkPaintParamsKey& key) : fKey(key.asSpan()) {}
|
||||
#endif
|
||||
|
||||
void setUniqueID(uint32_t newID) {
|
||||
SkASSERT(!fUniqueID.isValid());
|
||||
@ -102,9 +121,21 @@ public:
|
||||
|
||||
SkUniquePaintParamsID fUniqueID; // fixed-size (uint32_t) unique ID assigned to a key
|
||||
SkPaintParamsKey fKey; // variable-length paint key descriptor
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
// The BlendInfo isn't used in the hash (that is the key's job) but it does directly vary
|
||||
// with the key. It could, theoretically, be recreated from the key but that would add
|
||||
// extra complexity.
|
||||
SkPipelineData::BlendInfo fBlendInfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
const Entry* findOrCreate(const SkPaintParamsKey&,
|
||||
const SkPipelineData::BlendInfo&) SK_EXCLUDES(fSpinLock);
|
||||
#else
|
||||
const Entry* findOrCreate(const SkPaintParamsKey&) SK_EXCLUDES(fSpinLock);
|
||||
#endif
|
||||
|
||||
const Entry* lookup(SkUniquePaintParamsID) const SK_EXCLUDES(fSpinLock);
|
||||
|
||||
@ -131,7 +162,11 @@ public:
|
||||
SkSpan<const SkPaintParamsKey::DataPayloadField> expectations);
|
||||
|
||||
private:
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
Entry* makeEntry(const SkPaintParamsKey&, const SkPipelineData::BlendInfo&);
|
||||
#else
|
||||
Entry* makeEntry(const SkPaintParamsKey&);
|
||||
#endif
|
||||
|
||||
struct Hash {
|
||||
size_t operator()(const SkPaintParamsKey*) const;
|
||||
|
Loading…
Reference in New Issue
Block a user