xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // ProgramVk.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //    Implements the class methods for ProgramVk.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ProgramVk.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ProgramLinkedResources.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/renderer_utils.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/BufferVk.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TextureVk.h"
19*8975f5c5SAndroid Build Coastguard Worker 
20*8975f5c5SAndroid Build Coastguard Worker namespace rx
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker 
23*8975f5c5SAndroid Build Coastguard Worker namespace
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker // Identical to Std140 encoder in all aspects, except it ignores opaque uniform types.
26*8975f5c5SAndroid Build Coastguard Worker class VulkanDefaultBlockEncoder : public sh::Std140BlockEncoder
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker   public:
advanceOffset(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int arrayStride,int matrixStride)29*8975f5c5SAndroid Build Coastguard Worker     void advanceOffset(GLenum type,
30*8975f5c5SAndroid Build Coastguard Worker                        const std::vector<unsigned int> &arraySizes,
31*8975f5c5SAndroid Build Coastguard Worker                        bool isRowMajorMatrix,
32*8975f5c5SAndroid Build Coastguard Worker                        int arrayStride,
33*8975f5c5SAndroid Build Coastguard Worker                        int matrixStride) override
34*8975f5c5SAndroid Build Coastguard Worker     {
35*8975f5c5SAndroid Build Coastguard Worker         if (gl::IsOpaqueType(type))
36*8975f5c5SAndroid Build Coastguard Worker         {
37*8975f5c5SAndroid Build Coastguard Worker             return;
38*8975f5c5SAndroid Build Coastguard Worker         }
39*8975f5c5SAndroid Build Coastguard Worker 
40*8975f5c5SAndroid Build Coastguard Worker         sh::Std140BlockEncoder::advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride,
41*8975f5c5SAndroid Build Coastguard Worker                                               matrixStride);
42*8975f5c5SAndroid Build Coastguard Worker     }
43*8975f5c5SAndroid Build Coastguard Worker };
44*8975f5c5SAndroid Build Coastguard Worker 
45*8975f5c5SAndroid Build Coastguard Worker class Std140BlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
46*8975f5c5SAndroid Build Coastguard Worker {
47*8975f5c5SAndroid Build Coastguard Worker   public:
makeEncoder()48*8975f5c5SAndroid Build Coastguard Worker     sh::BlockLayoutEncoder *makeEncoder() override { return new sh::Std140BlockEncoder(); }
49*8975f5c5SAndroid Build Coastguard Worker };
50*8975f5c5SAndroid Build Coastguard Worker 
51*8975f5c5SAndroid Build Coastguard Worker class LinkTaskVk final : public vk::Context, public LinkTask
52*8975f5c5SAndroid Build Coastguard Worker {
53*8975f5c5SAndroid Build Coastguard Worker   public:
LinkTaskVk(vk::Renderer * renderer,PipelineLayoutCache & pipelineLayoutCache,DescriptorSetLayoutCache & descriptorSetLayoutCache,const gl::ProgramState & state,bool isGLES1,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess)54*8975f5c5SAndroid Build Coastguard Worker     LinkTaskVk(vk::Renderer *renderer,
55*8975f5c5SAndroid Build Coastguard Worker                PipelineLayoutCache &pipelineLayoutCache,
56*8975f5c5SAndroid Build Coastguard Worker                DescriptorSetLayoutCache &descriptorSetLayoutCache,
57*8975f5c5SAndroid Build Coastguard Worker                const gl::ProgramState &state,
58*8975f5c5SAndroid Build Coastguard Worker                bool isGLES1,
59*8975f5c5SAndroid Build Coastguard Worker                vk::PipelineRobustness pipelineRobustness,
60*8975f5c5SAndroid Build Coastguard Worker                vk::PipelineProtectedAccess pipelineProtectedAccess)
61*8975f5c5SAndroid Build Coastguard Worker         : vk::Context(renderer),
62*8975f5c5SAndroid Build Coastguard Worker           mState(state),
63*8975f5c5SAndroid Build Coastguard Worker           mExecutable(&mState.getExecutable()),
64*8975f5c5SAndroid Build Coastguard Worker           mIsGLES1(isGLES1),
65*8975f5c5SAndroid Build Coastguard Worker           mPipelineRobustness(pipelineRobustness),
66*8975f5c5SAndroid Build Coastguard Worker           mPipelineProtectedAccess(pipelineProtectedAccess),
67*8975f5c5SAndroid Build Coastguard Worker           mPipelineLayoutCache(pipelineLayoutCache),
68*8975f5c5SAndroid Build Coastguard Worker           mDescriptorSetLayoutCache(descriptorSetLayoutCache)
69*8975f5c5SAndroid Build Coastguard Worker     {}
70*8975f5c5SAndroid Build Coastguard Worker     ~LinkTaskVk() override = default;
71*8975f5c5SAndroid Build Coastguard Worker 
link(const gl::ProgramLinkedResources & resources,const gl::ProgramMergedVaryings & mergedVaryings,std::vector<std::shared_ptr<LinkSubTask>> * linkSubTasksOut,std::vector<std::shared_ptr<LinkSubTask>> * postLinkSubTasksOut)72*8975f5c5SAndroid Build Coastguard Worker     void link(const gl::ProgramLinkedResources &resources,
73*8975f5c5SAndroid Build Coastguard Worker               const gl::ProgramMergedVaryings &mergedVaryings,
74*8975f5c5SAndroid Build Coastguard Worker               std::vector<std::shared_ptr<LinkSubTask>> *linkSubTasksOut,
75*8975f5c5SAndroid Build Coastguard Worker               std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut) override
76*8975f5c5SAndroid Build Coastguard Worker     {
77*8975f5c5SAndroid Build Coastguard Worker         ASSERT(linkSubTasksOut && linkSubTasksOut->empty());
78*8975f5c5SAndroid Build Coastguard Worker         ASSERT(postLinkSubTasksOut && postLinkSubTasksOut->empty());
79*8975f5c5SAndroid Build Coastguard Worker 
80*8975f5c5SAndroid Build Coastguard Worker         // In the Vulkan backend, the only subtasks are pipeline warm up, which is not required for
81*8975f5c5SAndroid Build Coastguard Worker         // link.  Running as a post-link task, the expensive warm up is run in a thread without
82*8975f5c5SAndroid Build Coastguard Worker         // holding up the link results.
83*8975f5c5SAndroid Build Coastguard Worker         angle::Result result = linkImpl(resources, mergedVaryings, postLinkSubTasksOut);
84*8975f5c5SAndroid Build Coastguard Worker         ASSERT((result == angle::Result::Continue) == (mErrorCode == VK_SUCCESS));
85*8975f5c5SAndroid Build Coastguard Worker     }
86*8975f5c5SAndroid Build Coastguard Worker 
handleError(VkResult result,const char * file,const char * function,unsigned int line)87*8975f5c5SAndroid Build Coastguard Worker     void handleError(VkResult result,
88*8975f5c5SAndroid Build Coastguard Worker                      const char *file,
89*8975f5c5SAndroid Build Coastguard Worker                      const char *function,
90*8975f5c5SAndroid Build Coastguard Worker                      unsigned int line) override
91*8975f5c5SAndroid Build Coastguard Worker     {
92*8975f5c5SAndroid Build Coastguard Worker         mErrorCode     = result;
93*8975f5c5SAndroid Build Coastguard Worker         mErrorFile     = file;
94*8975f5c5SAndroid Build Coastguard Worker         mErrorFunction = function;
95*8975f5c5SAndroid Build Coastguard Worker         mErrorLine     = line;
96*8975f5c5SAndroid Build Coastguard Worker     }
97*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,gl::InfoLog & infoLog)98*8975f5c5SAndroid Build Coastguard Worker     angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
99*8975f5c5SAndroid Build Coastguard Worker     {
100*8975f5c5SAndroid Build Coastguard Worker         ContextVk *contextVk              = vk::GetImpl(context);
101*8975f5c5SAndroid Build Coastguard Worker         ProgramExecutableVk *executableVk = vk::GetImpl(mExecutable);
102*8975f5c5SAndroid Build Coastguard Worker 
103*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(executableVk->initializeDescriptorPools(contextVk,
104*8975f5c5SAndroid Build Coastguard Worker                                                           &contextVk->getDescriptorSetLayoutCache(),
105*8975f5c5SAndroid Build Coastguard Worker                                                           &contextVk->getMetaDescriptorPools()));
106*8975f5c5SAndroid Build Coastguard Worker 
107*8975f5c5SAndroid Build Coastguard Worker         // If the program uses framebuffer fetch and this is the first time this happens, switch the
108*8975f5c5SAndroid Build Coastguard Worker         // context to "framebuffer fetch mode".  In this mode, all render passes assume framebuffer
109*8975f5c5SAndroid Build Coastguard Worker         // fetch may be used, so they are prepared to accept a program that uses input attachments.
110*8975f5c5SAndroid Build Coastguard Worker         // This is done only when a program with framebuffer fetch is created to avoid potential
111*8975f5c5SAndroid Build Coastguard Worker         // performance impact on applications that don't use this extension.  If other contexts in
112*8975f5c5SAndroid Build Coastguard Worker         // the share group use this program, they will lazily switch to this mode.
113*8975f5c5SAndroid Build Coastguard Worker         //
114*8975f5c5SAndroid Build Coastguard Worker         // This is purely an optimization (to avoid creating and later releasing) non-framebuffer
115*8975f5c5SAndroid Build Coastguard Worker         // fetch render passes.  The optimization is unnecessary for and does not apply to dynamic
116*8975f5c5SAndroid Build Coastguard Worker         // rendering.
117*8975f5c5SAndroid Build Coastguard Worker         if (!contextVk->getFeatures().preferDynamicRendering.enabled &&
118*8975f5c5SAndroid Build Coastguard Worker             contextVk->getFeatures().permanentlySwitchToFramebufferFetchMode.enabled &&
119*8975f5c5SAndroid Build Coastguard Worker             mExecutable->usesColorFramebufferFetch())
120*8975f5c5SAndroid Build Coastguard Worker         {
121*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(contextVk->switchToColorFramebufferFetchMode(true));
122*8975f5c5SAndroid Build Coastguard Worker         }
123*8975f5c5SAndroid Build Coastguard Worker 
124*8975f5c5SAndroid Build Coastguard Worker         // Forward any errors
125*8975f5c5SAndroid Build Coastguard Worker         if (mErrorCode != VK_SUCCESS)
126*8975f5c5SAndroid Build Coastguard Worker         {
127*8975f5c5SAndroid Build Coastguard Worker             contextVk->handleError(mErrorCode, mErrorFile, mErrorFunction, mErrorLine);
128*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
129*8975f5c5SAndroid Build Coastguard Worker         }
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker         // Accumulate relevant perf counters
132*8975f5c5SAndroid Build Coastguard Worker         const angle::VulkanPerfCounters &from = getPerfCounters();
133*8975f5c5SAndroid Build Coastguard Worker         angle::VulkanPerfCounters &to         = contextVk->getPerfCounters();
134*8975f5c5SAndroid Build Coastguard Worker 
135*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationCacheHits += from.pipelineCreationCacheHits;
136*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationCacheMisses += from.pipelineCreationCacheMisses;
137*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationTotalCacheHitsDurationNs +=
138*8975f5c5SAndroid Build Coastguard Worker             from.pipelineCreationTotalCacheHitsDurationNs;
139*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationTotalCacheMissesDurationNs +=
140*8975f5c5SAndroid Build Coastguard Worker             from.pipelineCreationTotalCacheMissesDurationNs;
141*8975f5c5SAndroid Build Coastguard Worker 
142*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
143*8975f5c5SAndroid Build Coastguard Worker     }
144*8975f5c5SAndroid Build Coastguard Worker 
145*8975f5c5SAndroid Build Coastguard Worker   private:
146*8975f5c5SAndroid Build Coastguard Worker     angle::Result linkImpl(const gl::ProgramLinkedResources &resources,
147*8975f5c5SAndroid Build Coastguard Worker                            const gl::ProgramMergedVaryings &mergedVaryings,
148*8975f5c5SAndroid Build Coastguard Worker                            std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut);
149*8975f5c5SAndroid Build Coastguard Worker 
150*8975f5c5SAndroid Build Coastguard Worker     void linkResources(const gl::ProgramLinkedResources &resources);
151*8975f5c5SAndroid Build Coastguard Worker     angle::Result initDefaultUniformBlocks();
152*8975f5c5SAndroid Build Coastguard Worker     void generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> *layoutMapOut,
153*8975f5c5SAndroid Build Coastguard Worker                                       gl::ShaderMap<size_t> *requiredBufferSizeOut);
154*8975f5c5SAndroid Build Coastguard Worker     void initDefaultUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> *layoutMapOut);
155*8975f5c5SAndroid Build Coastguard Worker 
156*8975f5c5SAndroid Build Coastguard Worker     // The front-end ensures that the program is not accessed while linking, so it is safe to
157*8975f5c5SAndroid Build Coastguard Worker     // direclty access the state from a potentially parallel job.
158*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramState &mState;
159*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *mExecutable;
160*8975f5c5SAndroid Build Coastguard Worker     const bool mIsGLES1;
161*8975f5c5SAndroid Build Coastguard Worker     const vk::PipelineRobustness mPipelineRobustness;
162*8975f5c5SAndroid Build Coastguard Worker     const vk::PipelineProtectedAccess mPipelineProtectedAccess;
163*8975f5c5SAndroid Build Coastguard Worker 
164*8975f5c5SAndroid Build Coastguard Worker     // Helpers that are interally thread-safe
165*8975f5c5SAndroid Build Coastguard Worker     PipelineLayoutCache &mPipelineLayoutCache;
166*8975f5c5SAndroid Build Coastguard Worker     DescriptorSetLayoutCache &mDescriptorSetLayoutCache;
167*8975f5c5SAndroid Build Coastguard Worker 
168*8975f5c5SAndroid Build Coastguard Worker     // Error handling
169*8975f5c5SAndroid Build Coastguard Worker     VkResult mErrorCode        = VK_SUCCESS;
170*8975f5c5SAndroid Build Coastguard Worker     const char *mErrorFile     = nullptr;
171*8975f5c5SAndroid Build Coastguard Worker     const char *mErrorFunction = nullptr;
172*8975f5c5SAndroid Build Coastguard Worker     unsigned int mErrorLine    = 0;
173*8975f5c5SAndroid Build Coastguard Worker };
174*8975f5c5SAndroid Build Coastguard Worker 
linkImpl(const gl::ProgramLinkedResources & resources,const gl::ProgramMergedVaryings & mergedVaryings,std::vector<std::shared_ptr<LinkSubTask>> * postLinkSubTasksOut)175*8975f5c5SAndroid Build Coastguard Worker angle::Result LinkTaskVk::linkImpl(const gl::ProgramLinkedResources &resources,
176*8975f5c5SAndroid Build Coastguard Worker                                    const gl::ProgramMergedVaryings &mergedVaryings,
177*8975f5c5SAndroid Build Coastguard Worker                                    std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut)
178*8975f5c5SAndroid Build Coastguard Worker {
179*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "LinkTaskVk::linkImpl");
180*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mExecutable);
181*8975f5c5SAndroid Build Coastguard Worker 
182*8975f5c5SAndroid Build Coastguard Worker     // Link resources before calling GetShaderSource to make sure they are ready for the set/binding
183*8975f5c5SAndroid Build Coastguard Worker     // assignment done in that function.
184*8975f5c5SAndroid Build Coastguard Worker     linkResources(resources);
185*8975f5c5SAndroid Build Coastguard Worker 
186*8975f5c5SAndroid Build Coastguard Worker     executableVk->clearVariableInfoMap();
187*8975f5c5SAndroid Build Coastguard Worker 
188*8975f5c5SAndroid Build Coastguard Worker     // Gather variable info and compiled SPIR-V binaries.
189*8975f5c5SAndroid Build Coastguard Worker     executableVk->assignAllSpvLocations(this, mState, resources);
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<const angle::spirv::Blob *> spirvBlobs;
192*8975f5c5SAndroid Build Coastguard Worker     SpvGetShaderSpirvCode(mState, &spirvBlobs);
193*8975f5c5SAndroid Build Coastguard Worker 
194*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled &&
195*8975f5c5SAndroid Build Coastguard Worker         getFeatures().enablePrecisionQualifiers.enabled)
196*8975f5c5SAndroid Build Coastguard Worker     {
197*8975f5c5SAndroid Build Coastguard Worker         executableVk->resolvePrecisionMismatch(mergedVaryings);
198*8975f5c5SAndroid Build Coastguard Worker     }
199*8975f5c5SAndroid Build Coastguard Worker 
200*8975f5c5SAndroid Build Coastguard Worker     // Compile the shaders.
201*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(executableVk->initShaders(this, mExecutable->getLinkedShaderStages(), spirvBlobs,
202*8975f5c5SAndroid Build Coastguard Worker                                         mIsGLES1));
203*8975f5c5SAndroid Build Coastguard Worker 
204*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initDefaultUniformBlocks());
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(executableVk->createPipelineLayout(this, &mPipelineLayoutCache,
207*8975f5c5SAndroid Build Coastguard Worker                                                  &mDescriptorSetLayoutCache, nullptr));
208*8975f5c5SAndroid Build Coastguard Worker 
209*8975f5c5SAndroid Build Coastguard Worker     // Warm up the pipeline cache by creating a few placeholder pipelines.  This is not done for
210*8975f5c5SAndroid Build Coastguard Worker     // separable programs, and is deferred to when the program pipeline is finalized.
211*8975f5c5SAndroid Build Coastguard Worker     //
212*8975f5c5SAndroid Build Coastguard Worker     // The cache warm up is skipped for GLES1 for two reasons:
213*8975f5c5SAndroid Build Coastguard Worker     //
214*8975f5c5SAndroid Build Coastguard Worker     // - Since GLES1 shaders are limited, the individual programs don't necessarily add new
215*8975f5c5SAndroid Build Coastguard Worker     //   pipelines, but rather it's draw time state that controls that.  Since the programs are
216*8975f5c5SAndroid Build Coastguard Worker     //   generated at draw time, it's just as well to let the pipelines be created using the
217*8975f5c5SAndroid Build Coastguard Worker     //   renderer's shared cache.
218*8975f5c5SAndroid Build Coastguard Worker     // - Individual GLES1 tests are long, and this adds a considerable overhead to those tests
219*8975f5c5SAndroid Build Coastguard Worker     if (!mState.isSeparable() && !mIsGLES1 && getFeatures().warmUpPipelineCacheAtLink.enabled)
220*8975f5c5SAndroid Build Coastguard Worker     {
221*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(executableVk->getPipelineCacheWarmUpTasks(
222*8975f5c5SAndroid Build Coastguard Worker             mRenderer, mPipelineRobustness, mPipelineProtectedAccess, postLinkSubTasksOut));
223*8975f5c5SAndroid Build Coastguard Worker     }
224*8975f5c5SAndroid Build Coastguard Worker 
225*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
226*8975f5c5SAndroid Build Coastguard Worker }
227*8975f5c5SAndroid Build Coastguard Worker 
linkResources(const gl::ProgramLinkedResources & resources)228*8975f5c5SAndroid Build Coastguard Worker void LinkTaskVk::linkResources(const gl::ProgramLinkedResources &resources)
229*8975f5c5SAndroid Build Coastguard Worker {
230*8975f5c5SAndroid Build Coastguard Worker     Std140BlockLayoutEncoderFactory std140EncoderFactory;
231*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramLinkedResourcesLinker linker(&std140EncoderFactory);
232*8975f5c5SAndroid Build Coastguard Worker 
233*8975f5c5SAndroid Build Coastguard Worker     linker.linkResources(mState, resources);
234*8975f5c5SAndroid Build Coastguard Worker }
235*8975f5c5SAndroid Build Coastguard Worker 
initDefaultUniformBlocks()236*8975f5c5SAndroid Build Coastguard Worker angle::Result LinkTaskVk::initDefaultUniformBlocks()
237*8975f5c5SAndroid Build Coastguard Worker {
238*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mExecutable);
239*8975f5c5SAndroid Build Coastguard Worker 
240*8975f5c5SAndroid Build Coastguard Worker     // Process vertex and fragment uniforms into std140 packing.
241*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<sh::BlockLayoutMap> layoutMap;
242*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<size_t> requiredBufferSize;
243*8975f5c5SAndroid Build Coastguard Worker     requiredBufferSize.fill(0);
244*8975f5c5SAndroid Build Coastguard Worker 
245*8975f5c5SAndroid Build Coastguard Worker     generateUniformLayoutMapping(&layoutMap, &requiredBufferSize);
246*8975f5c5SAndroid Build Coastguard Worker     initDefaultUniformLayoutMapping(&layoutMap);
247*8975f5c5SAndroid Build Coastguard Worker 
248*8975f5c5SAndroid Build Coastguard Worker     // All uniform initializations are complete, now resize the buffers accordingly and return
249*8975f5c5SAndroid Build Coastguard Worker     return executableVk->resizeUniformBlockMemory(this, requiredBufferSize);
250*8975f5c5SAndroid Build Coastguard Worker }
251*8975f5c5SAndroid Build Coastguard Worker 
InitDefaultUniformBlock(const std::vector<sh::ShaderVariable> & uniforms,sh::BlockLayoutMap * blockLayoutMapOut,size_t * blockSizeOut)252*8975f5c5SAndroid Build Coastguard Worker void InitDefaultUniformBlock(const std::vector<sh::ShaderVariable> &uniforms,
253*8975f5c5SAndroid Build Coastguard Worker                              sh::BlockLayoutMap *blockLayoutMapOut,
254*8975f5c5SAndroid Build Coastguard Worker                              size_t *blockSizeOut)
255*8975f5c5SAndroid Build Coastguard Worker {
256*8975f5c5SAndroid Build Coastguard Worker     if (uniforms.empty())
257*8975f5c5SAndroid Build Coastguard Worker     {
258*8975f5c5SAndroid Build Coastguard Worker         *blockSizeOut = 0;
259*8975f5c5SAndroid Build Coastguard Worker         return;
260*8975f5c5SAndroid Build Coastguard Worker     }
261*8975f5c5SAndroid Build Coastguard Worker 
262*8975f5c5SAndroid Build Coastguard Worker     VulkanDefaultBlockEncoder blockEncoder;
263*8975f5c5SAndroid Build Coastguard Worker     sh::GetActiveUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
264*8975f5c5SAndroid Build Coastguard Worker 
265*8975f5c5SAndroid Build Coastguard Worker     *blockSizeOut = blockEncoder.getCurrentOffset();
266*8975f5c5SAndroid Build Coastguard Worker     return;
267*8975f5c5SAndroid Build Coastguard Worker }
268*8975f5c5SAndroid Build Coastguard Worker 
generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> * layoutMapOut,gl::ShaderMap<size_t> * requiredBufferSizeOut)269*8975f5c5SAndroid Build Coastguard Worker void LinkTaskVk::generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> *layoutMapOut,
270*8975f5c5SAndroid Build Coastguard Worker                                               gl::ShaderMap<size_t> *requiredBufferSizeOut)
271*8975f5c5SAndroid Build Coastguard Worker {
272*8975f5c5SAndroid Build Coastguard Worker     for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
273*8975f5c5SAndroid Build Coastguard Worker     {
274*8975f5c5SAndroid Build Coastguard Worker         const gl::SharedCompiledShaderState &shader = mState.getAttachedShader(shaderType);
275*8975f5c5SAndroid Build Coastguard Worker 
276*8975f5c5SAndroid Build Coastguard Worker         if (shader)
277*8975f5c5SAndroid Build Coastguard Worker         {
278*8975f5c5SAndroid Build Coastguard Worker             const std::vector<sh::ShaderVariable> &uniforms = shader->uniforms;
279*8975f5c5SAndroid Build Coastguard Worker             InitDefaultUniformBlock(uniforms, &(*layoutMapOut)[shaderType],
280*8975f5c5SAndroid Build Coastguard Worker                                     &(*requiredBufferSizeOut)[shaderType]);
281*8975f5c5SAndroid Build Coastguard Worker         }
282*8975f5c5SAndroid Build Coastguard Worker     }
283*8975f5c5SAndroid Build Coastguard Worker }
284*8975f5c5SAndroid Build Coastguard Worker 
initDefaultUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> * layoutMapOut)285*8975f5c5SAndroid Build Coastguard Worker void LinkTaskVk::initDefaultUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> *layoutMapOut)
286*8975f5c5SAndroid Build Coastguard Worker {
287*8975f5c5SAndroid Build Coastguard Worker     // Init the default block layout info.
288*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mExecutable);
289*8975f5c5SAndroid Build Coastguard Worker     const auto &uniforms              = mExecutable->getUniforms();
290*8975f5c5SAndroid Build Coastguard Worker 
291*8975f5c5SAndroid Build Coastguard Worker     for (const gl::VariableLocation &location : mExecutable->getUniformLocations())
292*8975f5c5SAndroid Build Coastguard Worker     {
293*8975f5c5SAndroid Build Coastguard Worker         gl::ShaderMap<sh::BlockMemberInfo> layoutInfo;
294*8975f5c5SAndroid Build Coastguard Worker 
295*8975f5c5SAndroid Build Coastguard Worker         if (location.used() && !location.ignored)
296*8975f5c5SAndroid Build Coastguard Worker         {
297*8975f5c5SAndroid Build Coastguard Worker             const auto &uniform = uniforms[location.index];
298*8975f5c5SAndroid Build Coastguard Worker             if (uniform.isInDefaultBlock() && !uniform.isSampler() && !uniform.isImage() &&
299*8975f5c5SAndroid Build Coastguard Worker                 !uniform.isFragmentInOut())
300*8975f5c5SAndroid Build Coastguard Worker             {
301*8975f5c5SAndroid Build Coastguard Worker                 std::string uniformName = mExecutable->getUniformNameByIndex(location.index);
302*8975f5c5SAndroid Build Coastguard Worker                 if (uniform.isArray())
303*8975f5c5SAndroid Build Coastguard Worker                 {
304*8975f5c5SAndroid Build Coastguard Worker                     // Gets the uniform name without the [0] at the end.
305*8975f5c5SAndroid Build Coastguard Worker                     uniformName = gl::StripLastArrayIndex(uniformName);
306*8975f5c5SAndroid Build Coastguard Worker                     ASSERT(uniformName.size() !=
307*8975f5c5SAndroid Build Coastguard Worker                            mExecutable->getUniformNameByIndex(location.index).size());
308*8975f5c5SAndroid Build Coastguard Worker                 }
309*8975f5c5SAndroid Build Coastguard Worker 
310*8975f5c5SAndroid Build Coastguard Worker                 bool found = false;
311*8975f5c5SAndroid Build Coastguard Worker 
312*8975f5c5SAndroid Build Coastguard Worker                 for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
313*8975f5c5SAndroid Build Coastguard Worker                 {
314*8975f5c5SAndroid Build Coastguard Worker                     auto it = (*layoutMapOut)[shaderType].find(uniformName);
315*8975f5c5SAndroid Build Coastguard Worker                     if (it != (*layoutMapOut)[shaderType].end())
316*8975f5c5SAndroid Build Coastguard Worker                     {
317*8975f5c5SAndroid Build Coastguard Worker                         found                  = true;
318*8975f5c5SAndroid Build Coastguard Worker                         layoutInfo[shaderType] = it->second;
319*8975f5c5SAndroid Build Coastguard Worker                     }
320*8975f5c5SAndroid Build Coastguard Worker                 }
321*8975f5c5SAndroid Build Coastguard Worker 
322*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(found);
323*8975f5c5SAndroid Build Coastguard Worker             }
324*8975f5c5SAndroid Build Coastguard Worker         }
325*8975f5c5SAndroid Build Coastguard Worker 
326*8975f5c5SAndroid Build Coastguard Worker         for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
327*8975f5c5SAndroid Build Coastguard Worker         {
328*8975f5c5SAndroid Build Coastguard Worker             executableVk->getSharedDefaultUniformBlock(shaderType)
329*8975f5c5SAndroid Build Coastguard Worker                 ->uniformLayout.push_back(layoutInfo[shaderType]);
330*8975f5c5SAndroid Build Coastguard Worker         }
331*8975f5c5SAndroid Build Coastguard Worker     }
332*8975f5c5SAndroid Build Coastguard Worker }
333*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
334*8975f5c5SAndroid Build Coastguard Worker 
335*8975f5c5SAndroid Build Coastguard Worker // ProgramVk implementation.
ProgramVk(const gl::ProgramState & state)336*8975f5c5SAndroid Build Coastguard Worker ProgramVk::ProgramVk(const gl::ProgramState &state) : ProgramImpl(state) {}
337*8975f5c5SAndroid Build Coastguard Worker 
338*8975f5c5SAndroid Build Coastguard Worker ProgramVk::~ProgramVk() = default;
339*8975f5c5SAndroid Build Coastguard Worker 
destroy(const gl::Context * context)340*8975f5c5SAndroid Build Coastguard Worker void ProgramVk::destroy(const gl::Context *context)
341*8975f5c5SAndroid Build Coastguard Worker {
342*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
343*8975f5c5SAndroid Build Coastguard Worker     getExecutable()->reset(contextVk);
344*8975f5c5SAndroid Build Coastguard Worker }
345*8975f5c5SAndroid Build Coastguard Worker 
load(const gl::Context * context,gl::BinaryInputStream * stream,std::shared_ptr<LinkTask> * loadTaskOut,egl::CacheGetResult * resultOut)346*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramVk::load(const gl::Context *context,
347*8975f5c5SAndroid Build Coastguard Worker                               gl::BinaryInputStream *stream,
348*8975f5c5SAndroid Build Coastguard Worker                               std::shared_ptr<LinkTask> *loadTaskOut,
349*8975f5c5SAndroid Build Coastguard Worker                               egl::CacheGetResult *resultOut)
350*8975f5c5SAndroid Build Coastguard Worker {
351*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
352*8975f5c5SAndroid Build Coastguard Worker 
353*8975f5c5SAndroid Build Coastguard Worker     // TODO: parallelize program load.  http://anglebug.com/41488637
354*8975f5c5SAndroid Build Coastguard Worker     *loadTaskOut = {};
355*8975f5c5SAndroid Build Coastguard Worker 
356*8975f5c5SAndroid Build Coastguard Worker     return getExecutable()->load(contextVk, mState.isSeparable(), stream, resultOut);
357*8975f5c5SAndroid Build Coastguard Worker }
358*8975f5c5SAndroid Build Coastguard Worker 
save(const gl::Context * context,gl::BinaryOutputStream * stream)359*8975f5c5SAndroid Build Coastguard Worker void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
360*8975f5c5SAndroid Build Coastguard Worker {
361*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
362*8975f5c5SAndroid Build Coastguard Worker     getExecutable()->save(contextVk, mState.isSeparable(), stream);
363*8975f5c5SAndroid Build Coastguard Worker }
364*8975f5c5SAndroid Build Coastguard Worker 
setBinaryRetrievableHint(bool retrievable)365*8975f5c5SAndroid Build Coastguard Worker void ProgramVk::setBinaryRetrievableHint(bool retrievable)
366*8975f5c5SAndroid Build Coastguard Worker {
367*8975f5c5SAndroid Build Coastguard Worker     // Nothing to do here yet.
368*8975f5c5SAndroid Build Coastguard Worker }
369*8975f5c5SAndroid Build Coastguard Worker 
setSeparable(bool separable)370*8975f5c5SAndroid Build Coastguard Worker void ProgramVk::setSeparable(bool separable)
371*8975f5c5SAndroid Build Coastguard Worker {
372*8975f5c5SAndroid Build Coastguard Worker     // Nothing to do here yet.
373*8975f5c5SAndroid Build Coastguard Worker }
374*8975f5c5SAndroid Build Coastguard Worker 
link(const gl::Context * context,std::shared_ptr<LinkTask> * linkTaskOut)375*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramVk::link(const gl::Context *context, std::shared_ptr<LinkTask> *linkTaskOut)
376*8975f5c5SAndroid Build Coastguard Worker {
377*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
378*8975f5c5SAndroid Build Coastguard Worker 
379*8975f5c5SAndroid Build Coastguard Worker     *linkTaskOut = std::shared_ptr<LinkTask>(new LinkTaskVk(
380*8975f5c5SAndroid Build Coastguard Worker         contextVk->getRenderer(), contextVk->getPipelineLayoutCache(),
381*8975f5c5SAndroid Build Coastguard Worker         contextVk->getDescriptorSetLayoutCache(), mState, context->getState().isGLES1(),
382*8975f5c5SAndroid Build Coastguard Worker         contextVk->pipelineRobustness(), contextVk->pipelineProtectedAccess()));
383*8975f5c5SAndroid Build Coastguard Worker 
384*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
385*8975f5c5SAndroid Build Coastguard Worker }
386*8975f5c5SAndroid Build Coastguard Worker 
validate(const gl::Caps & caps)387*8975f5c5SAndroid Build Coastguard Worker GLboolean ProgramVk::validate(const gl::Caps &caps)
388*8975f5c5SAndroid Build Coastguard Worker {
389*8975f5c5SAndroid Build Coastguard Worker     // No-op. The spec is very vague about the behavior of validation.
390*8975f5c5SAndroid Build Coastguard Worker     return GL_TRUE;
391*8975f5c5SAndroid Build Coastguard Worker }
392*8975f5c5SAndroid Build Coastguard Worker 
393*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
394