1 /*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/graphite/PipelineData.h"
9
10 #include "src/core/SkOpts.h"
11 #include "src/gpu/graphite/ShaderCodeDictionary.h"
12
13 namespace skgpu::graphite {
14
15 using SnippetRequirementFlags = SnippetRequirementFlags;
16
PipelineDataGatherer(Layout layout)17 PipelineDataGatherer::PipelineDataGatherer(Layout layout)
18 : fUniformManager(layout), fSnippetRequirementFlags(SnippetRequirementFlags::kNone) {}
19
resetWithNewLayout(Layout layout)20 void PipelineDataGatherer::resetWithNewLayout(Layout layout) {
21 fUniformManager.resetWithNewLayout(layout);
22 fTextureDataBlock.reset();
23 fSnippetRequirementFlags = SnippetRequirementFlags::kNone;
24 }
25
26 #ifdef SK_DEBUG
checkReset()27 void PipelineDataGatherer::checkReset() {
28 SkASSERT(fTextureDataBlock.empty());
29 SkDEBUGCODE(fUniformManager.checkReset());
30 SkASSERT(fSnippetRequirementFlags == SnippetRequirementFlags::kNone);
31 }
32
setExpectedUniforms(SkSpan<const Uniform> expectedUniforms)33 void PipelineDataGatherer::setExpectedUniforms(SkSpan<const Uniform> expectedUniforms) {
34 fUniformManager.setExpectedUniforms(expectedUniforms);
35 }
36 #endif // SK_DEBUG
37
addFlags(SkEnumBitMask<SnippetRequirementFlags> flags)38 void PipelineDataGatherer::addFlags(SkEnumBitMask<SnippetRequirementFlags> flags) {
39 fSnippetRequirementFlags |= flags;
40 }
41
needsLocalCoords() const42 bool PipelineDataGatherer::needsLocalCoords() const {
43 return fSnippetRequirementFlags & SnippetRequirementFlags::kLocalCoords;
44 }
45
46 ////////////////////////////////////////////////////////////////////////////////////////////////////
Make(const UniformDataBlock & other,SkArenaAlloc * arena)47 UniformDataBlock* UniformDataBlock::Make(const UniformDataBlock& other, SkArenaAlloc* arena) {
48 static constexpr size_t kUniformAlignment = alignof(void*);
49 char* mem = static_cast<char*>(arena->makeBytesAlignedTo(other.size(), kUniformAlignment));
50 memcpy(mem, other.data(), other.size());
51
52 return arena->make([&](void* ptr) {
53 return new (ptr) UniformDataBlock(SkSpan<const char>(mem, other.size()));
54 });
55 }
56
hash() const57 uint32_t UniformDataBlock::hash() const {
58 return SkOpts::hash_fn(fData.data(), fData.size(), 0);
59 }
60
61 ////////////////////////////////////////////////////////////////////////////////////////////////////
Make(const TextureDataBlock & other,SkArenaAlloc * arena)62 TextureDataBlock* TextureDataBlock::Make(const TextureDataBlock& other,
63 SkArenaAlloc* arena) {
64 return arena->make([&](void *ptr) {
65 return new (ptr) TextureDataBlock(other);
66 });
67 }
68
operator ==(const TextureDataBlock & other) const69 bool TextureDataBlock::operator==(const TextureDataBlock& other) const {
70 if (fTextureData.size() != other.fTextureData.size()) {
71 return false;
72 }
73
74 for (size_t i = 0; i < fTextureData.size(); ++i) {
75 if (fTextureData[i] != other.fTextureData[i]) {
76 return false;
77 }
78 }
79
80 return true;
81 }
82
hash() const83 uint32_t TextureDataBlock::hash() const {
84 uint32_t hash = 0;
85
86 for (auto& d : fTextureData) {
87 uint32_t samplerKey = std::get<1>(d).asKey();
88 hash = SkOpts::hash_fn(&samplerKey, sizeof(samplerKey), hash);
89
90 // Because the lifetime of the TextureDataCache is for just one Recording and the
91 // TextureDataBlocks hold refs on their proxies, we can just use the proxy's pointer
92 // for the hash here.
93 uintptr_t proxy = reinterpret_cast<uintptr_t>(std::get<0>(d).get());
94 hash = SkOpts::hash_fn(&proxy, sizeof(proxy), hash);
95 }
96
97 return hash;
98 }
99
100 #ifdef SK_DEBUG
UniformExpectationsValidator(PipelineDataGatherer * gatherer,SkSpan<const Uniform> expectedUniforms)101 UniformExpectationsValidator::UniformExpectationsValidator(PipelineDataGatherer *gatherer,
102 SkSpan<const Uniform> expectedUniforms)
103 : fGatherer(gatherer) {
104 fGatherer->setExpectedUniforms(expectedUniforms);
105 }
106 #endif
107
108 } // namespace skgpu::graphite
109