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 9 #ifndef GrVkPipelineState_DEFINED 10 #define GrVkPipelineState_DEFINED 11 12 #include "GrProgramDesc.h" 13 #include "GrStencilSettings.h" 14 #include "GrVkDescriptorSetManager.h" 15 #include "GrVkImage.h" 16 #include "GrVkPipelineStateDataManager.h" 17 #include "glsl/GrGLSLProgramBuilder.h" 18 19 #include "vk/GrVkDefines.h" 20 21 class GrPipeline; 22 class GrVkCommandBuffer; 23 class GrVkDescriptorPool; 24 class GrVkDescriptorSet; 25 class GrVkGpu; 26 class GrVkImageView; 27 class GrVkPipeline; 28 class GrVkSampler; 29 class GrVkUniformBuffer; 30 31 /** 32 * This class holds onto a GrVkPipeline object that we use for draws. Besides storing the acutal 33 * GrVkPipeline object, this class is also responsible handling all uniforms, descriptors, samplers, 34 * and other similar objects that are used along with the VkPipeline in the draw. This includes both 35 * allocating and freeing these objects, as well as updating their values. 36 */ 37 class GrVkPipelineState : public SkRefCnt { 38 public: 39 typedef GrGLSLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles; 40 41 ~GrVkPipelineState(); 42 43 GrVkPipeline* vkPipeline() const { return fPipeline; } 44 45 void setData(GrVkGpu*, const GrPrimitiveProcessor&, const GrPipeline&); 46 47 void bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer); 48 49 void addUniformResources(GrVkCommandBuffer&); 50 51 void freeGPUResources(const GrVkGpu* gpu); 52 53 // This releases resources that only a given instance of a GrVkPipelineState needs to hold onto 54 // and don't need to survive across new uses of the GrVkPipelineState. 55 void freeTempResources(const GrVkGpu* gpu); 56 57 void abandonGPUResources(); 58 59 /** 60 * For Vulkan we want to cache the entire VkPipeline for reuse of draws. The Desc here holds all 61 * the information needed to differentiate one pipeline from another. 62 * 63 * The GrProgramDesc contains all the information need to create the actual shaders for the 64 * pipeline. 65 * 66 * For Vulkan we need to add to the GrProgramDesc to include the rest of the state on the 67 * pipline. This includes stencil settings, blending information, render pass format, draw face 68 * information, and primitive type. Note that some state is set dynamically on the pipeline for 69 * each draw and thus is not included in this descriptor. This includes the viewport, scissor, 70 * and blend constant. 71 */ 72 class Desc : public GrProgramDesc { 73 public: 74 static bool Build(Desc*, 75 const GrPrimitiveProcessor&, 76 const GrPipeline&, 77 const GrStencilSettings&, 78 GrPrimitiveType primitiveType, 79 const GrShaderCaps&); 80 private: 81 typedef GrProgramDesc INHERITED; 82 }; 83 84 const Desc& getDesc() { return fDesc; } 85 86 private: 87 typedef GrVkPipelineStateDataManager::UniformInfoArray UniformInfoArray; 88 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; 89 90 GrVkPipelineState(GrVkGpu* gpu, 91 const GrVkPipelineState::Desc&, 92 GrVkPipeline* pipeline, 93 VkPipelineLayout layout, 94 const GrVkDescriptorSetManager::Handle& samplerDSHandle, 95 const BuiltinUniformHandles& builtinUniformHandles, 96 const UniformInfoArray& uniforms, 97 uint32_t vertexUniformSize, 98 uint32_t fragmentUniformSize, 99 uint32_t numSamplers, 100 GrGLSLPrimitiveProcessor* geometryProcessor, 101 GrGLSLXferProcessor* xferProcessor, 102 const GrGLSLFragProcs& fragmentProcessors); 103 104 // Each pool will manage one type of descriptor. Thus each descriptor set we use will all be of 105 // one VkDescriptorType. 106 struct DescriptorPoolManager { 107 DescriptorPoolManager(VkDescriptorSetLayout layout, VkDescriptorType type, 108 uint32_t descCount, GrVkGpu* gpu) 109 : fDescLayout(layout) 110 , fDescType(type) 111 , fDescCountPerSet(descCount) 112 , fCurrentDescriptorCount(0) 113 , fPool(nullptr) { 114 SkASSERT(descCount < kMaxDescLimit >> 2); 115 fMaxDescriptors = fDescCountPerSet << 2; 116 this->getNewPool(gpu); 117 } 118 119 ~DescriptorPoolManager() { 120 SkASSERT(!fDescLayout); 121 SkASSERT(!fPool); 122 } 123 124 void getNewDescriptorSet(GrVkGpu* gpu, VkDescriptorSet* ds); 125 126 void freeGPUResources(const GrVkGpu* gpu); 127 void abandonGPUResources(); 128 129 VkDescriptorSetLayout fDescLayout; 130 VkDescriptorType fDescType; 131 uint32_t fDescCountPerSet; 132 uint32_t fMaxDescriptors; 133 uint32_t fCurrentDescriptorCount; 134 GrVkDescriptorPool* fPool; 135 136 private: 137 static const uint32_t kMaxDescLimit = 1 << 10; 138 139 void getNewPool(GrVkGpu* gpu); 140 }; 141 142 void writeUniformBuffers(const GrVkGpu* gpu); 143 144 void writeSamplers(GrVkGpu* gpu, 145 const SkTArray<const GrProcessor::TextureSampler*>& textureBindings, 146 bool allowSRGBInputs); 147 148 /** 149 * We use the RT's size and origin to adjust from Skia device space to vulkan normalized device 150 * space and to make device space positions have the correct origin for processors that require 151 * them. 152 */ 153 struct RenderTargetState { 154 SkISize fRenderTargetSize; 155 GrSurfaceOrigin fRenderTargetOrigin; 156 157 RenderTargetState() { this->invalidate(); } 158 void invalidate() { 159 fRenderTargetSize.fWidth = -1; 160 fRenderTargetSize.fHeight = -1; 161 fRenderTargetOrigin = (GrSurfaceOrigin)-1; 162 } 163 164 /** 165 * Gets a vec4 that adjusts the position from Skia device coords to Vulkans normalized device 166 * coords. Assuming the transformed position, pos, is a homogeneous vec3, the vec, v, is 167 * applied as such: 168 * pos.x = dot(v.xy, pos.xz) 169 * pos.y = dot(v.zw, pos.yz) 170 */ 171 void getRTAdjustmentVec(float* destVec) { 172 destVec[0] = 2.f / fRenderTargetSize.fWidth; 173 destVec[1] = -1.f; 174 if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) { 175 destVec[2] = -2.f / fRenderTargetSize.fHeight; 176 destVec[3] = 1.f; 177 } else { 178 destVec[2] = 2.f / fRenderTargetSize.fHeight; 179 destVec[3] = -1.f; 180 } 181 } 182 }; 183 184 // Helper for setData() that sets the view matrix and loads the render target height uniform 185 void setRenderTargetState(const GrPipeline&); 186 187 // GrVkResources 188 GrVkPipeline* fPipeline; 189 190 // Used for binding DescriptorSets to the command buffer but does not need to survive during 191 // command buffer execution. Thus this is not need to be a GrVkResource. 192 VkPipelineLayout fPipelineLayout; 193 194 // The DescriptorSets need to survive until the gpu has finished all draws that use them. 195 // However, they will only be freed by the descriptor pool. Thus by simply keeping the 196 // descriptor pool alive through the draw, the descritor sets will also stay alive. Thus we do 197 // not need a GrVkResource versions of VkDescriptorSet. We hold on to these in the 198 // GrVkPipelineState since we update the descriptor sets and bind them at separate times; 199 VkDescriptorSet fDescriptorSets[2]; 200 201 // Once we move samplers over to use the resource provider for descriptor sets we will not need 202 // the above array and instead just use GrVkDescriptorSet like the uniform one here. 203 const GrVkDescriptorSet* fUniformDescriptorSet; 204 const GrVkDescriptorSet* fSamplerDescriptorSet; 205 206 const GrVkDescriptorSetManager::Handle fSamplerDSHandle; 207 208 // Meta data so we know which descriptor sets we are using and need to bind. 209 int fStartDS; 210 int fDSCount; 211 212 std::unique_ptr<GrVkUniformBuffer> fVertexUniformBuffer; 213 std::unique_ptr<GrVkUniformBuffer> fFragmentUniformBuffer; 214 215 // GrVkResources used for sampling textures 216 SkTDArray<GrVkSampler*> fSamplers; 217 SkTDArray<const GrVkImageView*> fTextureViews; 218 SkTDArray<const GrVkResource*> fTextures; 219 220 // Tracks the current render target uniforms stored in the vertex buffer. 221 RenderTargetState fRenderTargetState; 222 BuiltinUniformHandles fBuiltinUniformHandles; 223 224 // Processors in the GrVkPipelineState 225 std::unique_ptr<GrGLSLPrimitiveProcessor> fGeometryProcessor; 226 std::unique_ptr<GrGLSLXferProcessor> fXferProcessor; 227 GrGLSLFragProcs fFragmentProcessors; 228 229 Desc fDesc; 230 231 GrVkPipelineStateDataManager fDataManager; 232 233 int fNumSamplers; 234 235 friend class GrVkPipelineStateBuilder; 236 }; 237 238 #endif 239