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