Chromium Code Reviews| 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 |