[graphite] Add TextureDataCache
This adds caching and uniquifying of SkTextureDataBlocks to parallel our treatment of SkUniformDataBlocks. Bug: skia:12701 Change-Id: Ib4474f48b9048daf4b848ccbb339cb42246f184b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/523418 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
7ef299accb
commit
a7c2d73690
@ -13,6 +13,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
class SkTextureDataBlock;
|
||||
class SkUniformDataBlock;
|
||||
|
||||
namespace skgpu {
|
||||
@ -30,6 +31,7 @@ class TaskGraph;
|
||||
|
||||
template<typename DataBlockT> class PipelineDataCache;
|
||||
using UniformDataCache = PipelineDataCache<SkUniformDataBlock>;
|
||||
using TextureDataCache = PipelineDataCache<SkTextureDataBlock>;
|
||||
|
||||
class Recorder final {
|
||||
public:
|
||||
@ -84,6 +86,7 @@ private:
|
||||
|
||||
std::unique_ptr<TaskGraph> fGraph;
|
||||
std::unique_ptr<UniformDataCache> fUniformDataCache;
|
||||
std::unique_ptr<TextureDataCache> fTextureDataCache;
|
||||
std::unique_ptr<DrawBufferManager> fDrawBufferManager;
|
||||
std::vector<Device*> fTrackedDevices;
|
||||
|
||||
|
@ -10,9 +10,13 @@
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
|
||||
class SkTextureDataBlock;
|
||||
|
||||
namespace skgpu {
|
||||
|
||||
class CommandBuffer;
|
||||
template<typename DataBlockT> class PipelineDataCache;
|
||||
using TextureDataCache = PipelineDataCache<SkTextureDataBlock>;
|
||||
|
||||
class Recording final {
|
||||
public:
|
||||
@ -22,9 +26,12 @@ protected:
|
||||
private:
|
||||
friend class Context; // for access fCommandBuffer
|
||||
friend class Recorder; // for ctor
|
||||
Recording(sk_sp<CommandBuffer>);
|
||||
Recording(sk_sp<CommandBuffer>, std::unique_ptr<TextureDataCache>);
|
||||
|
||||
sk_sp<CommandBuffer> fCommandBuffer;
|
||||
|
||||
// The TextureDataCache holds all the Textures and Samplers used in this Recording.
|
||||
std::unique_ptr<TextureDataCache> fTextureDataCache;
|
||||
};
|
||||
|
||||
} // namespace skgpu
|
||||
|
@ -31,8 +31,6 @@
|
||||
#include "src/core/SkPaintParamsKey.h"
|
||||
#include "src/core/SkPipelineData.h"
|
||||
#include "src/core/SkTBlockList.h"
|
||||
#include "src/core/SkUniformData.h"
|
||||
#include "src/gpu/BufferWriter.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
@ -300,6 +298,7 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
UniformDataCache geometryUniformDataCache;
|
||||
UniformBindingCache geometryUniformBindings(bufferMgr, &geometryUniformDataCache);
|
||||
UniformBindingCache shadingUniformBindings(bufferMgr, recorder->priv().uniformDataCache());
|
||||
TextureDataCache* textureDataCache = recorder->priv().textureDataCache();
|
||||
|
||||
std::unordered_map<const GraphicsPipelineDesc*, uint32_t, Hash, Eq> pipelineDescToIndex;
|
||||
|
||||
@ -320,13 +319,14 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
// and remember the location for re-use on any RenderStep that does shading.
|
||||
SkUniquePaintParamsID shaderID;
|
||||
UniformDataCache::Index shadingUniformIndex;
|
||||
TextureDataCache::Index textureBindingIndex; // TODO: fill in the textureBinding field
|
||||
TextureDataCache::Index textureBindingIndex;
|
||||
if (draw.fPaintParams.has_value()) {
|
||||
std::unique_ptr<SkPipelineData> pipelineData;
|
||||
std::tie(shaderID, pipelineData) = ExtractPaintData(recorder, &builder,
|
||||
draw.fPaintParams.value());
|
||||
shadingUniformIndex = shadingUniformBindings.addUniforms(
|
||||
pipelineData->uniformDataBlock());
|
||||
textureBindingIndex = textureDataCache->insert(pipelineData->textureDataBlock());
|
||||
} // else depth-only
|
||||
|
||||
for (int stepIndex = 0; stepIndex < draw.fRenderer.numRenderSteps(); ++stepIndex) {
|
||||
@ -396,6 +396,7 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
// Setting to # render steps ensures the very first time through the loop will bind a pipeline.
|
||||
uint32_t lastPipeline = draws->renderStepCount();
|
||||
UniformDataCache::Index lastShadingUniforms;
|
||||
TextureDataCache::Index lastTextureBindings;
|
||||
UniformDataCache::Index lastGeometryUniforms;
|
||||
SkIRect lastScissor = SkIRect::MakeSize(drawPass->fTarget->dimensions());
|
||||
|
||||
@ -407,6 +408,8 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
key.geometryUniforms() != lastGeometryUniforms;
|
||||
const bool shadingUniformChange = key.shadingUniforms().isValid() &&
|
||||
key.shadingUniforms() != lastShadingUniforms;
|
||||
const bool textureBindingsChange = key.textureBindings().isValid() &&
|
||||
key.textureBindings() != lastTextureBindings;
|
||||
|
||||
const bool pipelineChange = key.pipeline() != lastPipeline;
|
||||
const bool stateChange = geometryUniformChange ||
|
||||
@ -441,6 +444,10 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
BindUniformBuffer{binding, UniformSlot::kPaint});
|
||||
lastShadingUniforms = key.shadingUniforms();
|
||||
}
|
||||
if (textureBindingsChange) {
|
||||
// TODO: add BindTexturesAndSamplers command here
|
||||
lastTextureBindings = key.textureBindings();
|
||||
}
|
||||
if (draw.fClip.scissor() != lastScissor) {
|
||||
drawPass->fCommands.emplace_back(SetScissor{draw.fClip.scissor()});
|
||||
lastScissor = draw.fClip.scissor();
|
||||
|
@ -139,7 +139,7 @@ using UniformDataCache = PipelineDataCache<SkUniformDataBlock>;
|
||||
// A TextureDataCache only lives for a single Recording. When a Recording is snapped it is pulled
|
||||
// off of the Recorder and goes with the Recording as a record of the required Textures and
|
||||
// Samplers.
|
||||
using TextureDataCache = PipelineDataCache<SkPipelineData::TextureDataBlock>;
|
||||
using TextureDataCache = PipelineDataCache<SkTextureDataBlock>;
|
||||
|
||||
} // namespace skgpu
|
||||
|
||||
|
@ -27,7 +27,8 @@ namespace skgpu {
|
||||
Recorder::Recorder(sk_sp<Gpu> gpu, sk_sp<GlobalCache> globalCache)
|
||||
: fGpu(std::move(gpu))
|
||||
, fGraph(new TaskGraph)
|
||||
, fUniformDataCache(new UniformDataCache) {
|
||||
, fUniformDataCache(new UniformDataCache)
|
||||
, fTextureDataCache(new TextureDataCache) {
|
||||
|
||||
fResourceProvider = fGpu->makeResourceProvider(std::move(globalCache), this->singleOwner());
|
||||
fDrawBufferManager.reset(new DrawBufferManager(fResourceProvider.get(),
|
||||
@ -48,13 +49,19 @@ std::unique_ptr<Recording> Recorder::snap() {
|
||||
device->flushPendingWorkToRecorder();
|
||||
}
|
||||
|
||||
// TODO: fulfill all promise images in the TextureDataCache here
|
||||
// TODO: create all the samplers needed in the TextureDataCache here
|
||||
|
||||
auto commandBuffer = fResourceProvider->createCommandBuffer();
|
||||
|
||||
fGraph->addCommands(fResourceProvider.get(), commandBuffer.get());
|
||||
fDrawBufferManager->transferToCommandBuffer(commandBuffer.get());
|
||||
|
||||
fGraph->reset();
|
||||
return std::unique_ptr<Recording>(new Recording(std::move(commandBuffer)));
|
||||
std::unique_ptr<Recording> recording(new Recording(std::move(commandBuffer),
|
||||
std::move(fTextureDataCache)));
|
||||
fTextureDataCache = std::make_unique<TextureDataCache>();
|
||||
return recording;
|
||||
}
|
||||
|
||||
void Recorder::registerDevice(Device* device) {
|
||||
|
@ -23,6 +23,10 @@ UniformDataCache* RecorderPriv::uniformDataCache() const {
|
||||
return fRecorder->fUniformDataCache.get();
|
||||
}
|
||||
|
||||
TextureDataCache* RecorderPriv::textureDataCache() const {
|
||||
return fRecorder->fTextureDataCache.get();
|
||||
}
|
||||
|
||||
const Caps* RecorderPriv::caps() const {
|
||||
return fRecorder->fGpu->caps();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ public:
|
||||
|
||||
ResourceProvider* resourceProvider() const;
|
||||
UniformDataCache* uniformDataCache() const;
|
||||
TextureDataCache* textureDataCache() const;
|
||||
DrawBufferManager* drawBufferManager() const;
|
||||
const Caps* caps() const;
|
||||
|
||||
|
@ -8,11 +8,14 @@
|
||||
#include "experimental/graphite/include/Recording.h"
|
||||
|
||||
#include "experimental/graphite/src/CommandBuffer.h"
|
||||
#include "experimental/graphite/src/PipelineDataCache.h"
|
||||
|
||||
namespace skgpu {
|
||||
|
||||
Recording::Recording(sk_sp<CommandBuffer> commandBuffer)
|
||||
: fCommandBuffer(std::move(commandBuffer)){
|
||||
Recording::Recording(sk_sp<CommandBuffer> commandBuffer,
|
||||
std::unique_ptr<TextureDataCache> textureDataCache)
|
||||
: fCommandBuffer(std::move(commandBuffer))
|
||||
, fTextureDataCache(std::move(textureDataCache)) {
|
||||
}
|
||||
|
||||
Recording::~Recording() {}
|
||||
|
@ -8,10 +8,6 @@
|
||||
#include "src/core/SkOpts.h"
|
||||
#include "src/core/SkPipelineData.h"
|
||||
|
||||
SkPipelineData::SkPipelineData(sk_sp<SkUniformData> initial)
|
||||
: fUniformDataBlock(std::move(initial)) {
|
||||
}
|
||||
|
||||
void SkPipelineData::add(sk_sp<SkUniformData> uniforms) {
|
||||
SkASSERT(uniforms && uniforms->count());
|
||||
fUniformDataBlock.add(std::move(uniforms));
|
||||
@ -66,14 +62,14 @@ uint32_t SkUniformDataBlock::hash() const {
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
static constexpr int kSkFilterModeCount = static_cast<int>(SkFilterMode::kLast) + 1;
|
||||
|
||||
bool SkPipelineData::TextureDataBlock::TextureInfo::operator==(const TextureInfo& other) const {
|
||||
bool SkTextureDataBlock::TextureInfo::operator==(const TextureInfo& other) const {
|
||||
return fProxy == other.fProxy &&
|
||||
fSamplingOptions == other.fSamplingOptions &&
|
||||
fTileModes[0] == other.fTileModes[0] &&
|
||||
fTileModes[1] == other.fTileModes[1];
|
||||
}
|
||||
|
||||
uint32_t SkPipelineData::TextureDataBlock::TextureInfo::samplerKey() const {
|
||||
uint32_t SkTextureDataBlock::TextureInfo::samplerKey() const {
|
||||
static_assert(kSkTileModeCount <= 4 && kSkFilterModeCount <= 2);
|
||||
return (static_cast<int>(fTileModes[0]) << 0) |
|
||||
(static_cast<int>(fTileModes[1]) << 2) |
|
||||
@ -81,7 +77,7 @@ uint32_t SkPipelineData::TextureDataBlock::TextureInfo::samplerKey() const {
|
||||
(static_cast<int>(fSamplingOptions.mipmap) << 5);
|
||||
}
|
||||
|
||||
bool SkPipelineData::TextureDataBlock::operator==(const TextureDataBlock& other) const {
|
||||
bool SkTextureDataBlock::operator==(const SkTextureDataBlock& other) const {
|
||||
if (fTextureData.size() != other.fTextureData.size()) {
|
||||
return false;
|
||||
}
|
||||
@ -95,7 +91,7 @@ bool SkPipelineData::TextureDataBlock::operator==(const TextureDataBlock& other)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t SkPipelineData::TextureDataBlock::hash() const {
|
||||
uint32_t SkTextureDataBlock::hash() const {
|
||||
uint32_t hash = 0;
|
||||
|
||||
for (auto& d : fTextureData) {
|
||||
|
@ -51,6 +51,41 @@ private:
|
||||
std::vector<sk_sp<SkUniformData>> fUniformData;
|
||||
};
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
class SkTextureDataBlock {
|
||||
public:
|
||||
struct TextureInfo {
|
||||
bool operator==(const TextureInfo&) const;
|
||||
bool operator!=(const TextureInfo& other) const { return !(*this == other); }
|
||||
|
||||
uint32_t samplerKey() const;
|
||||
|
||||
sk_sp<skgpu::TextureProxy> fProxy;
|
||||
SkSamplingOptions fSamplingOptions;
|
||||
SkTileMode fTileModes[2];
|
||||
};
|
||||
|
||||
SkTextureDataBlock() = default;
|
||||
|
||||
bool empty() const { return fTextureData.empty(); }
|
||||
int numTextures() const { return SkTo<int>(fTextureData.size()); }
|
||||
const TextureInfo& texture(int index) { return fTextureData[index]; }
|
||||
|
||||
bool operator==(const SkTextureDataBlock&) const;
|
||||
bool operator!=(const SkTextureDataBlock& other) const { return !(*this == other); }
|
||||
uint32_t hash() const;
|
||||
|
||||
void add(const SkSamplingOptions& sampling,
|
||||
const SkTileMode tileModes[2],
|
||||
sk_sp<skgpu::TextureProxy> proxy) {
|
||||
fTextureData.push_back({std::move(proxy), sampling, {tileModes[0], tileModes[1]}});
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<TextureInfo> fTextureData;
|
||||
};
|
||||
#endif // SK_GRAPHITE_ENABLED
|
||||
|
||||
// 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
|
||||
// to accumulate all the uniforms and then rearrange them to minimize padding. This would,
|
||||
@ -76,7 +111,6 @@ public:
|
||||
#endif
|
||||
|
||||
SkPipelineData() = default;
|
||||
SkPipelineData(sk_sp<SkUniformData> initial);
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
void setBlendInfo(const SkPipelineData::BlendInfo& blendInfo) {
|
||||
@ -84,39 +118,6 @@ public:
|
||||
}
|
||||
const BlendInfo& blendInfo() const { return fBlendInfo; }
|
||||
|
||||
class TextureDataBlock {
|
||||
public:
|
||||
struct TextureInfo {
|
||||
bool operator==(const TextureInfo&) const;
|
||||
bool operator!=(const TextureInfo& other) const { return !(*this == other); }
|
||||
|
||||
uint32_t samplerKey() const;
|
||||
|
||||
sk_sp<skgpu::TextureProxy> fProxy;
|
||||
SkSamplingOptions fSamplingOptions;
|
||||
SkTileMode fTileModes[2];
|
||||
};
|
||||
|
||||
TextureDataBlock() = default;
|
||||
|
||||
bool empty() const { return fTextureData.empty(); }
|
||||
int numTextures() const { return SkTo<int>(fTextureData.size()); }
|
||||
const TextureInfo& texture(int index) { return fTextureData[index]; }
|
||||
|
||||
bool operator==(const TextureDataBlock&) const;
|
||||
bool operator!=(const TextureDataBlock& other) const { return !(*this == other); }
|
||||
uint32_t hash() const;
|
||||
|
||||
void add(const SkSamplingOptions& sampling,
|
||||
const SkTileMode tileModes[2],
|
||||
sk_sp<skgpu::TextureProxy> proxy) {
|
||||
fTextureData.push_back({std::move(proxy), sampling, {tileModes[0], tileModes[1]}});
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<TextureInfo> fTextureData;
|
||||
};
|
||||
|
||||
void add(const SkSamplingOptions& sampling,
|
||||
const SkTileMode tileModes[2],
|
||||
sk_sp<skgpu::TextureProxy> proxy) {
|
||||
@ -124,7 +125,7 @@ public:
|
||||
}
|
||||
bool hasTextures() const { return !fTextureDataBlock.empty(); }
|
||||
|
||||
const TextureDataBlock& textureDataBlock() { return fTextureDataBlock; }
|
||||
const SkTextureDataBlock& textureDataBlock() { return fTextureDataBlock; }
|
||||
#endif
|
||||
|
||||
void add(sk_sp<SkUniformData>);
|
||||
@ -132,17 +133,11 @@ public:
|
||||
|
||||
SkUniformDataBlock& uniformDataBlock() { return fUniformDataBlock; }
|
||||
|
||||
// TODO: remove these two once the PipelineDataCache has been split
|
||||
bool operator==(const SkPipelineData& that) const {
|
||||
return fUniformDataBlock == that.fUniformDataBlock;
|
||||
}
|
||||
uint32_t hash() const { return fUniformDataBlock.hash(); }
|
||||
|
||||
private:
|
||||
SkUniformDataBlock fUniformDataBlock;
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
TextureDataBlock fTextureDataBlock;
|
||||
SkTextureDataBlock fTextureDataBlock;
|
||||
BlendInfo fBlendInfo;
|
||||
#endif
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user