blob: 74a6ffdea68429cc892d17aa89e160c7abec72eb [file] [log] [blame]
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/core/SkOpts.h"
#include "src/core/SkPipelineData.h"
#include "src/core/SkShaderCodeDictionary.h"
#ifdef SK_GRAPHITE_ENABLED
SkPipelineDataGatherer::SkPipelineDataGatherer(skgpu::graphite::Layout layout)
: fUniformManager(layout)
, fSnippetRequirementFlags(SnippetRequirementFlags::kNone) {
}
#endif
void SkPipelineDataGatherer::reset() {
#ifdef SK_GRAPHITE_ENABLED
fTextureDataBlock.reset();
fUniformManager.reset();
#endif
fSnippetRequirementFlags = SnippetRequirementFlags::kNone;
}
#ifdef SK_DEBUG
void SkPipelineDataGatherer::checkReset() {
#ifdef SK_GRAPHITE_ENABLED
SkASSERT(fTextureDataBlock.empty());
SkDEBUGCODE(fUniformManager.checkReset());
#endif
SkASSERT(fSnippetRequirementFlags == SnippetRequirementFlags::kNone);
}
#endif // SK_DEBUG
void SkPipelineDataGatherer::addFlags(SnippetRequirementFlags flags) {
fSnippetRequirementFlags |= flags;
}
bool SkPipelineDataGatherer::needsLocalCoords() const {
return fSnippetRequirementFlags & SnippetRequirementFlags::kLocalCoords;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
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 arena->make([&](void* ptr) {
return new (ptr) SkUniformDataBlock(SkSpan<const char>(mem, other.size()));
});
}
uint32_t SkUniformDataBlock::hash() const {
return SkOpts::hash_fn(fData.data(), fData.size(), 0);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef SK_GRAPHITE_ENABLED
static constexpr int kSkFilterModeCount = static_cast<int>(SkFilterMode::kLast) + 1;
std::unique_ptr<SkTextureDataBlock> SkTextureDataBlock::Make(const SkTextureDataBlock& other,
SkArenaAlloc* /* arena */) {
return std::make_unique<SkTextureDataBlock>(other);
}
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 SkTextureDataBlock::TextureInfo::samplerKey() const {
static_assert(kSkTileModeCount <= 4 && kSkFilterModeCount <= 2);
return (static_cast<int>(fTileModes[0]) << 0) |
(static_cast<int>(fTileModes[1]) << 2) |
(static_cast<int>(fSamplingOptions.filter) << 4) |
(static_cast<int>(fSamplingOptions.mipmap) << 5);
}
bool SkTextureDataBlock::operator==(const SkTextureDataBlock& other) const {
if (fTextureData.size() != other.fTextureData.size()) {
return false;
}
for (size_t i = 0; i < fTextureData.size(); ++i) {
if (fTextureData[i] != other.fTextureData[i]) {
return false;
}
}
return true;
}
uint32_t SkTextureDataBlock::hash() const {
uint32_t hash = 0;
for (auto& d : fTextureData) {
uint32_t samplerKey = d.samplerKey();
hash = SkOpts::hash_fn(&samplerKey, sizeof(samplerKey), hash);
// Because the lifetime of the TextureDataCache is for just one Recording and the
// TextureDataBlocks hold refs on their proxies, we can just use the proxy's pointer
// for the hash here. This is a bit sloppy though in that it would be nice if proxies backed
// by the same scratch texture hashed the same (it is tough to see how we could do that
// at DrawPass creation time though).
hash = SkOpts::hash_fn(d.fProxy.get(), sizeof(skgpu::graphite::TextureProxy*), hash);
}
return hash;
}
#endif