xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkUniformHandler.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2 * Copyright 2016 Google Inc.
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 #ifndef GrVkUniformHandler_DEFINED
9 #define GrVkUniformHandler_DEFINED
10 
11 #include "include/private/base/SkAssert.h"
12 #include "include/private/base/SkTArray.h"
13 #include "include/private/gpu/ganesh/GrTypesPriv.h"
14 #include "src/base/SkTBlockList.h"
15 #include "src/gpu/Swizzle.h"
16 #include "src/gpu/ganesh/GrSamplerState.h"
17 #include "src/gpu/ganesh/GrShaderVar.h"
18 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
19 
20 #include <cstdint>
21 
22 class GrBackendFormat;
23 class GrGLSLProgramBuilder;
24 class GrProcessor;
25 class GrVkSampler;
26 class SkString;
27 enum class SkSLType : char;
28 struct GrShaderCaps;
29 
30 class GrVkUniformHandler : public GrGLSLUniformHandler {
31 public:
32     static const int kUniformsPerBlock = 8;
33 
34     /**
35      * Binding a descriptor set invalidates all higher index descriptor sets. We must bind
36      * in the order of this enumeration. Samplers are after Uniforms because GrOps can specify
37      * GP textures as dynamic state, meaning they get rebound for each draw in a pipeline while
38      * uniforms are bound once before all the draws. We bind input attachments after samplers
39      * so those also need to be rebound if we bind new samplers.
40      */
41     static constexpr int kUniformBufferDescSet = 0;
42     static constexpr int kSamplerDescSet = 1;
43     static constexpr int kInputDescSet = 2;
44 
45     static constexpr int kDescSetCount = kInputDescSet + 1;
46 
47     // The bindings within their respective sets for various descriptor types.
48     static constexpr int kUniformBinding = 0;
49     static constexpr int kInputBinding = 0;
50 
51     // The two types of memory layout we're concerned with
52     enum Layout {
53         kStd140Layout = 0,
54         kStd430Layout = 1,
55 
56         kLastLayout = kStd430Layout
57     };
58     static constexpr int kLayoutCount = kLastLayout + 1;
59 
60     struct VkUniformInfo : public UniformInfo {
61         // offsets are only valid if the SkSLType of the fVariable is not a sampler.
62         uint32_t                fOffsets[kLayoutCount];
63         // fImmutableSampler is used for sampling an image with a ycbcr conversion.
64         const GrVkSampler*      fImmutableSampler = nullptr;
65     };
66     typedef SkTBlockList<VkUniformInfo> UniformInfoArray;
67 
68     ~GrVkUniformHandler() override;
69 
getUniformVariable(UniformHandle u)70     const GrShaderVar& getUniformVariable(UniformHandle u) const override {
71         return fUniforms.item(u.toIndex()).fVariable;
72     }
73 
getUniformCStr(UniformHandle u)74     const char* getUniformCStr(UniformHandle u) const override {
75         return this->getUniformVariable(u).c_str();
76     }
77 
78     /**
79      * Returns the offset that the RTFlip synthetic uniform should use if it needs to be created.
80      */
81     uint32_t getRTFlipOffset() const;
82 
numUniforms()83     int numUniforms() const override {
84         return fUniforms.count();
85     }
86 
uniform(int idx)87     UniformInfo& uniform(int idx) override {
88         return fUniforms.item(idx);
89     }
uniform(int idx)90     const UniformInfo& uniform(int idx) const override {
91         return fUniforms.item(idx);
92     }
93 
usePushConstants()94     bool usePushConstants() const { return fUsePushConstants; }
currentOffset()95     uint32_t currentOffset() const {
96         return fUsePushConstants ? fCurrentOffsets[kStd430Layout] : fCurrentOffsets[kStd140Layout];
97     }
98 
99 private:
GrVkUniformHandler(GrGLSLProgramBuilder * program)100     explicit GrVkUniformHandler(GrGLSLProgramBuilder* program)
101         : INHERITED(program)
102         , fUniforms(kUniformsPerBlock)
103         , fSamplers(kUniformsPerBlock)
104         , fUsePushConstants(false)
105         , fCurrentOffsets{0, 0} {
106     }
107 
108     UniformHandle internalAddUniformArray(const GrProcessor* owner,
109                                           uint32_t visibility,
110                                           SkSLType type,
111                                           const char* name,
112                                           bool mangleName,
113                                           int arrayCount,
114                                           const char** outName) override;
115 
116     SamplerHandle addSampler(const GrBackendFormat&,
117                              GrSamplerState,
118                              const skgpu::Swizzle&,
119                              const char* name,
120                              const GrShaderCaps*) override;
121 
122     SamplerHandle addInputSampler(const skgpu::Swizzle& swizzle, const char* name) override;
123 
numSamplers()124     int numSamplers() const { return fSamplers.count(); }
samplerVariable(SamplerHandle handle)125     const char* samplerVariable(SamplerHandle handle) const override {
126         return fSamplers.item(handle.toIndex()).fVariable.c_str();
127     }
samplerSwizzle(SamplerHandle handle)128     skgpu::Swizzle samplerSwizzle(SamplerHandle handle) const override {
129         return fSamplerSwizzles[handle.toIndex()];
130     }
samplerVisibility(SamplerHandle handle)131     uint32_t samplerVisibility(SamplerHandle handle) const {
132         return fSamplers.item(handle.toIndex()).fVisibility;
133     }
134 
immutableSampler(UniformHandle u)135     const GrVkSampler* immutableSampler(UniformHandle u) const {
136         return fSamplers.item(u.toIndex()).fImmutableSampler;
137     }
138 
inputSamplerVariable(SamplerHandle handle)139     const char* inputSamplerVariable(SamplerHandle handle) const override {
140         // Currently we will only ever have one input sampler variable, though in the future we may
141         // expand to allow more inputs. For now assert that any requested handle maps to index 0,
142         // to make sure we didn't add multiple input samplers.
143         SkASSERT(handle.toIndex() == 0);
144         return fInputUniform.fVariable.c_str();
145     }
inputSamplerSwizzle(SamplerHandle handle)146     skgpu::Swizzle inputSamplerSwizzle(SamplerHandle handle) const override {
147         SkASSERT(handle.toIndex() == 0);
148         return fInputSwizzle;
149     }
150 
151     void appendUniformDecls(GrShaderFlags, SkString*) const override;
152 
getUniformInfo(UniformHandle u)153     const VkUniformInfo& getUniformInfo(UniformHandle u) const {
154         return fUniforms.item(u.toIndex());
155     }
156 
157     void determineIfUsePushConstants() const;
158 
159     UniformInfoArray         fUniforms;
160     UniformInfoArray         fSamplers;
161     skia_private::TArray<skgpu::Swizzle> fSamplerSwizzles;
162     UniformInfo              fInputUniform;
163     skgpu::Swizzle           fInputSwizzle;
164     mutable bool             fUsePushConstants;
165 
166     uint32_t            fCurrentOffsets[kLayoutCount];
167 
168     friend class GrVkPipelineStateBuilder;
169     friend class GrVkDescriptorSetManager;
170 
171     using INHERITED = GrGLSLUniformHandler;
172 };
173 
174 #endif
175