• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
vkPipeline()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 
getDesc()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 {
DescriptorPoolManagerDescriptorPoolManager107         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 
~DescriptorPoolManagerDescriptorPoolManager119         ~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 
RenderTargetStateRenderTargetState157         RenderTargetState() { this->invalidate(); }
invalidateRenderTargetState158         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         */
getRTAdjustmentVecRenderTargetState171         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