| /* | |
| * 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/gpu/graphite/PipelineData.h" | |
| #include "src/core/SkOpts.h" | |
| #include "src/gpu/graphite/ShaderCodeDictionary.h" | |
| namespace skgpu::graphite { | |
| using SnippetRequirementFlags = SnippetRequirementFlags; | |
| PipelineDataGatherer::PipelineDataGatherer(Layout layout) | |
| : fUniformManager(layout), fSnippetRequirementFlags(SnippetRequirementFlags::kNone) {} | |
| void PipelineDataGatherer::resetWithNewLayout(Layout layout) { | |
| fUniformManager.resetWithNewLayout(layout); | |
| fTextureDataBlock.reset(); | |
| fSnippetRequirementFlags = SnippetRequirementFlags::kNone; | |
| } | |
| #ifdef SK_DEBUG | |
| void PipelineDataGatherer::checkReset() { | |
| SkASSERT(fTextureDataBlock.empty()); | |
| SkDEBUGCODE(fUniformManager.checkReset()); | |
| SkASSERT(fSnippetRequirementFlags == SnippetRequirementFlags::kNone); | |
| } | |
| void PipelineDataGatherer::setExpectedUniforms(SkSpan<const Uniform> expectedUniforms) { | |
| fUniformManager.setExpectedUniforms(expectedUniforms); | |
| } | |
| #endif // SK_DEBUG | |
| void PipelineDataGatherer::addFlags(SkEnumBitMask<SnippetRequirementFlags> flags) { | |
| fSnippetRequirementFlags |= flags; | |
| } | |
| bool PipelineDataGatherer::needsLocalCoords() const { | |
| return fSnippetRequirementFlags & SnippetRequirementFlags::kLocalCoords; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| UniformDataBlock* UniformDataBlock::Make(const UniformDataBlock& 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) UniformDataBlock(SkSpan<const char>(mem, other.size())); | |
| }); | |
| } | |
| uint32_t UniformDataBlock::hash() const { | |
| return SkOpts::hash_fn(fData.data(), fData.size(), 0); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////// | |
| TextureDataBlock* TextureDataBlock::Make(const TextureDataBlock& other, | |
| SkArenaAlloc* arena) { | |
| return arena->make([&](void *ptr) { | |
| return new (ptr) TextureDataBlock(other); | |
| }); | |
| } | |
| bool TextureDataBlock::operator==(const TextureDataBlock& 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 TextureDataBlock::hash() const { | |
| uint32_t hash = 0; | |
| for (auto& d : fTextureData) { | |
| uint32_t samplerKey = std::get<1>(d).asKey(); | |
| 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. | |
| uintptr_t proxy = reinterpret_cast<uintptr_t>(std::get<0>(d).get()); | |
| hash = SkOpts::hash_fn(&proxy, sizeof(proxy), hash); | |
| } | |
| return hash; | |
| } | |
| #ifdef SK_DEBUG | |
| UniformExpectationsValidator::UniformExpectationsValidator(PipelineDataGatherer *gatherer, | |
| SkSpan<const Uniform> expectedUniforms) | |
| : fGatherer(gatherer) { | |
| fGatherer->setExpectedUniforms(expectedUniforms); | |
| } | |
| #endif | |
| } // namespace skgpu::graphite |