• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ProgramVk.cpp:
7 //    Implements the class methods for ProgramVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/ProgramVk.h"
11 
12 #include "common/debug.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/ProgramLinkedResources.h"
16 #include "libANGLE/renderer/glslang_wrapper_utils.h"
17 #include "libANGLE/renderer/renderer_utils.h"
18 #include "libANGLE/renderer/vulkan/BufferVk.h"
19 #include "libANGLE/renderer/vulkan/GlslangWrapperVk.h"
20 #include "libANGLE/renderer/vulkan/TextureVk.h"
21 
22 namespace rx
23 {
24 
25 namespace
26 {
27 // Identical to Std140 encoder in all aspects, except it ignores opaque uniform types.
28 class VulkanDefaultBlockEncoder : public sh::Std140BlockEncoder
29 {
30   public:
advanceOffset(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int arrayStride,int matrixStride)31     void advanceOffset(GLenum type,
32                        const std::vector<unsigned int> &arraySizes,
33                        bool isRowMajorMatrix,
34                        int arrayStride,
35                        int matrixStride) override
36     {
37         if (gl::IsOpaqueType(type))
38         {
39             return;
40         }
41 
42         sh::Std140BlockEncoder::advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride,
43                                               matrixStride);
44     }
45 };
46 
InitDefaultUniformBlock(const std::vector<sh::ShaderVariable> & uniforms,sh::BlockLayoutMap * blockLayoutMapOut,size_t * blockSizeOut)47 void InitDefaultUniformBlock(const std::vector<sh::ShaderVariable> &uniforms,
48                              sh::BlockLayoutMap *blockLayoutMapOut,
49                              size_t *blockSizeOut)
50 {
51     if (uniforms.empty())
52     {
53         *blockSizeOut = 0;
54         return;
55     }
56 
57     VulkanDefaultBlockEncoder blockEncoder;
58     sh::GetActiveUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
59 
60     size_t blockSize = blockEncoder.getCurrentOffset();
61 
62     // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
63     if (blockSize == 0)
64     {
65         *blockSizeOut = 0;
66         return;
67     }
68 
69     *blockSizeOut = blockSize;
70     return;
71 }
72 
73 template <typename T>
UpdateDefaultUniformBlock(GLsizei count,uint32_t arrayIndex,int componentCount,const T * v,const sh::BlockMemberInfo & layoutInfo,angle::MemoryBuffer * uniformData)74 void UpdateDefaultUniformBlock(GLsizei count,
75                                uint32_t arrayIndex,
76                                int componentCount,
77                                const T *v,
78                                const sh::BlockMemberInfo &layoutInfo,
79                                angle::MemoryBuffer *uniformData)
80 {
81     const int elementSize = sizeof(T) * componentCount;
82 
83     uint8_t *dst = uniformData->data() + layoutInfo.offset;
84     if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
85     {
86         uint32_t arrayOffset = arrayIndex * layoutInfo.arrayStride;
87         uint8_t *writePtr    = dst + arrayOffset;
88         ASSERT(writePtr + (elementSize * count) <= uniformData->data() + uniformData->size());
89         memcpy(writePtr, v, elementSize * count);
90     }
91     else
92     {
93         // Have to respect the arrayStride between each element of the array.
94         int maxIndex = arrayIndex + count;
95         for (int writeIndex = arrayIndex, readIndex = 0; writeIndex < maxIndex;
96              writeIndex++, readIndex++)
97         {
98             const int arrayOffset = writeIndex * layoutInfo.arrayStride;
99             uint8_t *writePtr     = dst + arrayOffset;
100             const T *readPtr      = v + (readIndex * componentCount);
101             ASSERT(writePtr + elementSize <= uniformData->data() + uniformData->size());
102             memcpy(writePtr, readPtr, elementSize);
103         }
104     }
105 }
106 
107 template <typename T>
ReadFromDefaultUniformBlock(int componentCount,uint32_t arrayIndex,T * dst,const sh::BlockMemberInfo & layoutInfo,const angle::MemoryBuffer * uniformData)108 void ReadFromDefaultUniformBlock(int componentCount,
109                                  uint32_t arrayIndex,
110                                  T *dst,
111                                  const sh::BlockMemberInfo &layoutInfo,
112                                  const angle::MemoryBuffer *uniformData)
113 {
114     ASSERT(layoutInfo.offset != -1);
115 
116     const int elementSize = sizeof(T) * componentCount;
117     const uint8_t *source = uniformData->data() + layoutInfo.offset;
118 
119     if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
120     {
121         const uint8_t *readPtr = source + arrayIndex * layoutInfo.arrayStride;
122         memcpy(dst, readPtr, elementSize);
123     }
124     else
125     {
126         // Have to respect the arrayStride between each element of the array.
127         const int arrayOffset  = arrayIndex * layoutInfo.arrayStride;
128         const uint8_t *readPtr = source + arrayOffset;
129         memcpy(dst, readPtr, elementSize);
130     }
131 }
132 
133 class Std140BlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
134 {
135   public:
makeEncoder()136     sh::BlockLayoutEncoder *makeEncoder() override { return new sh::Std140BlockEncoder(); }
137 };
138 
SetupDefaultPipelineState(const ContextVk * contextVk,size_t outputVariablesCount,gl::PrimitiveMode mode,vk::GraphicsPipelineDesc * graphicsPipelineDescOut)139 void SetupDefaultPipelineState(const ContextVk *contextVk,
140                                size_t outputVariablesCount,
141                                gl::PrimitiveMode mode,
142                                vk::GraphicsPipelineDesc *graphicsPipelineDescOut)
143 {
144     graphicsPipelineDescOut->initDefaults(contextVk);
145     graphicsPipelineDescOut->setTopology(mode);
146     graphicsPipelineDescOut->setRenderPassSampleCount(1);
147 
148     constexpr angle::FormatID kDefaultColorAttachmentFormat = angle::FormatID::R8G8B8A8_UNORM;
149     for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < outputVariablesCount;
150          colorAttachmentIndex++)
151     {
152         graphicsPipelineDescOut->setRenderPassColorAttachmentFormat(colorAttachmentIndex,
153                                                                     kDefaultColorAttachmentFormat);
154     }
155 }
156 }  // anonymous namespace
157 
158 // ProgramVk implementation.
ProgramVk(const gl::ProgramState & state)159 ProgramVk::ProgramVk(const gl::ProgramState &state) : ProgramImpl(state)
160 {
161     GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
162 }
163 
164 ProgramVk::~ProgramVk() = default;
165 
destroy(const gl::Context * context)166 void ProgramVk::destroy(const gl::Context *context)
167 {
168     ContextVk *contextVk = vk::GetImpl(context);
169     reset(contextVk);
170 }
171 
reset(ContextVk * contextVk)172 void ProgramVk::reset(ContextVk *contextVk)
173 {
174     GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
175 
176     mExecutable.reset(contextVk);
177 }
178 
load(const gl::Context * context,gl::BinaryInputStream * stream,gl::InfoLog & infoLog)179 std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
180                                                gl::BinaryInputStream *stream,
181                                                gl::InfoLog &infoLog)
182 {
183     ContextVk *contextVk = vk::GetImpl(context);
184 
185     reset(contextVk);
186 
187     return mExecutable.load(contextVk, mState.getExecutable(), stream);
188 }
189 
save(const gl::Context * context,gl::BinaryOutputStream * stream)190 void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
191 {
192     mExecutable.save(stream);
193 }
194 
setBinaryRetrievableHint(bool retrievable)195 void ProgramVk::setBinaryRetrievableHint(bool retrievable)
196 {
197     // Nothing to do here yet.
198 }
199 
setSeparable(bool separable)200 void ProgramVk::setSeparable(bool separable)
201 {
202     // Nothing to do here yet.
203 }
204 
link(const gl::Context * context,const gl::ProgramLinkedResources & resources,gl::InfoLog & infoLog,const gl::ProgramMergedVaryings & mergedVaryings)205 std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
206                                            const gl::ProgramLinkedResources &resources,
207                                            gl::InfoLog &infoLog,
208                                            const gl::ProgramMergedVaryings &mergedVaryings)
209 {
210     ANGLE_TRACE_EVENT0("gpu.angle", "ProgramVk::link");
211 
212     ContextVk *contextVk = vk::GetImpl(context);
213     // Link resources before calling GetShaderSource to make sure they are ready for the set/binding
214     // assignment done in that function.
215     linkResources(resources);
216 
217     reset(contextVk);
218     mExecutable.clearVariableInfoMap();
219 
220     // Gather variable info and compiled SPIR-V binaries.
221     gl::ShaderMap<const angle::spirv::Blob *> spirvBlobs;
222     GlslangWrapperVk::GetShaderCode(contextVk->getFeatures(), mState, resources,
223                                     &mGlslangProgramInterfaceInfo, &spirvBlobs,
224                                     &mExecutable.mVariableInfoMap);
225 
226     if (contextVk->getFeatures().enablePrecisionQualifiers.enabled)
227     {
228         mExecutable.resolvePrecisionMismatch(mergedVaryings);
229     }
230 
231     // Compile the shaders.
232     const gl::ProgramExecutable &programExecutable = mState.getExecutable();
233     angle::Result status                           = mExecutable.mOriginalShaderInfo.initShaders(
234         programExecutable.getLinkedShaderStages(), spirvBlobs, mExecutable.mVariableInfoMap);
235     if (status != angle::Result::Continue)
236     {
237         return std::make_unique<LinkEventDone>(status);
238     }
239 
240     status = initDefaultUniformBlocks(context);
241     if (status != angle::Result::Continue)
242     {
243         return std::make_unique<LinkEventDone>(status);
244     }
245 
246     // TODO(jie.a.chen@intel.com): Parallelize linking.
247     // http://crbug.com/849576
248     status = mExecutable.createPipelineLayout(contextVk, programExecutable, nullptr);
249 
250     // Create pipeline with default state
251     if ((status == angle::Result::Continue) &&
252         contextVk->getFeatures().createPipelineDuringLink.enabled)
253     {
254         status = createGraphicsPipelineWithDefaultState(context);
255     }
256 
257     return std::make_unique<LinkEventDone>(status);
258 }
259 
createGraphicsPipelineWithDefaultState(const gl::Context * context)260 angle::Result ProgramVk::createGraphicsPipelineWithDefaultState(const gl::Context *context)
261 {
262     const gl::ProgramExecutable &glExecutable = mState.getExecutable();
263 
264     // NOOP if -
265     // 1. Program is separable
266     // 2. Program has a compute shader
267     // 3. Program has greater than 3 output variables
268     bool isProgramSeperable = mState.isSeparable();
269     bool hasComputeShader   = glExecutable.hasLinkedShaderStage(gl::ShaderType::Compute);
270     if (isProgramSeperable || hasComputeShader || glExecutable.getOutputVariables().size() > 3)
271     {
272         return angle::Result::Continue;
273     }
274 
275     ContextVk *contextVk                    = vk::GetImpl(context);
276     const vk::GraphicsPipelineDesc *descPtr = nullptr;
277     vk::PipelineHelper *pipeline            = nullptr;
278     vk::GraphicsPipelineDesc graphicsPipelineDesc;
279 
280     // It is only at drawcall time that we will have complete information required to build the
281     // graphics pipeline descriptor. Use the most "commonly seen" state values and create the
282     // pipeline. This attempts to improve shader binary cache hits in the underlying ICD since it is
283     // common for the same shader to be used across different pipelines.
284     gl::PrimitiveMode mode = (glExecutable.hasLinkedShaderStage(gl::ShaderType::TessControl) ||
285                               glExecutable.hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
286                                  ? gl::PrimitiveMode::Patches
287                                  : gl::PrimitiveMode::TriangleStrip;
288     SetupDefaultPipelineState(contextVk, glExecutable.getOutputVariables().size(), mode,
289                               &graphicsPipelineDesc);
290     return mExecutable.getGraphicsPipeline(contextVk, mode, graphicsPipelineDesc, glExecutable,
291                                            &descPtr, &pipeline);
292 }
293 
linkResources(const gl::ProgramLinkedResources & resources)294 void ProgramVk::linkResources(const gl::ProgramLinkedResources &resources)
295 {
296     Std140BlockLayoutEncoderFactory std140EncoderFactory;
297     gl::ProgramLinkedResourcesLinker linker(&std140EncoderFactory);
298 
299     linker.linkResources(mState, resources);
300 }
301 
initDefaultUniformBlocks(const gl::Context * glContext)302 angle::Result ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
303 {
304     ContextVk *contextVk = vk::GetImpl(glContext);
305 
306     // Process vertex and fragment uniforms into std140 packing.
307     gl::ShaderMap<sh::BlockLayoutMap> layoutMap;
308     gl::ShaderMap<size_t> requiredBufferSize;
309     requiredBufferSize.fill(0);
310 
311     generateUniformLayoutMapping(layoutMap, requiredBufferSize);
312     initDefaultUniformLayoutMapping(layoutMap);
313 
314     // All uniform initializations are complete, now resize the buffers accordingly and return
315     return mExecutable.resizeUniformBlockMemory(contextVk, mState.getExecutable(),
316                                                 requiredBufferSize);
317 }
318 
generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> & layoutMap,gl::ShaderMap<size_t> & requiredBufferSize)319 void ProgramVk::generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap,
320                                              gl::ShaderMap<size_t> &requiredBufferSize)
321 {
322     const gl::ProgramExecutable &glExecutable = mState.getExecutable();
323 
324     for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
325     {
326         gl::Shader *shader = mState.getAttachedShader(shaderType);
327 
328         if (shader)
329         {
330             const std::vector<sh::ShaderVariable> &uniforms = shader->getUniforms();
331             InitDefaultUniformBlock(uniforms, &layoutMap[shaderType],
332                                     &requiredBufferSize[shaderType]);
333         }
334     }
335 }
336 
initDefaultUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> & layoutMap)337 void ProgramVk::initDefaultUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap)
338 {
339     // Init the default block layout info.
340     const auto &uniforms                      = mState.getUniforms();
341     const gl::ProgramExecutable &glExecutable = mState.getExecutable();
342 
343     for (const gl::VariableLocation &location : mState.getUniformLocations())
344     {
345         gl::ShaderMap<sh::BlockMemberInfo> layoutInfo;
346 
347         if (location.used() && !location.ignored)
348         {
349             const auto &uniform = uniforms[location.index];
350             if (uniform.isInDefaultBlock() && !uniform.isSampler() && !uniform.isImage() &&
351                 !uniform.isFragmentInOut)
352             {
353                 std::string uniformName = uniform.name;
354                 if (uniform.isArray())
355                 {
356                     // Gets the uniform name without the [0] at the end.
357                     uniformName = gl::StripLastArrayIndex(uniformName);
358                     ASSERT(uniformName.size() != uniform.name.size());
359                 }
360 
361                 bool found = false;
362 
363                 for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
364                 {
365                     auto it = layoutMap[shaderType].find(uniformName);
366                     if (it != layoutMap[shaderType].end())
367                     {
368                         found                  = true;
369                         layoutInfo[shaderType] = it->second;
370                     }
371                 }
372 
373                 ASSERT(found);
374             }
375         }
376 
377         for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
378         {
379             mExecutable.mDefaultUniformBlocks[shaderType]->uniformLayout.push_back(
380                 layoutInfo[shaderType]);
381         }
382     }
383 }
384 
validate(const gl::Caps & caps,gl::InfoLog * infoLog)385 GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
386 {
387     // No-op. The spec is very vague about the behavior of validation.
388     return GL_TRUE;
389 }
390 
391 template <typename T>
setUniformImpl(GLint location,GLsizei count,const T * v,GLenum entryPointType)392 void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
393 {
394     const gl::VariableLocation &locationInfo  = mState.getUniformLocations()[location];
395     const gl::LinkedUniform &linkedUniform    = mState.getUniforms()[locationInfo.index];
396     const gl::ProgramExecutable &glExecutable = mState.getExecutable();
397 
398     ASSERT(!linkedUniform.isSampler());
399 
400     if (linkedUniform.typeInfo->type == entryPointType)
401     {
402         for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
403         {
404             DefaultUniformBlock &uniformBlock     = *mExecutable.mDefaultUniformBlocks[shaderType];
405             const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
406 
407             // Assume an offset of -1 means the block is unused.
408             if (layoutInfo.offset == -1)
409             {
410                 continue;
411             }
412 
413             const GLint componentCount = linkedUniform.typeInfo->componentCount;
414             UpdateDefaultUniformBlock(count, locationInfo.arrayIndex, componentCount, v, layoutInfo,
415                                       &uniformBlock.uniformData);
416             mExecutable.mDefaultUniformBlocksDirty.set(shaderType);
417         }
418     }
419     else
420     {
421         for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
422         {
423             DefaultUniformBlock &uniformBlock     = *mExecutable.mDefaultUniformBlocks[shaderType];
424             const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
425 
426             // Assume an offset of -1 means the block is unused.
427             if (layoutInfo.offset == -1)
428             {
429                 continue;
430             }
431 
432             const GLint componentCount = linkedUniform.typeInfo->componentCount;
433 
434             ASSERT(linkedUniform.typeInfo->type == gl::VariableBoolVectorType(entryPointType));
435 
436             GLint initialArrayOffset =
437                 locationInfo.arrayIndex * layoutInfo.arrayStride + layoutInfo.offset;
438             for (GLint i = 0; i < count; i++)
439             {
440                 GLint elementOffset = i * layoutInfo.arrayStride + initialArrayOffset;
441                 GLint *dst =
442                     reinterpret_cast<GLint *>(uniformBlock.uniformData.data() + elementOffset);
443                 const T *source = v + i * componentCount;
444 
445                 for (int c = 0; c < componentCount; c++)
446                 {
447                     dst[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
448                 }
449             }
450 
451             mExecutable.mDefaultUniformBlocksDirty.set(shaderType);
452         }
453     }
454 }
455 
456 template <typename T>
getUniformImpl(GLint location,T * v,GLenum entryPointType) const457 void ProgramVk::getUniformImpl(GLint location, T *v, GLenum entryPointType) const
458 {
459     const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
460     const gl::LinkedUniform &linkedUniform   = mState.getUniforms()[locationInfo.index];
461 
462     ASSERT(!linkedUniform.isSampler() && !linkedUniform.isImage());
463 
464     const gl::ShaderType shaderType = linkedUniform.getFirstShaderTypeWhereActive();
465     ASSERT(shaderType != gl::ShaderType::InvalidEnum);
466 
467     const DefaultUniformBlock &uniformBlock = *mExecutable.mDefaultUniformBlocks[shaderType];
468     const sh::BlockMemberInfo &layoutInfo   = uniformBlock.uniformLayout[location];
469 
470     ASSERT(linkedUniform.typeInfo->componentType == entryPointType ||
471            linkedUniform.typeInfo->componentType == gl::VariableBoolVectorType(entryPointType));
472 
473     if (gl::IsMatrixType(linkedUniform.type))
474     {
475         const uint8_t *ptrToElement = uniformBlock.uniformData.data() + layoutInfo.offset +
476                                       (locationInfo.arrayIndex * layoutInfo.arrayStride);
477         GetMatrixUniform(linkedUniform.type, v, reinterpret_cast<const T *>(ptrToElement), false);
478     }
479     else
480     {
481         ReadFromDefaultUniformBlock(linkedUniform.typeInfo->componentCount, locationInfo.arrayIndex,
482                                     v, layoutInfo, &uniformBlock.uniformData);
483     }
484 }
485 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)486 void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
487 {
488     setUniformImpl(location, count, v, GL_FLOAT);
489 }
490 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)491 void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
492 {
493     setUniformImpl(location, count, v, GL_FLOAT_VEC2);
494 }
495 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)496 void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
497 {
498     setUniformImpl(location, count, v, GL_FLOAT_VEC3);
499 }
500 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)501 void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
502 {
503     setUniformImpl(location, count, v, GL_FLOAT_VEC4);
504 }
505 
setUniform1iv(GLint location,GLsizei count,const GLint * v)506 void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
507 {
508     const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
509     const gl::LinkedUniform &linkedUniform   = mState.getUniforms()[locationInfo.index];
510     if (linkedUniform.isSampler())
511     {
512         // We could potentially cache some indexing here. For now this is a no-op since the mapping
513         // is handled entirely in ContextVk.
514         return;
515     }
516 
517     setUniformImpl(location, count, v, GL_INT);
518 }
519 
setUniform2iv(GLint location,GLsizei count,const GLint * v)520 void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
521 {
522     setUniformImpl(location, count, v, GL_INT_VEC2);
523 }
524 
setUniform3iv(GLint location,GLsizei count,const GLint * v)525 void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
526 {
527     setUniformImpl(location, count, v, GL_INT_VEC3);
528 }
529 
setUniform4iv(GLint location,GLsizei count,const GLint * v)530 void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
531 {
532     setUniformImpl(location, count, v, GL_INT_VEC4);
533 }
534 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)535 void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
536 {
537     setUniformImpl(location, count, v, GL_UNSIGNED_INT);
538 }
539 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)540 void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
541 {
542     setUniformImpl(location, count, v, GL_UNSIGNED_INT_VEC2);
543 }
544 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)545 void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
546 {
547     setUniformImpl(location, count, v, GL_UNSIGNED_INT_VEC3);
548 }
549 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)550 void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
551 {
552     setUniformImpl(location, count, v, GL_UNSIGNED_INT_VEC4);
553 }
554 
555 template <int cols, int rows>
setUniformMatrixfv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)556 void ProgramVk::setUniformMatrixfv(GLint location,
557                                    GLsizei count,
558                                    GLboolean transpose,
559                                    const GLfloat *value)
560 {
561     const gl::VariableLocation &locationInfo  = mState.getUniformLocations()[location];
562     const gl::LinkedUniform &linkedUniform    = mState.getUniforms()[locationInfo.index];
563     const gl::ProgramExecutable &glExecutable = mState.getExecutable();
564 
565     for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
566     {
567         DefaultUniformBlock &uniformBlock     = *mExecutable.mDefaultUniformBlocks[shaderType];
568         const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
569 
570         // Assume an offset of -1 means the block is unused.
571         if (layoutInfo.offset == -1)
572         {
573             continue;
574         }
575 
576         SetFloatUniformMatrixGLSL<cols, rows>::Run(
577             locationInfo.arrayIndex, linkedUniform.getArraySizeProduct(), count, transpose, value,
578             uniformBlock.uniformData.data() + layoutInfo.offset);
579 
580         mExecutable.mDefaultUniformBlocksDirty.set(shaderType);
581     }
582 }
583 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)584 void ProgramVk::setUniformMatrix2fv(GLint location,
585                                     GLsizei count,
586                                     GLboolean transpose,
587                                     const GLfloat *value)
588 {
589     setUniformMatrixfv<2, 2>(location, count, transpose, value);
590 }
591 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)592 void ProgramVk::setUniformMatrix3fv(GLint location,
593                                     GLsizei count,
594                                     GLboolean transpose,
595                                     const GLfloat *value)
596 {
597     setUniformMatrixfv<3, 3>(location, count, transpose, value);
598 }
599 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)600 void ProgramVk::setUniformMatrix4fv(GLint location,
601                                     GLsizei count,
602                                     GLboolean transpose,
603                                     const GLfloat *value)
604 {
605     setUniformMatrixfv<4, 4>(location, count, transpose, value);
606 }
607 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)608 void ProgramVk::setUniformMatrix2x3fv(GLint location,
609                                       GLsizei count,
610                                       GLboolean transpose,
611                                       const GLfloat *value)
612 {
613     setUniformMatrixfv<2, 3>(location, count, transpose, value);
614 }
615 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)616 void ProgramVk::setUniformMatrix3x2fv(GLint location,
617                                       GLsizei count,
618                                       GLboolean transpose,
619                                       const GLfloat *value)
620 {
621     setUniformMatrixfv<3, 2>(location, count, transpose, value);
622 }
623 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)624 void ProgramVk::setUniformMatrix2x4fv(GLint location,
625                                       GLsizei count,
626                                       GLboolean transpose,
627                                       const GLfloat *value)
628 {
629     setUniformMatrixfv<2, 4>(location, count, transpose, value);
630 }
631 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)632 void ProgramVk::setUniformMatrix4x2fv(GLint location,
633                                       GLsizei count,
634                                       GLboolean transpose,
635                                       const GLfloat *value)
636 {
637     setUniformMatrixfv<4, 2>(location, count, transpose, value);
638 }
639 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)640 void ProgramVk::setUniformMatrix3x4fv(GLint location,
641                                       GLsizei count,
642                                       GLboolean transpose,
643                                       const GLfloat *value)
644 {
645     setUniformMatrixfv<3, 4>(location, count, transpose, value);
646 }
647 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)648 void ProgramVk::setUniformMatrix4x3fv(GLint location,
649                                       GLsizei count,
650                                       GLboolean transpose,
651                                       const GLfloat *value)
652 {
653     setUniformMatrixfv<4, 3>(location, count, transpose, value);
654 }
655 
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const656 void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
657 {
658     getUniformImpl(location, params, GL_FLOAT);
659 }
660 
getUniformiv(const gl::Context * context,GLint location,GLint * params) const661 void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
662 {
663     getUniformImpl(location, params, GL_INT);
664 }
665 
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const666 void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
667 {
668     getUniformImpl(location, params, GL_UNSIGNED_INT);
669 }
670 }  // namespace rx
671