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