| /* |
| * 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 |