diff --git a/experimental/graphite/include/Recorder.h b/experimental/graphite/include/Recorder.h index 615db48bbf..b8463b170b 100644 --- a/experimental/graphite/include/Recorder.h +++ b/experimental/graphite/include/Recorder.h @@ -13,6 +13,7 @@ #include +class SkTextureDataBlock; class SkUniformDataBlock; namespace skgpu { @@ -30,6 +31,7 @@ class TaskGraph; template class PipelineDataCache; using UniformDataCache = PipelineDataCache; +using TextureDataCache = PipelineDataCache; class Recorder final { public: @@ -84,6 +86,7 @@ private: std::unique_ptr fGraph; std::unique_ptr fUniformDataCache; + std::unique_ptr fTextureDataCache; std::unique_ptr fDrawBufferManager; std::vector fTrackedDevices; diff --git a/experimental/graphite/include/Recording.h b/experimental/graphite/include/Recording.h index 0dce3362e7..5d8ee80dff 100644 --- a/experimental/graphite/include/Recording.h +++ b/experimental/graphite/include/Recording.h @@ -10,9 +10,13 @@ #include "include/core/SkRefCnt.h" +class SkTextureDataBlock; + namespace skgpu { class CommandBuffer; +template class PipelineDataCache; +using TextureDataCache = PipelineDataCache; class Recording final { public: @@ -22,9 +26,12 @@ protected: private: friend class Context; // for access fCommandBuffer friend class Recorder; // for ctor - Recording(sk_sp); + Recording(sk_sp, std::unique_ptr); sk_sp fCommandBuffer; + + // The TextureDataCache holds all the Textures and Samplers used in this Recording. + std::unique_ptr fTextureDataCache; }; } // namespace skgpu diff --git a/experimental/graphite/src/DrawPass.cpp b/experimental/graphite/src/DrawPass.cpp index 3b654288da..abd45bfa50 100644 --- a/experimental/graphite/src/DrawPass.cpp +++ b/experimental/graphite/src/DrawPass.cpp @@ -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 #include @@ -300,6 +298,7 @@ std::unique_ptr DrawPass::Make(Recorder* recorder, UniformDataCache geometryUniformDataCache; UniformBindingCache geometryUniformBindings(bufferMgr, &geometryUniformDataCache); UniformBindingCache shadingUniformBindings(bufferMgr, recorder->priv().uniformDataCache()); + TextureDataCache* textureDataCache = recorder->priv().textureDataCache(); std::unordered_map pipelineDescToIndex; @@ -320,13 +319,14 @@ std::unique_ptr 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 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::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::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::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(); diff --git a/experimental/graphite/src/PipelineDataCache.h b/experimental/graphite/src/PipelineDataCache.h index 1fcd9fed55..a29f7f4b34 100644 --- a/experimental/graphite/src/PipelineDataCache.h +++ b/experimental/graphite/src/PipelineDataCache.h @@ -139,7 +139,7 @@ using UniformDataCache = PipelineDataCache; // 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; +using TextureDataCache = PipelineDataCache; } // namespace skgpu diff --git a/experimental/graphite/src/Recorder.cpp b/experimental/graphite/src/Recorder.cpp index 43485c4baa..f80fb83fed 100644 --- a/experimental/graphite/src/Recorder.cpp +++ b/experimental/graphite/src/Recorder.cpp @@ -27,7 +27,8 @@ namespace skgpu { Recorder::Recorder(sk_sp gpu, sk_sp 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 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(new Recording(std::move(commandBuffer))); + std::unique_ptr recording(new Recording(std::move(commandBuffer), + std::move(fTextureDataCache))); + fTextureDataCache = std::make_unique(); + return recording; } void Recorder::registerDevice(Device* device) { diff --git a/experimental/graphite/src/RecorderPriv.cpp b/experimental/graphite/src/RecorderPriv.cpp index cd61c0748a..99e609cb35 100644 --- a/experimental/graphite/src/RecorderPriv.cpp +++ b/experimental/graphite/src/RecorderPriv.cpp @@ -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(); } diff --git a/experimental/graphite/src/RecorderPriv.h b/experimental/graphite/src/RecorderPriv.h index 02b8694680..2a125514be 100644 --- a/experimental/graphite/src/RecorderPriv.h +++ b/experimental/graphite/src/RecorderPriv.h @@ -18,6 +18,7 @@ public: ResourceProvider* resourceProvider() const; UniformDataCache* uniformDataCache() const; + TextureDataCache* textureDataCache() const; DrawBufferManager* drawBufferManager() const; const Caps* caps() const; diff --git a/experimental/graphite/src/Recording.cpp b/experimental/graphite/src/Recording.cpp index 9a04fffecf..d6bcb03bc2 100644 --- a/experimental/graphite/src/Recording.cpp +++ b/experimental/graphite/src/Recording.cpp @@ -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) - : fCommandBuffer(std::move(commandBuffer)){ +Recording::Recording(sk_sp commandBuffer, + std::unique_ptr textureDataCache) + : fCommandBuffer(std::move(commandBuffer)) + , fTextureDataCache(std::move(textureDataCache)) { } Recording::~Recording() {} diff --git a/src/core/SkPipelineData.cpp b/src/core/SkPipelineData.cpp index 3d449b5c29..f0de1c44db 100644 --- a/src/core/SkPipelineData.cpp +++ b/src/core/SkPipelineData.cpp @@ -8,10 +8,6 @@ #include "src/core/SkOpts.h" #include "src/core/SkPipelineData.h" -SkPipelineData::SkPipelineData(sk_sp initial) - : fUniformDataBlock(std::move(initial)) { -} - void SkPipelineData::add(sk_sp 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(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(fTileModes[0]) << 0) | (static_cast(fTileModes[1]) << 2) | @@ -81,7 +77,7 @@ uint32_t SkPipelineData::TextureDataBlock::TextureInfo::samplerKey() const { (static_cast(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) { diff --git a/src/core/SkPipelineData.h b/src/core/SkPipelineData.h index d4cd411a1e..cbe80e5460 100644 --- a/src/core/SkPipelineData.h +++ b/src/core/SkPipelineData.h @@ -51,6 +51,41 @@ private: std::vector> 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 fProxy; + SkSamplingOptions fSamplingOptions; + SkTileMode fTileModes[2]; + }; + + SkTextureDataBlock() = default; + + bool empty() const { return fTextureData.empty(); } + int numTextures() const { return SkTo(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 proxy) { + fTextureData.push_back({std::move(proxy), sampling, {tileModes[0], tileModes[1]}}); + } + +private: + std::vector 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 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 fProxy; - SkSamplingOptions fSamplingOptions; - SkTileMode fTileModes[2]; - }; - - TextureDataBlock() = default; - - bool empty() const { return fTextureData.empty(); } - int numTextures() const { return SkTo(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 proxy) { - fTextureData.push_back({std::move(proxy), sampling, {tileModes[0], tileModes[1]}}); - } - - private: - std::vector fTextureData; - }; - void add(const SkSamplingOptions& sampling, const SkTileMode tileModes[2], sk_sp 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); @@ -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 };