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/gpu/vk/GrVkTypes.h" 12 #include "src/gpu/GrSamplerState.h" 13 #include "src/gpu/GrShaderVar.h" 14 #include "src/gpu/GrTBlockList.h" 15 #include "src/gpu/glsl/GrGLSLProgramBuilder.h" 16 #include "src/gpu/glsl/GrGLSLUniformHandler.h" 17 #include "src/gpu/vk/GrVkSampler.h" 18 19 class GrVkUniformHandler : public GrGLSLUniformHandler { 20 public: 21 static const int kUniformsPerBlock = 8; 22 23 enum { 24 /** 25 * Binding a descriptor set invalidates all higher index descriptor sets. We must bind 26 * in the order of this enumeration. Samplers are after Uniforms because GrOps can specify 27 * GP textures as dynamic state, meaning they get rebound for each draw in a pipeline while 28 * uniforms are bound once before all the draws. We bind input attachments after samplers 29 * so those also need to be rebound if we bind new samplers. 30 */ 31 kUniformBufferDescSet = 0, 32 kSamplerDescSet = 1, 33 kInputDescSet = 2, 34 35 kLastDescSet = kInputDescSet, 36 }; 37 static constexpr int kDescSetCount = kLastDescSet + 1; 38 39 // The bindings within their respective sets for various descriptor types. 40 enum { 41 kUniformBinding = 0, 42 kInputBinding = 0, 43 }; 44 enum { 45 kDstInputAttachmentIndex = 0 46 }; 47 48 // The two types of memory layout we're concerned with 49 enum Layout { 50 kStd140Layout = 0, 51 kStd430Layout = 1, 52 53 kLastLayout = kStd430Layout 54 }; 55 static constexpr int kLayoutCount = kLastLayout + 1; 56 57 struct VkUniformInfo : public UniformInfo { 58 // offsets are only valid if the GrSLType of the fVariable is not a sampler. 59 uint32_t fOffsets[kLayoutCount]; 60 // fImmutableSampler is used for sampling an image with a ycbcr conversion. 61 const GrVkSampler* fImmutableSampler = nullptr; 62 }; 63 typedef GrTBlockList<VkUniformInfo> UniformInfoArray; 64 65 ~GrVkUniformHandler() override; 66 getUniformVariable(UniformHandle u)67 const GrShaderVar& getUniformVariable(UniformHandle u) const override { 68 return fUniforms.item(u.toIndex()).fVariable; 69 } 70 getUniformCStr(UniformHandle u)71 const char* getUniformCStr(UniformHandle u) const override { 72 return this->getUniformVariable(u).c_str(); 73 } 74 75 /** 76 * Returns the offset that the RTHeight synthetic uniform should use if it needs to be created. 77 */ 78 uint32_t getRTHeightOffset() const; 79 numUniforms()80 int numUniforms() const override { 81 return fUniforms.count(); 82 } 83 uniform(int idx)84 UniformInfo& uniform(int idx) override { 85 return fUniforms.item(idx); 86 } uniform(int idx)87 const UniformInfo& uniform(int idx) const override { 88 return fUniforms.item(idx); 89 } 90 getFlipY()91 bool getFlipY() const { return fFlipY; } 92 usePushConstants()93 bool usePushConstants() const { return fUsePushConstants; } currentOffset()94 uint32_t currentOffset() const { 95 return fUsePushConstants ? fCurrentOffsets[kStd430Layout] : fCurrentOffsets[kStd140Layout]; 96 } 97 98 private: GrVkUniformHandler(GrGLSLProgramBuilder * program)99 explicit GrVkUniformHandler(GrGLSLProgramBuilder* program) 100 : INHERITED(program) 101 , fUniforms(kUniformsPerBlock) 102 , fSamplers(kUniformsPerBlock) 103 , fFlipY(program->origin() != kTopLeft_GrSurfaceOrigin) 104 , fUsePushConstants(false) 105 , fCurrentOffsets{0, 0} { 106 } 107 108 UniformHandle internalAddUniformArray(const GrFragmentProcessor* owner, 109 uint32_t visibility, 110 GrSLType 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 GrSwizzle&, 119 const char* name, 120 const GrShaderCaps*) override; 121 122 SamplerHandle addInputSampler(const GrSwizzle& 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 GrSwizzle 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 GrSwizzle 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 SkTArray<GrSwizzle> fSamplerSwizzles; 162 UniformInfo fInputUniform; 163 GrSwizzle fInputSwizzle; 164 bool fFlipY; 165 mutable bool fUsePushConstants; 166 167 uint32_t fCurrentOffsets[kLayoutCount]; 168 169 friend class GrVkPipelineStateBuilder; 170 friend class GrVkDescriptorSetManager; 171 172 using INHERITED = GrGLSLUniformHandler; 173 }; 174 175 #endif 176