Home | History | Annotate | Download | only in vk
      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