blob: 7130d39db38d836bd6dcf2e76df369897035189d [file] [log] [blame]
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001//
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"
Jamie Madill76e471e2017-10-21 09:56:01 -040013#include "common/utilities.h"
Jamie Madillc564c072017-06-01 12:45:42 -040014#include "libANGLE/Context.h"
Jamie Madill8ecf7f92017-01-13 17:29:52 -050015#include "libANGLE/renderer/vulkan/ContextVk.h"
16#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
17#include "libANGLE/renderer/vulkan/RendererVk.h"
Jamie Madill5547b382017-10-23 18:16:01 -040018#include "libANGLE/renderer/vulkan/TextureVk.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040019
20namespace rx
21{
22
Jamie Madill76e471e2017-10-21 09:56:01 -040023namespace
24{
25
26gl::Error InitDefaultUniformBlock(const gl::Context *context,
27 VkDevice device,
28 gl::Shader *shader,
29 vk::BufferAndMemory *storageOut,
30 sh::BlockLayoutMap *blockLayoutMapOut,
31 size_t *requiredSizeOut)
32{
33 const auto &uniforms = shader->getUniforms(context);
34
35 if (uniforms.empty())
36 {
37 *requiredSizeOut = 0;
38 return gl::NoError();
39 }
40
41 sh::Std140BlockEncoder blockEncoder;
Olli Etuaho3de27032017-11-30 12:16:47 +020042 sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
Jamie Madill76e471e2017-10-21 09:56:01 -040043
44 size_t blockSize = blockEncoder.getBlockSize();
45
46 // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
47 if (blockSize == 0)
48 {
49 *requiredSizeOut = 0;
50 return gl::NoError();
51 }
52
53 VkBufferCreateInfo uniformBufferInfo;
54 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
55 uniformBufferInfo.pNext = nullptr;
56 uniformBufferInfo.flags = 0;
57 uniformBufferInfo.size = blockSize;
58 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
59 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
60 uniformBufferInfo.queueFamilyIndexCount = 0;
61 uniformBufferInfo.pQueueFamilyIndices = nullptr;
62
63 ANGLE_TRY(storageOut->buffer.init(device, uniformBufferInfo));
64
Jamie Madill57dd97a2018-02-06 17:10:49 -050065 // Assume host vislble/coherent memory available.
66 VkMemoryPropertyFlags flags =
67 (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Jamie Madill57fbfd82018-02-14 12:45:34 -050068
69 ContextVk *contextVk = vk::GetImpl(context);
70
71 ANGLE_TRY(AllocateBufferMemory(contextVk->getRenderer(), flags, &storageOut->buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -040072 &storageOut->memory, requiredSizeOut));
73
74 return gl::NoError();
75}
76
77template <typename T>
78void UpdateDefaultUniformBlock(GLsizei count,
79 int componentCount,
80 const T *v,
81 const sh::BlockMemberInfo &layoutInfo,
82 angle::MemoryBuffer *uniformData)
83{
84 // Assume an offset of -1 means the block is unused.
85 if (layoutInfo.offset == -1)
86 {
87 return;
88 }
89
90 int elementSize = sizeof(T) * componentCount;
91 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
92 {
93 uint8_t *writePtr = uniformData->data() + layoutInfo.offset;
94 memcpy(writePtr, v, elementSize * count);
95 }
96 else
97 {
98 UNIMPLEMENTED();
99 }
100}
101
Luc Ferron7cec3352018-03-13 13:29:34 -0400102template <typename T>
103void ReadFromDefaultUniformBlock(int componentCount,
104 T *dst,
105 const sh::BlockMemberInfo &layoutInfo,
106 const angle::MemoryBuffer *uniformData)
107{
108 ASSERT(layoutInfo.offset != -1);
109
110 int elementSize = sizeof(T) * componentCount;
111 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
112 {
113 const uint8_t *readPtr = uniformData->data() + layoutInfo.offset;
114 memcpy(dst, readPtr, elementSize);
115 }
116 else
117 {
118 UNIMPLEMENTED();
119 }
120}
121
Jamie Madill76e471e2017-10-21 09:56:01 -0400122vk::Error SyncDefaultUniformBlock(VkDevice device,
123 vk::DeviceMemory *bufferMemory,
124 const angle::MemoryBuffer &bufferData)
125{
126 ASSERT(bufferMemory->valid() && !bufferData.empty());
127 uint8_t *mapPointer = nullptr;
128 ANGLE_TRY(bufferMemory->map(device, 0, bufferData.size(), 0, &mapPointer));
129 memcpy(mapPointer, bufferData.data(), bufferData.size());
130 bufferMemory->unmap(device);
131 return vk::NoError();
132}
133
134enum ShaderIndex : uint32_t
135{
136 MinShaderIndex = 0,
137 VertexShader = MinShaderIndex,
138 FragmentShader = 1,
139 MaxShaderIndex = 2,
140};
141
142gl::Shader *GetShader(const gl::ProgramState &programState, uint32_t shaderIndex)
143{
144 switch (shaderIndex)
145 {
146 case VertexShader:
147 return programState.getAttachedVertexShader();
148 case FragmentShader:
149 return programState.getAttachedFragmentShader();
150 default:
151 UNREACHABLE();
152 return nullptr;
153 }
154}
155
156} // anonymous namespace
157
158ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
159 : storage(), uniformData(), uniformsDirty(false), uniformLayout()
160{
161}
162
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500163ProgramVk::DefaultUniformBlock::~DefaultUniformBlock()
164{
165}
166
Jamie Madill76e471e2017-10-21 09:56:01 -0400167ProgramVk::ProgramVk(const gl::ProgramState &state)
Jamie Madill8c3988c2017-12-21 14:44:56 -0500168 : ProgramImpl(state), mDefaultUniformBlocks(), mUsedDescriptorSetRange(), mDirtyTextures(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400169{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500170 mUsedDescriptorSetRange.invalidate();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400171}
172
173ProgramVk::~ProgramVk()
174{
175}
176
Jamie Madillb7d924a2018-03-10 11:16:54 -0500177gl::Error ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500178{
Jamie Madill67ae6c52018-03-09 11:49:01 -0500179 ContextVk *contextVk = vk::GetImpl(contextImpl);
Jamie Madillb7d924a2018-03-10 11:16:54 -0500180 return reset(contextVk);
Jamie Madillc5143482017-10-15 20:20:06 -0400181}
Jamie Madill5deea722017-02-16 10:44:46 -0500182
Jamie Madillb7d924a2018-03-10 11:16:54 -0500183vk::Error ProgramVk::reset(ContextVk *contextVk)
Jamie Madillc5143482017-10-15 20:20:06 -0400184{
Jamie Madill67ae6c52018-03-09 11:49:01 -0500185 // TODO(jmadill): Handle re-linking a program that is in-use. http://anglebug.com/2397
186
187 VkDevice device = contextVk->getDevice();
188
Jamie Madill76e471e2017-10-21 09:56:01 -0400189 for (auto &uniformBlock : mDefaultUniformBlocks)
190 {
191 uniformBlock.storage.memory.destroy(device);
192 uniformBlock.storage.buffer.destroy(device);
193 }
194
195 mEmptyUniformBlockStorage.memory.destroy(device);
196 mEmptyUniformBlockStorage.buffer.destroy(device);
197
Jamie Madill5deea722017-02-16 10:44:46 -0500198 mLinkedFragmentModule.destroy(device);
199 mLinkedVertexModule.destroy(device);
Jamie Madillf2f6d372018-01-10 21:37:23 -0500200 mVertexModuleSerial = Serial();
201 mFragmentModuleSerial = Serial();
Jamie Madill76e471e2017-10-21 09:56:01 -0400202
Jamie Madill67ae6c52018-03-09 11:49:01 -0500203 // Free our descriptor set handles.
204 if (!mDescriptorSets.empty())
205 {
206 vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
Jamie Madillb7d924a2018-03-10 11:16:54 -0500207 ANGLE_TRY(descriptorPool->freeDescriptorSets(
208 device, static_cast<uint32_t>(mDescriptorSets.size()), mDescriptorSets.data()));
Jamie Madill67ae6c52018-03-09 11:49:01 -0500209 }
Jamie Madill5547b382017-10-23 18:16:01 -0400210 mDescriptorSets.clear();
Jamie Madill8c3988c2017-12-21 14:44:56 -0500211 mUsedDescriptorSetRange.invalidate();
Jamie Madill5547b382017-10-23 18:16:01 -0400212 mDirtyTextures = false;
Jamie Madillb7d924a2018-03-10 11:16:54 -0500213
214 return vk::NoError();
Jamie Madill5deea722017-02-16 10:44:46 -0500215}
216
Jamie Madill9cf9e872017-06-05 12:59:25 -0400217gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
218 gl::InfoLog &infoLog,
219 gl::BinaryInputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400220{
221 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500222 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400223}
224
Jamie Madill27a60632017-06-30 15:12:01 -0400225void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400226{
227 UNIMPLEMENTED();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400228}
229
230void ProgramVk::setBinaryRetrievableHint(bool retrievable)
231{
232 UNIMPLEMENTED();
233}
234
Yunchao He61afff12017-03-14 15:34:03 +0800235void ProgramVk::setSeparable(bool separable)
236{
237 UNIMPLEMENTED();
238}
239
Jamie Madill9cf9e872017-06-05 12:59:25 -0400240gl::LinkResult ProgramVk::link(const gl::Context *glContext,
Jamie Madillc9727f32017-11-07 12:37:07 -0500241 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400242 gl::InfoLog &infoLog)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400243{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400244 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madillc5143482017-10-15 20:20:06 -0400245 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500246 GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
Jamie Madillc5143482017-10-15 20:20:06 -0400247 VkDevice device = renderer->getDevice();
248
Jamie Madillb7d924a2018-03-10 11:16:54 -0500249 ANGLE_TRY(reset(contextVk));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500250
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500251 std::vector<uint32_t> vertexCode;
252 std::vector<uint32_t> fragmentCode;
253 bool linkSuccess = false;
Jamie Madill4dd167f2017-11-09 13:08:31 -0500254 ANGLE_TRY_RESULT(
255 glslangWrapper->linkProgram(glContext, mState, resources, &vertexCode, &fragmentCode),
256 linkSuccess);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500257 if (!linkSuccess)
258 {
259 return false;
260 }
261
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500262 {
263 VkShaderModuleCreateInfo vertexShaderInfo;
264 vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
265 vertexShaderInfo.pNext = nullptr;
266 vertexShaderInfo.flags = 0;
267 vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
268 vertexShaderInfo.pCode = vertexCode.data();
Jamie Madillc5143482017-10-15 20:20:06 -0400269
270 ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
Jamie Madillf2f6d372018-01-10 21:37:23 -0500271 mVertexModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500272 }
273
274 {
275 VkShaderModuleCreateInfo fragmentShaderInfo;
276 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
277 fragmentShaderInfo.pNext = nullptr;
278 fragmentShaderInfo.flags = 0;
279 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
280 fragmentShaderInfo.pCode = fragmentCode.data();
281
Jamie Madillc5143482017-10-15 20:20:06 -0400282 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madillf2f6d372018-01-10 21:37:23 -0500283 mFragmentModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500284 }
285
Jamie Madill76e471e2017-10-21 09:56:01 -0400286 ANGLE_TRY(initDescriptorSets(contextVk));
287 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500288
Jamie Madill8c3988c2017-12-21 14:44:56 -0500289 if (!mState.getSamplerUniformRange().empty())
290 {
291 // Ensure the descriptor set range includes the textures at position 1.
292 mUsedDescriptorSetRange.extend(1);
293 mDirtyTextures = true;
294 }
295
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500296 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400297}
298
Jamie Madill76e471e2017-10-21 09:56:01 -0400299gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
300{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400301 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madill57fbfd82018-02-14 12:45:34 -0500302 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400303 VkDevice device = contextVk->getDevice();
304
305 // Process vertex and fragment uniforms into std140 packing.
306 std::array<sh::BlockLayoutMap, 2> layoutMap;
307 std::array<size_t, 2> requiredBufferSize = {{0, 0}};
308
309 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
310 {
311 ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex),
312 &mDefaultUniformBlocks[shaderIndex].storage,
313 &layoutMap[shaderIndex],
314 &requiredBufferSize[shaderIndex]));
315 }
316
317 // Init the default block layout info.
318 const auto &locations = mState.getUniformLocations();
319 const auto &uniforms = mState.getUniforms();
320 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
321 {
322 std::array<sh::BlockMemberInfo, 2> layoutInfo;
323
324 const auto &location = locations[locationIndex];
325 if (location.used() && !location.ignored)
326 {
Jamie Madillde03e002017-10-21 14:04:20 -0400327 const auto &uniform = uniforms[location.index];
328
329 if (uniform.isSampler())
330 continue;
331
Jamie Madill76e471e2017-10-21 09:56:01 -0400332 std::string uniformName = uniform.name;
333 if (uniform.isArray())
334 {
Olli Etuaho1734e172017-10-27 15:30:27 +0300335 uniformName += ArrayString(location.arrayIndex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400336 }
337
338 bool found = false;
339
340 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
341 {
342 auto it = layoutMap[shaderIndex].find(uniformName);
343 if (it != layoutMap[shaderIndex].end())
344 {
345 found = true;
346 layoutInfo[shaderIndex] = it->second;
347 }
348 }
349
350 ASSERT(found);
351 }
352
353 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
354 {
355 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
356 }
357 }
358
359 bool anyDirty = false;
360 bool allDirty = true;
361
362 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
363 {
364 if (requiredBufferSize[shaderIndex] > 0)
365 {
366 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
367 requiredBufferSize[shaderIndex]))
368 {
369 return gl::OutOfMemory() << "Memory allocation failure.";
370 }
371 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
372 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
373
374 anyDirty = true;
375 }
376 else
377 {
378 allDirty = false;
379 }
380 }
381
382 if (anyDirty)
383 {
384 // Initialize the "empty" uniform block if necessary.
385 if (!allDirty)
386 {
387 VkBufferCreateInfo uniformBufferInfo;
388 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
389 uniformBufferInfo.pNext = nullptr;
390 uniformBufferInfo.flags = 0;
391 uniformBufferInfo.size = 1;
392 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
393 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
394 uniformBufferInfo.queueFamilyIndexCount = 0;
395 uniformBufferInfo.pQueueFamilyIndices = nullptr;
396
397 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
398
Jamie Madill57dd97a2018-02-06 17:10:49 -0500399 // Assume host vislble/coherent memory available.
400 VkMemoryPropertyFlags flags =
401 (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Jamie Madill76e471e2017-10-21 09:56:01 -0400402 size_t requiredSize = 0;
Jamie Madill57fbfd82018-02-14 12:45:34 -0500403 ANGLE_TRY(AllocateBufferMemory(renderer, flags, &mEmptyUniformBlockStorage.buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -0400404 &mEmptyUniformBlockStorage.memory, &requiredSize));
405 }
406
407 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
Jamie Madill8c3988c2017-12-21 14:44:56 -0500408
409 // Ensure the descriptor set range includes the uniform buffers at position 0.
410 mUsedDescriptorSetRange.extend(0);
Jamie Madill5547b382017-10-23 18:16:01 -0400411 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400412
413 return gl::NoError();
414}
415
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400416GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
417{
418 UNIMPLEMENTED();
419 return GLboolean();
420}
421
Jamie Madill76e471e2017-10-21 09:56:01 -0400422template <typename T>
423void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
424{
425 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
426 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
427
Luc Ferron7cec3352018-03-13 13:29:34 -0400428 if (linkedUniform.isSampler())
429 {
430 UNIMPLEMENTED();
431 return;
432 }
433
Jamie Madill76e471e2017-10-21 09:56:01 -0400434 if (linkedUniform.type == entryPointType)
435 {
436 for (auto &uniformBlock : mDefaultUniformBlocks)
437 {
438 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
439 UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
440 &uniformBlock.uniformData);
441 }
442 }
443 else
444 {
445 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
446 UNIMPLEMENTED();
447 }
448}
449
Luc Ferron7cec3352018-03-13 13:29:34 -0400450template <typename T>
451void ProgramVk::getUniformImpl(GLint location, T *v, GLenum entryPointType) const
452{
453 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
454 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
455
456 if (linkedUniform.isSampler())
457 {
458 UNIMPLEMENTED();
459 return;
460 }
461
462 ASSERT(linkedUniform.typeInfo->componentType == entryPointType);
463 const gl::ShaderType shaderType = linkedUniform.getFirstStaticUseShaderType();
464 ASSERT(shaderType != gl::ShaderType::SHADER_TYPE_INVALID);
465
466 const DefaultUniformBlock &uniformBlock = mDefaultUniformBlocks[shaderType];
467 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
468 ReadFromDefaultUniformBlock(linkedUniform.typeInfo->componentCount, v, layoutInfo,
469 &uniformBlock.uniformData);
470}
471
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400472void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
473{
Jamie Madill76e471e2017-10-21 09:56:01 -0400474 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400475}
476
477void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
478{
Jamie Madill76e471e2017-10-21 09:56:01 -0400479 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400480}
481
482void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
483{
Jamie Madill76e471e2017-10-21 09:56:01 -0400484 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400485}
486
487void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
488{
Jamie Madill76e471e2017-10-21 09:56:01 -0400489 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400490}
491
492void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
493{
Luc Ferron7cec3352018-03-13 13:29:34 -0400494 setUniformImpl(location, count, v, GL_INT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400495}
496
497void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
498{
499 UNIMPLEMENTED();
500}
501
502void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
503{
504 UNIMPLEMENTED();
505}
506
507void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
508{
509 UNIMPLEMENTED();
510}
511
512void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
513{
514 UNIMPLEMENTED();
515}
516
517void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
518{
519 UNIMPLEMENTED();
520}
521
522void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
523{
524 UNIMPLEMENTED();
525}
526
527void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
528{
529 UNIMPLEMENTED();
530}
531
532void ProgramVk::setUniformMatrix2fv(GLint location,
533 GLsizei count,
534 GLboolean transpose,
535 const GLfloat *value)
536{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400537 if (transpose == GL_TRUE)
538 {
539 UNIMPLEMENTED();
540 return;
541 }
542
543 setUniformImpl(location, count, value, GL_FLOAT_MAT2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400544}
545
546void ProgramVk::setUniformMatrix3fv(GLint location,
547 GLsizei count,
548 GLboolean transpose,
549 const GLfloat *value)
550{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400551 if (transpose == GL_TRUE)
552 {
553 UNIMPLEMENTED();
554 return;
555 }
556 setUniformImpl(location, count, value, GL_FLOAT_MAT3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400557}
558
559void ProgramVk::setUniformMatrix4fv(GLint location,
560 GLsizei count,
561 GLboolean transpose,
562 const GLfloat *value)
563{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400564 if (transpose == GL_TRUE)
565 {
566 UNIMPLEMENTED();
567 return;
568 }
569
570 setUniformImpl(location, count, value, GL_FLOAT_MAT4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400571}
572
573void ProgramVk::setUniformMatrix2x3fv(GLint location,
574 GLsizei count,
575 GLboolean transpose,
576 const GLfloat *value)
577{
578 UNIMPLEMENTED();
579}
580
581void ProgramVk::setUniformMatrix3x2fv(GLint location,
582 GLsizei count,
583 GLboolean transpose,
584 const GLfloat *value)
585{
586 UNIMPLEMENTED();
587}
588
589void ProgramVk::setUniformMatrix2x4fv(GLint location,
590 GLsizei count,
591 GLboolean transpose,
592 const GLfloat *value)
593{
594 UNIMPLEMENTED();
595}
596
597void ProgramVk::setUniformMatrix4x2fv(GLint location,
598 GLsizei count,
599 GLboolean transpose,
600 const GLfloat *value)
601{
602 UNIMPLEMENTED();
603}
604
605void ProgramVk::setUniformMatrix3x4fv(GLint location,
606 GLsizei count,
607 GLboolean transpose,
608 const GLfloat *value)
609{
610 UNIMPLEMENTED();
611}
612
613void ProgramVk::setUniformMatrix4x3fv(GLint location,
614 GLsizei count,
615 GLboolean transpose,
616 const GLfloat *value)
617{
618 UNIMPLEMENTED();
619}
620
621void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
622{
623 UNIMPLEMENTED();
624}
625
Sami Väisänen46eaa942016-06-29 10:26:37 +0300626void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
627 GLenum genMode,
628 GLint components,
629 const GLfloat *coeffs)
630{
631 UNIMPLEMENTED();
632}
633
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500634const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
635{
636 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
637 return mLinkedVertexModule;
638}
639
Jamie Madillf2f6d372018-01-10 21:37:23 -0500640Serial ProgramVk::getVertexModuleSerial() const
641{
642 return mVertexModuleSerial;
643}
644
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500645const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
646{
647 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
648 return mLinkedFragmentModule;
649}
650
Jamie Madillf2f6d372018-01-10 21:37:23 -0500651Serial ProgramVk::getFragmentModuleSerial() const
652{
653 return mFragmentModuleSerial;
654}
655
Jamie Madill76e471e2017-10-21 09:56:01 -0400656vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
657{
Jamie Madill5547b382017-10-23 18:16:01 -0400658 ASSERT(mDescriptorSets.empty());
Jamie Madill76e471e2017-10-21 09:56:01 -0400659
Jamie Madill8c3988c2017-12-21 14:44:56 -0500660 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400661 VkDevice device = contextVk->getDevice();
662
663 // Write out to a new a descriptor set.
664 // TODO(jmadill): Handle descriptor set lifetime.
665 vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
666
Jamie Madill8c3988c2017-12-21 14:44:56 -0500667 const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
668
669 uint32_t descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
Jamie Madill76e471e2017-10-21 09:56:01 -0400670
Jamie Madill5547b382017-10-23 18:16:01 -0400671 VkDescriptorSetAllocateInfo allocInfo;
672 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
673 allocInfo.pNext = nullptr;
674 allocInfo.descriptorPool = descriptorPool->getHandle();
675 allocInfo.descriptorSetCount = descriptorSetCount;
Jamie Madill8c3988c2017-12-21 14:44:56 -0500676 allocInfo.pSetLayouts = descriptorSetLayouts[0].ptr();
Jamie Madill76e471e2017-10-21 09:56:01 -0400677
Jamie Madill5547b382017-10-23 18:16:01 -0400678 mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
679 ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
Jamie Madill76e471e2017-10-21 09:56:01 -0400680 return vk::NoError();
681}
682
Jamie Madill54164b02017-08-28 15:17:37 -0400683void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
684{
Luc Ferron7cec3352018-03-13 13:29:34 -0400685 getUniformImpl(location, params, GL_FLOAT);
Jamie Madill54164b02017-08-28 15:17:37 -0400686}
687
688void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
689{
Luc Ferron7cec3352018-03-13 13:29:34 -0400690 getUniformImpl(location, params, GL_INT);
Jamie Madill54164b02017-08-28 15:17:37 -0400691}
692
693void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
694{
695 UNIMPLEMENTED();
696}
697
Jamie Madill76e471e2017-10-21 09:56:01 -0400698vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
699{
700 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
701 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
702 {
703 return vk::NoError();
704 }
705
Jamie Madill8c3988c2017-12-21 14:44:56 -0500706 ASSERT(mUsedDescriptorSetRange.contains(0));
Jamie Madill5547b382017-10-23 18:16:01 -0400707
Jamie Madill76e471e2017-10-21 09:56:01 -0400708 VkDevice device = contextVk->getDevice();
709
710 // Update buffer memory by immediate mapping. This immediate update only works once.
711 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
712 for (auto &uniformBlock : mDefaultUniformBlocks)
713 {
714 if (uniformBlock.uniformsDirty)
715 {
716 ANGLE_TRY(SyncDefaultUniformBlock(device, &uniformBlock.storage.memory,
717 uniformBlock.uniformData));
718 uniformBlock.uniformsDirty = false;
719 }
720 }
721
722 return vk::NoError();
723}
724
725vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
726{
727 std::array<VkDescriptorBufferInfo, 2> descriptorBufferInfo;
728 std::array<VkWriteDescriptorSet, 2> writeDescriptorInfo;
729 uint32_t bufferCount = 0;
730
731 for (auto &uniformBlock : mDefaultUniformBlocks)
732 {
733 auto &bufferInfo = descriptorBufferInfo[bufferCount];
734
735 if (!uniformBlock.uniformData.empty())
736 {
737 bufferInfo.buffer = uniformBlock.storage.buffer.getHandle();
738 }
739 else
740 {
741 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
742 }
743
744 bufferInfo.offset = 0;
745 bufferInfo.range = VK_WHOLE_SIZE;
746
747 auto &writeInfo = writeDescriptorInfo[bufferCount];
748
749 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
750 writeInfo.pNext = nullptr;
Jamie Madill5547b382017-10-23 18:16:01 -0400751 writeInfo.dstSet = mDescriptorSets[0];
Jamie Madill76e471e2017-10-21 09:56:01 -0400752 writeInfo.dstBinding = bufferCount;
753 writeInfo.dstArrayElement = 0;
754 writeInfo.descriptorCount = 1;
755 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
756 writeInfo.pImageInfo = nullptr;
757 writeInfo.pBufferInfo = &bufferInfo;
758 writeInfo.pTexelBufferView = nullptr;
759
760 bufferCount++;
761 }
762
763 VkDevice device = contextVk->getDevice();
764
765 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
766
767 return vk::NoError();
768}
769
Jamie Madill5547b382017-10-23 18:16:01 -0400770const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
Jamie Madill76e471e2017-10-21 09:56:01 -0400771{
Jamie Madill5547b382017-10-23 18:16:01 -0400772 return mDescriptorSets;
773}
774
Jamie Madill8c3988c2017-12-21 14:44:56 -0500775const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
Jamie Madill5547b382017-10-23 18:16:01 -0400776{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500777 return mUsedDescriptorSetRange;
Jamie Madill5547b382017-10-23 18:16:01 -0400778}
779
780void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
781{
782 if (mState.getSamplerBindings().empty() || !mDirtyTextures)
783 {
784 return;
785 }
786
Jamie Madill8c3988c2017-12-21 14:44:56 -0500787 ASSERT(mUsedDescriptorSetRange.contains(1));
788 VkDescriptorSet descriptorSet = mDescriptorSets[1];
Jamie Madill5547b382017-10-23 18:16:01 -0400789
790 // TODO(jmadill): Don't hard-code the texture limit.
791 ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
792 ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
793 uint32_t imageCount = 0;
794
795 const gl::State &glState = contextVk->getGLState();
796 const auto &completeTextures = glState.getCompleteTextureCache();
797
798 for (const auto &samplerBinding : mState.getSamplerBindings())
799 {
800 ASSERT(!samplerBinding.unreferenced);
801
802 // TODO(jmadill): Sampler arrays
803 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
804
805 GLuint textureUnit = samplerBinding.boundTextureUnits[0];
806 const gl::Texture *texture = completeTextures[textureUnit];
807
808 // TODO(jmadill): Incomplete textures handling.
809 ASSERT(texture);
810
Jamie Madille1f3ad42017-10-28 23:00:42 -0400811 TextureVk *textureVk = vk::GetImpl(texture);
Jamie Madill5547b382017-10-23 18:16:01 -0400812 const vk::Image &image = textureVk->getImage();
813
814 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
815
816 imageInfo.sampler = textureVk->getSampler().getHandle();
817 imageInfo.imageView = textureVk->getImageView().getHandle();
818 imageInfo.imageLayout = image.getCurrentLayout();
819
820 auto &writeInfo = writeDescriptorInfo[imageCount];
821
822 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
823 writeInfo.pNext = nullptr;
824 writeInfo.dstSet = descriptorSet;
825 writeInfo.dstBinding = imageCount;
826 writeInfo.dstArrayElement = 0;
827 writeInfo.descriptorCount = 1;
828 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
829 writeInfo.pImageInfo = &imageInfo;
830 writeInfo.pBufferInfo = nullptr;
831 writeInfo.pTexelBufferView = nullptr;
832
833 imageCount++;
834 }
835
836 VkDevice device = contextVk->getDevice();
837
838 ASSERT(imageCount > 0);
839 vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
840
841 mDirtyTextures = false;
842}
843
844void ProgramVk::invalidateTextures()
845{
846 mDirtyTextures = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400847}
848
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400849} // namespace rx