OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 Google Inc. | |
bsalomon
2016/03/23 15:04:36
2016
egdaniel
2016/03/23 19:12:07
Done.
| |
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 "GrVkImage.h" | |
13 #include "GrVkProgramDesc.h" | |
14 #include "GrVkPipelineStateDataManager.h" | |
15 #include "glsl/GrGLSLProgramBuilder.h" | |
16 | |
17 #include "vulkan/vulkan.h" | |
18 | |
19 class GrPipeline; | |
20 class GrVkCommandBuffer; | |
21 class GrVkDescriptorPool; | |
22 class GrVkGpu; | |
23 class GrVkImageView; | |
24 class GrVkPipeline; | |
25 class GrVkSampler; | |
26 class GrVkUniformBuffer; | |
27 | |
28 class GrVkPipelineState : public SkRefCnt { | |
bsalomon
2016/03/23 15:04:37
brief comment on what this is?
egdaniel
2016/03/23 19:12:07
Done.
| |
29 public: | |
30 typedef GrGLSLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles; | |
31 | |
32 ~GrVkPipelineState(); | |
33 | |
34 GrVkPipeline* vkPipeline() const { return fPipeline; } | |
35 | |
36 void setData(GrVkGpu*, const GrPrimitiveProcessor&, const GrPipeline&); | |
37 | |
38 void bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer); | |
39 | |
40 void addUniformResources(GrVkCommandBuffer&); | |
41 | |
42 void freeGPUResources(const GrVkGpu* gpu); | |
43 | |
44 // This releases resources that only a given instance of a GrVkPipelineState needs to hold onto | |
45 // and don't need to survive across new uses of the GrVkPipelineState. | |
46 void freeTempResources(const GrVkGpu* gpu); | |
47 | |
48 void abandonGPUResources(); | |
49 | |
50 // The key is composed of two parts: | |
51 // 1. uint32_t for total key length | |
52 // 2. Pipeline state data | |
53 enum StateKeyOffsets { | |
54 // Part 1. | |
55 kLength_StateKeyOffset = 0, | |
56 // Part 2. | |
57 kData_StateKeyOffset = kLength_StateKeyOffset + sizeof(uint32_t), | |
58 }; | |
59 static void BuildStateKey(const GrPipeline&, GrPrimitiveType primitiveType, | |
60 SkTArray<unsigned char, true>* key); | |
61 | |
62 /** | |
63 * For Vulkan we want to cache the entire VkPipeline for reuse of draws. The Desc here holds all | |
64 * the information needed to differentiate one pipeline from another. | |
65 * | |
66 * The GrVkProgramDesc contains all the information need to create the actua l shaders for the | |
67 * pipeline. | |
68 * | |
69 * The fStateKey is used to store all the inputs for the rest of the state s tored on the | |
70 * pipeline. This includes stencil settings, blending information, render pa ss format, draw face | |
71 * information, and primitive type. Note that some state is set dynamically on the pipeline for | |
72 * each draw and thus is not included in this descriptor. This includes the viewport, scissor, | |
73 * and blend constant. | |
74 * | |
75 * A checksum which includes the fProgramDesc and fStateKey is included at t he top of the Desc | |
76 * for caching purposes and faster equality checks. | |
77 */ | |
78 struct Desc { | |
79 uint32_t fChecksum; | |
80 GrVkProgramDesc fProgramDesc; | |
81 | |
82 enum { | |
83 kRenderPassKeyAlloc = 12, // This is typical color attachment with n o stencil or msaa | |
84 kStencilKeyAlloc = sizeof(GrStencilSettings), | |
85 kDrawFaceKeyAlloc = 4, | |
86 kBlendingKeyAlloc = 4, | |
87 kPrimitiveTypeKeyAlloc = 4, | |
88 kPreAllocSize = kData_StateKeyOffset + kRenderPassKeyAlloc + kStenci lKeyAlloc + | |
89 kDrawFaceKeyAlloc + kBlendingKeyAlloc + kPrimitiveTy peKeyAlloc, | |
90 }; | |
91 SkSTArray<kPreAllocSize, uint8_t, true> fStateKey; | |
92 | |
93 bool operator== (const Desc& that) const { | |
94 if (fChecksum != that.fChecksum || fProgramDesc != that.fProgramDesc ) { | |
95 return false; | |
96 } | |
97 // We store the keyLength at the start of fVkKey. Thus we don't have to worry about | |
98 // different length keys since we will fail on the comparison immedi ately. Therefore we | |
99 // just use this PipelineDesc to get the length to iterate over. | |
100 int keyLength = fStateKey.count(); | |
101 SkASSERT(SkIsAlign4(keyLength)); | |
102 int l = keyLength >> 2; | |
103 const uint32_t* aKey = reinterpret_cast<const uint32_t*>(fStateKey.b egin()); | |
104 const uint32_t* bKey = reinterpret_cast<const uint32_t*>(that.fState Key.begin()); | |
105 for (int i = 0; i < l; ++i) { | |
106 if (aKey[i] != bKey[i]) { | |
107 return false; | |
108 } | |
109 } | |
110 return true; | |
111 } | |
112 | |
113 static bool Less(const Desc& a, const Desc& b) { | |
114 if (a.fChecksum != b.fChecksum) { | |
115 return a.fChecksum < b.fChecksum ? true : false; | |
116 } | |
117 bool progDescLess = GrProgramDesc::Less(a.fProgramDesc, b.fProgramDe sc); | |
118 if (progDescLess || a.fProgramDesc != b.fProgramDesc) { | |
119 return progDescLess; | |
120 } | |
121 | |
122 int keyLength = a.fStateKey.count(); | |
123 SkASSERT(SkIsAlign4(keyLength)); | |
124 int l = keyLength >> 2; | |
125 const uint32_t* aKey = reinterpret_cast<const uint32_t*>(a.fStateKey .begin()); | |
126 const uint32_t* bKey = reinterpret_cast<const uint32_t*>(b.fStateKey .begin()); | |
127 for (int i = 0; i < l; ++i) { | |
128 if (aKey[i] != bKey[i]) { | |
129 return aKey[i] < bKey[i] ? true : false; | |
130 } | |
131 } | |
132 return false; | |
133 } | |
134 }; | |
135 | |
136 const Desc& getDesc() { return fDesc; } | |
137 | |
138 private: | |
139 typedef GrVkPipelineStateDataManager::UniformInfoArray UniformInfoArray; | |
140 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; | |
141 | |
142 GrVkPipelineState(GrVkGpu* gpu, | |
143 const GrVkPipelineState::Desc&, | |
144 GrVkPipeline* pipeline, | |
145 VkPipelineLayout layout, | |
146 VkDescriptorSetLayout dsLayout[2], | |
147 const BuiltinUniformHandles& builtinUniformHandles, | |
148 const UniformInfoArray& uniforms, | |
149 uint32_t vertexUniformSize, | |
150 uint32_t fragmentUniformSize, | |
151 uint32_t numSamplers, | |
152 GrGLSLPrimitiveProcessor* geometryProcessor, | |
153 GrGLSLXferProcessor* xferProcessor, | |
154 const GrGLSLFragProcs& fragmentProcessors); | |
155 | |
156 // Each pool will manage one type of descriptor. Thus each descriptor set we use will all be of | |
157 // one VkDescriptorType. | |
158 struct DescriptorPoolManager { | |
159 DescriptorPoolManager(VkDescriptorSetLayout layout, VkDescriptorType typ e, | |
160 uint32_t descCount, GrVkGpu* gpu) | |
161 : fDescLayout(layout) | |
162 , fDescType(type) | |
163 , fCurrentDescriptorSet(0) | |
164 , fPool(nullptr) { | |
165 SkASSERT(descCount < (SK_MaxU32 >> 2)); | |
166 fMaxDescriptorSets = descCount << 2; | |
167 this->getNewPool(gpu); | |
168 } | |
169 | |
170 ~DescriptorPoolManager() { | |
171 SkASSERT(!fDescLayout); | |
172 SkASSERT(!fPool); | |
173 } | |
174 | |
175 void getNewDescriptorSet(GrVkGpu* gpu, VkDescriptorSet* ds); | |
176 | |
177 void freeGPUResources(const GrVkGpu* gpu); | |
178 void abandonGPUResources(); | |
179 | |
180 VkDescriptorSetLayout fDescLayout; | |
181 VkDescriptorType fDescType; | |
182 uint32_t fMaxDescriptorSets; | |
183 uint32_t fCurrentDescriptorSet; | |
184 GrVkDescriptorPool* fPool; | |
185 | |
186 private: | |
187 void getNewPool(GrVkGpu* gpu); | |
188 }; | |
189 | |
190 void writeUniformBuffers(const GrVkGpu* gpu); | |
191 | |
192 void writeSamplers(GrVkGpu* gpu, const SkTArray<const GrTextureAccess*>& tex tureBindings); | |
193 | |
194 | |
bsalomon
2016/03/23 15:04:37
rm \n?
egdaniel
2016/03/23 19:12:07
Done.
| |
195 /** | |
196 * We use the RT's size and origin to adjust from Skia device space to OpenGL normalized device | |
bsalomon
2016/03/23 15:04:37
OpenGL?
egdaniel
2016/03/23 19:12:07
Done.
| |
197 * space and to make device space positions have the correct origin for proce ssors that require | |
198 * them. | |
199 */ | |
200 struct RenderTargetState { | |
201 SkISize fRenderTargetSize; | |
202 GrSurfaceOrigin fRenderTargetOrigin; | |
203 | |
204 RenderTargetState() { this->invalidate(); } | |
205 void invalidate() { | |
206 fRenderTargetSize.fWidth = -1; | |
207 fRenderTargetSize.fHeight = -1; | |
208 fRenderTargetOrigin = (GrSurfaceOrigin)-1; | |
209 } | |
210 | |
211 /** | |
212 * Gets a vec4 that adjusts the position from Skia device coords to GL's normalized device | |
bsalomon
2016/03/23 15:04:36
GL
egdaniel
2016/03/23 19:12:06
Done.
| |
213 * coords. Assuming the transformed position, pos, is a homogeneous vec3, the vec, v, is | |
214 * applied as such: | |
215 * pos.x = dot(v.xy, pos.xz) | |
216 * pos.y = dot(v.zw, pos.yz) | |
217 */ | |
218 void getRTAdjustmentVec(float* destVec) { | |
219 destVec[0] = 2.f / fRenderTargetSize.fWidth; | |
220 destVec[1] = -1.f; | |
221 if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) { | |
222 destVec[2] = -2.f / fRenderTargetSize.fHeight; | |
223 destVec[3] = 1.f; | |
224 } else { | |
225 destVec[2] = 2.f / fRenderTargetSize.fHeight; | |
226 destVec[3] = -1.f; | |
227 } | |
228 } | |
229 }; | |
230 | |
231 // Helper for setData() that sets the view matrix and loads the render targe t height uniform | |
232 void setRenderTargetState(const GrPipeline&); | |
233 | |
234 // GrVkResources | |
235 GrVkPipeline* fPipeline; | |
236 | |
237 // Used for binding DescriptorSets to the command buffer but does not need t o survive during | |
238 // command buffer execution. Thus this is not need to be a GrVkResource. | |
239 VkPipelineLayout fPipelineLayout; | |
240 | |
241 // The DescriptorSets need to survive until the gpu has finished all draws t hat use them. | |
242 // However, they will only be freed by the descriptor pool. Thus by simply k eeping the | |
243 // descriptor pool alive through the draw, the descritor sets will also stay alive. Thus we do | |
244 // not need a GrVkResource versions of VkDescriptorSet. We hold on to these in the | |
245 // GrVkPipelineState since we update the descriptor sets and bind them at se parate times; | |
246 VkDescriptorSet fDescriptorSets[2]; | |
247 | |
248 // Meta data so we know which descriptor sets we are using and need to bind. | |
249 int fStartDS; | |
250 int fDSCount; | |
251 | |
252 SkAutoTDelete<GrVkUniformBuffer> fVertexUniformBuffer; | |
253 SkAutoTDelete<GrVkUniformBuffer> fFragmentUniformBuffer; | |
254 | |
255 // GrVkResources used for sampling textures | |
256 SkTDArray<GrVkSampler*> fSamplers; | |
257 SkTDArray<const GrVkImageView*> fTextureViews; | |
258 SkTDArray<const GrVkImage::Resource*> fTextures; | |
259 | |
260 // Tracks the current render target uniforms stored in the vertex buffer. | |
261 RenderTargetState fRenderTargetState; | |
262 BuiltinUniformHandles fBuiltinUniformHandles; | |
263 | |
264 // Processors in the GrVkPipelineState | |
265 SkAutoTDelete<GrGLSLPrimitiveProcessor> fGeometryProcessor; | |
266 SkAutoTDelete<GrGLSLXferProcessor> fXferProcessor; | |
267 GrGLSLFragProcs fFragmentProcessors; | |
268 | |
269 Desc fDesc; | |
270 | |
271 GrVkPipelineStateDataManager fDataManager; | |
272 | |
273 DescriptorPoolManager fSamplerPoolManager; | |
274 DescriptorPoolManager fUniformPoolManager; | |
275 | |
bsalomon
2016/03/23 15:04:37
Inconsistent alignment in these members... I'd say
| |
276 int fNumSamplers; | |
277 | |
278 friend class GrVkPipelineStateBuilder; | |
279 }; | |
280 | |
281 #endif | |
OLD | NEW |