diff --git a/third_party/skia/src/gpu/graphite/PipelineData.h b/third_party/skia/src/gpu/graphite/PipelineData.h index 236a3f177d2..d8746a83089 100644 --- a/third_party/skia/src/gpu/graphite/PipelineData.h +++ b/third_party/skia/src/gpu/graphite/PipelineData.h @@ -475,12 +475,16 @@ public: // and returns a pointer to the start of the new data and the calculated offset. std::pair allocateGradientData(int numStops, const SkGradientBaseShader* shader) { SkASSERT(!this->isFinalized()); - int* existingOffset = fGradientOffsetCache.find(shader->uniqueID()); - if (existingOffset) { - return {nullptr, *existingOffset}; + CacheEntry* existing = fGradientOffsetCache.find(shader->uniqueID()); + // SkShaderBase::uniqueID() is a process-global 32-bit counter that can wrap, so + // two distinct gradients can share an ID. Only honor a cache hit if numStops + // matches the cached allocation; otherwise the caller's draw would index past + // the bound storage buffer. + if (existing && existing->fNumStops == numStops) { + return {nullptr, existing->fOffset}; } auto [ptr, offset] = this->allocateFloatData(numStops * 5); // 4 for color, 1 for offset - fGradientOffsetCache.set(shader->uniqueID(), offset); + fGradientOffsetCache.set(shader->uniqueID(), {offset, numStops}); return {ptr, offset}; } @@ -522,8 +526,12 @@ private: // storage buffer can be bound once and accessed at random. SkTDArray fGradientStorage; + struct CacheEntry { + int fOffset; + int fNumStops; + }; // We use the shader's unique ID as a key to de-duplicate gradient data. - skia_private::THashMap fGradientOffsetCache; + skia_private::THashMap fGradientOffsetCache; std::optional fBufferInfo = std::nullopt; };