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