[graphite] Finally, allocate uniform data in an arena
Bug: skia:12701 Change-Id: Ib02db7160599d3c15a01597c746ce5131f2998e0 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/526298 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
d271a2330e
commit
cd692a6bb0
@ -15,6 +15,7 @@
|
||||
|
||||
class SkTextureDataBlock;
|
||||
class SkUniformDataBlock;
|
||||
class SkUniformDataBlockPassThrough; // TODO: remove
|
||||
|
||||
namespace skgpu::graphite {
|
||||
|
||||
@ -30,7 +31,7 @@ class Task;
|
||||
class TaskGraph;
|
||||
|
||||
template<typename StorageT, typename BaseT> class PipelineDataCache;
|
||||
using UniformDataCache = PipelineDataCache<std::unique_ptr<SkUniformDataBlock>, SkUniformDataBlock>;
|
||||
using UniformDataCache = PipelineDataCache<SkUniformDataBlockPassThrough, SkUniformDataBlock>;
|
||||
using TextureDataCache = PipelineDataCache<std::unique_ptr<SkTextureDataBlock>, SkTextureDataBlock>;
|
||||
|
||||
class Recorder final {
|
||||
|
@ -370,7 +370,7 @@ namespace {
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
|
||||
void add_blendshader_uniform_data(SkShaderCodeDictionary* dict,
|
||||
void add_blendshader_uniform_data(const SkShaderCodeDictionary* dict,
|
||||
SkBlendMode bm,
|
||||
SkPipelineDataGatherer* gatherer) {
|
||||
VALIDATE_UNIFORMS(gatherer, dict, kBlendShader)
|
||||
|
@ -26,12 +26,16 @@ void SkPipelineDataGatherer::checkReset() {
|
||||
}
|
||||
#endif // SK_DEBUG
|
||||
|
||||
std::unique_ptr<SkUniformDataBlock> SkUniformDataBlock::Make(const SkUniformDataBlock& other,
|
||||
SkArenaAlloc* /* arena */) {
|
||||
char* newMem = new char[other.size()];
|
||||
memcpy(newMem, other.data(), other.size());
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SkUniformDataBlock* SkUniformDataBlock::Make(const SkUniformDataBlock& other,
|
||||
SkArenaAlloc* arena) {
|
||||
static constexpr size_t kUniformAlignment = alignof(void*);
|
||||
char* mem = static_cast<char*>(arena->makeBytesAlignedTo(other.size(), kUniformAlignment));
|
||||
memcpy(mem, other.data(), other.size());
|
||||
|
||||
return std::make_unique<SkUniformDataBlock>(SkSpan<const char>(newMem, other.size()), true);
|
||||
return arena->make([&](void* ptr) {
|
||||
return new (ptr) SkUniformDataBlock(SkSpan<const char>(mem, other.size()));
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t SkUniformDataBlock::hash() const {
|
||||
|
@ -28,15 +28,10 @@ class SkUniform;
|
||||
|
||||
class SkUniformDataBlock {
|
||||
public:
|
||||
static std::unique_ptr<SkUniformDataBlock> Make(const SkUniformDataBlock&, SkArenaAlloc*);
|
||||
static SkUniformDataBlock* Make(const SkUniformDataBlock&, SkArenaAlloc*);
|
||||
|
||||
SkUniformDataBlock(SkSpan<const char> data, bool ownMem) : fData(data), fOwnMem(ownMem) {}
|
||||
SkUniformDataBlock(SkSpan<const char> data) : fData(data) {}
|
||||
SkUniformDataBlock() = default;
|
||||
~SkUniformDataBlock() {
|
||||
if (fOwnMem) {
|
||||
delete [] fData.data();
|
||||
}
|
||||
}
|
||||
|
||||
const char* data() const { return fData.data(); }
|
||||
size_t size() const { return fData.size(); }
|
||||
@ -51,10 +46,21 @@ public:
|
||||
|
||||
private:
|
||||
SkSpan<const char> fData;
|
||||
};
|
||||
|
||||
// This is only required until the uniform data is stored in the arena. Once there this
|
||||
// class will never delete the data referenced w/in the span
|
||||
bool fOwnMem = false;
|
||||
// We would like to store just a "const SkUniformDataBlock*" in the UniformDataCache but, until
|
||||
// the TextureDataCache is switched over to storing its data in an arena, whatever is held in
|
||||
// the cache must interoperate w/ std::unique_ptr (i.e., have a get() function).
|
||||
// TODO: remove this class
|
||||
class SkUniformDataBlockPassThrough {
|
||||
public:
|
||||
SkUniformDataBlockPassThrough() = default;
|
||||
SkUniformDataBlockPassThrough(SkUniformDataBlock* udb) : fUDB(udb) {}
|
||||
|
||||
SkUniformDataBlock* get() const { return fUDB; }
|
||||
|
||||
private:
|
||||
SkUniformDataBlock* fUDB = nullptr;
|
||||
};
|
||||
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
@ -155,9 +161,9 @@ public:
|
||||
void write(const SkRect& rect) { fUniformManager.write(rect); }
|
||||
void write(SkPoint point) { fUniformManager.write(point); }
|
||||
void write(const float* floats, int count) { fUniformManager.write(floats, count); }
|
||||
void write(float something) { fUniformManager.write(&something, 1); }
|
||||
void write(int something) { fUniformManager.write(something); }
|
||||
void write(skgpu::graphite::float2 something) { fUniformManager.write(something); }
|
||||
void write(float f) { fUniformManager.write(&f, 1); }
|
||||
void write(int i) { fUniformManager.write(i); }
|
||||
void write(skgpu::graphite::float2 v) { fUniformManager.write(v); }
|
||||
|
||||
bool hasUniforms() const { return fUniformManager.size(); }
|
||||
|
||||
|
@ -200,7 +200,7 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
const SkUniformDataBlock *udb = fUniformDataCache->lookup(uIndex);
|
||||
const SkUniformDataBlock* udb = fUniformDataCache->lookup(uIndex);
|
||||
SkASSERT(udb);
|
||||
|
||||
if (fBindings.find(uIndex.asUInt()) == fBindings.end()) {
|
||||
|
@ -140,7 +140,7 @@ private:
|
||||
|
||||
// A UniformDataCache lives for the entire duration of a Recorder. As such it has a greater
|
||||
// likelihood of overflowing a uint32_t index.
|
||||
using UniformDataCache = PipelineDataCache<std::unique_ptr<SkUniformDataBlock>, SkUniformDataBlock>;
|
||||
using UniformDataCache = PipelineDataCache<SkUniformDataBlockPassThrough, 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
|
||||
|
@ -509,7 +509,7 @@ UniformManager::UniformManager(Layout layout) : fLayout(layout) {
|
||||
}
|
||||
|
||||
SkUniformDataBlock UniformManager::peekData() const {
|
||||
return SkUniformDataBlock(SkMakeSpan(fStorage.begin(), fStorage.count()), false);
|
||||
return SkUniformDataBlock(SkMakeSpan(fStorage.begin(), fStorage.count()));
|
||||
}
|
||||
|
||||
void UniformManager::reset() {
|
||||
@ -598,16 +598,16 @@ void UniformManager::write(const float* floats, int count) {
|
||||
this->write(kType, count, floats);
|
||||
}
|
||||
|
||||
void UniformManager::write(int something) {
|
||||
void UniformManager::write(int i) {
|
||||
static const SkSLType kType = SkSLType::kInt;
|
||||
SkDEBUGCODE(this->checkExpected(kType, 1);)
|
||||
this->write(kType, 1, &something);
|
||||
this->write(kType, 1, &i);
|
||||
}
|
||||
|
||||
void UniformManager::write(float2 something) {
|
||||
void UniformManager::write(float2 v) {
|
||||
static const SkSLType kType = SkSLType::kFloat2;
|
||||
SkDEBUGCODE(this->checkExpected(kType, 1);)
|
||||
this->write(kType, 1, &something);
|
||||
this->write(kType, 1, &v);
|
||||
}
|
||||
|
||||
} // namespace skgpu::graphite
|
||||
|
@ -30,6 +30,7 @@ enum class Layout {
|
||||
kMetal, /** This is our own self-imposed layout we use for Metal. */
|
||||
};
|
||||
|
||||
// TODO: This is only used in the SkPipelineDataGatherer - maybe hide it better.
|
||||
class UniformManager {
|
||||
public:
|
||||
UniformManager(Layout layout);
|
||||
|
@ -16,14 +16,6 @@
|
||||
|
||||
using namespace skgpu::graphite;
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<SkUniformDataBlock> make_udb(const char* data, size_t size) {
|
||||
return std::make_unique<SkUniformDataBlock>(SkMakeSpan(data, size), false);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DEF_GRAPHITE_TEST_FOR_CONTEXTS(PipelineDataCacheTest, reporter, context) {
|
||||
std::unique_ptr<Recorder> recorder = context->makeRecorder();
|
||||
|
||||
@ -46,13 +38,13 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(PipelineDataCacheTest, reporter, context) {
|
||||
static const char kMemory1[kSize] = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22
|
||||
};
|
||||
std::unique_ptr<SkUniformDataBlock> udb1 = make_udb(kMemory1, kSize);
|
||||
SkUniformDataBlock udb1(SkMakeSpan(kMemory1, kSize));
|
||||
UniformDataCache::Index id1;
|
||||
{
|
||||
id1 = cache->insert(*udb1);
|
||||
id1 = cache->insert(udb1);
|
||||
REPORTER_ASSERT(reporter, id1.isValid());
|
||||
const SkUniformDataBlock* lookup = cache->lookup(id1);
|
||||
REPORTER_ASSERT(reporter, *lookup == *udb1);
|
||||
REPORTER_ASSERT(reporter, *lookup == udb1);
|
||||
|
||||
REPORTER_ASSERT(reporter, cache->count() == 1);
|
||||
}
|
||||
@ -62,13 +54,13 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(PipelineDataCacheTest, reporter, context) {
|
||||
static const char kMemory2[kSize] = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22
|
||||
};
|
||||
std::unique_ptr<SkUniformDataBlock> udb2 = make_udb(kMemory2, kSize);
|
||||
UniformDataCache::Index id2 = cache->insert(*udb2);
|
||||
SkUniformDataBlock udb2(SkMakeSpan(kMemory2, kSize));
|
||||
UniformDataCache::Index id2 = cache->insert(udb2);
|
||||
REPORTER_ASSERT(reporter, id2.isValid());
|
||||
REPORTER_ASSERT(reporter, id2 == id1);
|
||||
const SkUniformDataBlock* lookup = cache->lookup(id2);
|
||||
REPORTER_ASSERT(reporter, *lookup == *udb1);
|
||||
REPORTER_ASSERT(reporter, *lookup == *udb2);
|
||||
REPORTER_ASSERT(reporter, *lookup == udb1);
|
||||
REPORTER_ASSERT(reporter, *lookup == udb2);
|
||||
|
||||
REPORTER_ASSERT(reporter, cache->count() == 1);
|
||||
}
|
||||
@ -78,13 +70,13 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(PipelineDataCacheTest, reporter, context) {
|
||||
static const char kMemory3[kSize] = {
|
||||
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
|
||||
};
|
||||
std::unique_ptr<SkUniformDataBlock> udb3 = make_udb(kMemory3, kSize);
|
||||
UniformDataCache::Index id3 = cache->insert(*udb3);
|
||||
SkUniformDataBlock udb3(SkMakeSpan(kMemory3, kSize));
|
||||
UniformDataCache::Index id3 = cache->insert(udb3);
|
||||
REPORTER_ASSERT(reporter, id3.isValid());
|
||||
REPORTER_ASSERT(reporter, id3 != id1);
|
||||
const SkUniformDataBlock* lookup = cache->lookup(id3);
|
||||
REPORTER_ASSERT(reporter, *lookup == *udb3);
|
||||
REPORTER_ASSERT(reporter, *lookup != *udb1);
|
||||
REPORTER_ASSERT(reporter, *lookup == udb3);
|
||||
REPORTER_ASSERT(reporter, *lookup != udb1);
|
||||
|
||||
REPORTER_ASSERT(reporter, cache->count() == 2);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user