blob: 13a157aa958e8bbf9c33d82aac8dda3c7b1a171d [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 Madill9e54b5a2016-05-25 12:57:39 -040018
19namespace rx
20{
21
Jamie Madill76e471e2017-10-21 09:56:01 -040022namespace
23{
24
25gl::Error InitDefaultUniformBlock(const gl::Context *context,
26 VkDevice device,
27 gl::Shader *shader,
28 vk::BufferAndMemory *storageOut,
29 sh::BlockLayoutMap *blockLayoutMapOut,
30 size_t *requiredSizeOut)
31{
32 const auto &uniforms = shader->getUniforms(context);
33
34 if (uniforms.empty())
35 {
36 *requiredSizeOut = 0;
37 return gl::NoError();
38 }
39
40 sh::Std140BlockEncoder blockEncoder;
41 sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, false, blockLayoutMapOut);
42
43 size_t blockSize = blockEncoder.getBlockSize();
44
45 // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
46 if (blockSize == 0)
47 {
48 *requiredSizeOut = 0;
49 return gl::NoError();
50 }
51
52 VkBufferCreateInfo uniformBufferInfo;
53 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
54 uniformBufferInfo.pNext = nullptr;
55 uniformBufferInfo.flags = 0;
56 uniformBufferInfo.size = blockSize;
57 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
58 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
59 uniformBufferInfo.queueFamilyIndexCount = 0;
60 uniformBufferInfo.pQueueFamilyIndices = nullptr;
61
62 ANGLE_TRY(storageOut->buffer.init(device, uniformBufferInfo));
63
64 ANGLE_TRY(AllocateBufferMemory(GetImplAs<ContextVk>(context), blockSize, &storageOut->buffer,
65 &storageOut->memory, requiredSizeOut));
66
67 return gl::NoError();
68}
69
70template <typename T>
71void UpdateDefaultUniformBlock(GLsizei count,
72 int componentCount,
73 const T *v,
74 const sh::BlockMemberInfo &layoutInfo,
75 angle::MemoryBuffer *uniformData)
76{
77 // Assume an offset of -1 means the block is unused.
78 if (layoutInfo.offset == -1)
79 {
80 return;
81 }
82
83 int elementSize = sizeof(T) * componentCount;
84 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
85 {
86 uint8_t *writePtr = uniformData->data() + layoutInfo.offset;
87 memcpy(writePtr, v, elementSize * count);
88 }
89 else
90 {
91 UNIMPLEMENTED();
92 }
93}
94
95vk::Error SyncDefaultUniformBlock(VkDevice device,
96 vk::DeviceMemory *bufferMemory,
97 const angle::MemoryBuffer &bufferData)
98{
99 ASSERT(bufferMemory->valid() && !bufferData.empty());
100 uint8_t *mapPointer = nullptr;
101 ANGLE_TRY(bufferMemory->map(device, 0, bufferData.size(), 0, &mapPointer));
102 memcpy(mapPointer, bufferData.data(), bufferData.size());
103 bufferMemory->unmap(device);
104 return vk::NoError();
105}
106
107enum ShaderIndex : uint32_t
108{
109 MinShaderIndex = 0,
110 VertexShader = MinShaderIndex,
111 FragmentShader = 1,
112 MaxShaderIndex = 2,
113};
114
115gl::Shader *GetShader(const gl::ProgramState &programState, uint32_t shaderIndex)
116{
117 switch (shaderIndex)
118 {
119 case VertexShader:
120 return programState.getAttachedVertexShader();
121 case FragmentShader:
122 return programState.getAttachedFragmentShader();
123 default:
124 UNREACHABLE();
125 return nullptr;
126 }
127}
128
129} // anonymous namespace
130
131ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
132 : storage(), uniformData(), uniformsDirty(false), uniformLayout()
133{
134}
135
136ProgramVk::ProgramVk(const gl::ProgramState &state)
137 : ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSet(VK_NULL_HANDLE)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400138{
139}
140
141ProgramVk::~ProgramVk()
142{
143}
144
Jamie Madillc564c072017-06-01 12:45:42 -0400145void ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500146{
Jamie Madillc564c072017-06-01 12:45:42 -0400147 VkDevice device = GetImplAs<ContextVk>(contextImpl)->getDevice();
Jamie Madillc5143482017-10-15 20:20:06 -0400148 reset(device);
149}
Jamie Madill5deea722017-02-16 10:44:46 -0500150
Jamie Madillc5143482017-10-15 20:20:06 -0400151void ProgramVk::reset(VkDevice device)
152{
Jamie Madill76e471e2017-10-21 09:56:01 -0400153 for (auto &uniformBlock : mDefaultUniformBlocks)
154 {
155 uniformBlock.storage.memory.destroy(device);
156 uniformBlock.storage.buffer.destroy(device);
157 }
158
159 mEmptyUniformBlockStorage.memory.destroy(device);
160 mEmptyUniformBlockStorage.buffer.destroy(device);
161
162 for (auto &descriptorSetLayout : mDescriptorSetLayouts)
163 {
164 descriptorSetLayout.destroy(device);
165 }
166
Jamie Madill5deea722017-02-16 10:44:46 -0500167 mLinkedFragmentModule.destroy(device);
168 mLinkedVertexModule.destroy(device);
169 mPipelineLayout.destroy(device);
Jamie Madill76e471e2017-10-21 09:56:01 -0400170
171 // Descriptor Sets are pool allocated, so do not need to be explicitly freed.
172 mDescriptorSet = VK_NULL_HANDLE;
Jamie Madill5deea722017-02-16 10:44:46 -0500173}
174
Jamie Madill9cf9e872017-06-05 12:59:25 -0400175gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
176 gl::InfoLog &infoLog,
177 gl::BinaryInputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400178{
179 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500180 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400181}
182
Jamie Madill27a60632017-06-30 15:12:01 -0400183void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400184{
185 UNIMPLEMENTED();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400186}
187
188void ProgramVk::setBinaryRetrievableHint(bool retrievable)
189{
190 UNIMPLEMENTED();
191}
192
Yunchao He61afff12017-03-14 15:34:03 +0800193void ProgramVk::setSeparable(bool separable)
194{
195 UNIMPLEMENTED();
196}
197
Jamie Madill9cf9e872017-06-05 12:59:25 -0400198gl::LinkResult ProgramVk::link(const gl::Context *glContext,
199 const gl::VaryingPacking &packing,
200 gl::InfoLog &infoLog)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400201{
Jamie Madillc5143482017-10-15 20:20:06 -0400202 ContextVk *contextVk = GetImplAs<ContextVk>(glContext);
203 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500204 GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
Jamie Madillc5143482017-10-15 20:20:06 -0400205 VkDevice device = renderer->getDevice();
206
207 reset(device);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500208
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500209 std::vector<uint32_t> vertexCode;
210 std::vector<uint32_t> fragmentCode;
211 bool linkSuccess = false;
Jamie Madill2a9e1072017-09-22 11:31:57 -0400212 ANGLE_TRY_RESULT(glslangWrapper->linkProgram(glContext, mState, &vertexCode, &fragmentCode),
213 linkSuccess);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500214 if (!linkSuccess)
215 {
216 return false;
217 }
218
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500219 {
220 VkShaderModuleCreateInfo vertexShaderInfo;
221 vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
222 vertexShaderInfo.pNext = nullptr;
223 vertexShaderInfo.flags = 0;
224 vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
225 vertexShaderInfo.pCode = vertexCode.data();
Jamie Madillc5143482017-10-15 20:20:06 -0400226
227 ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500228 }
229
230 {
231 VkShaderModuleCreateInfo fragmentShaderInfo;
232 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
233 fragmentShaderInfo.pNext = nullptr;
234 fragmentShaderInfo.flags = 0;
235 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
236 fragmentShaderInfo.pCode = fragmentCode.data();
237
Jamie Madillc5143482017-10-15 20:20:06 -0400238 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500239 }
240
Jamie Madillc5143482017-10-15 20:20:06 -0400241 ANGLE_TRY(initPipelineLayout(contextVk));
Jamie Madill76e471e2017-10-21 09:56:01 -0400242 ANGLE_TRY(initDescriptorSets(contextVk));
243 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500244
245 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400246}
247
Jamie Madill76e471e2017-10-21 09:56:01 -0400248gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
249{
250 ContextVk *contextVk = GetImplAs<ContextVk>(glContext);
251 VkDevice device = contextVk->getDevice();
252
253 // Process vertex and fragment uniforms into std140 packing.
254 std::array<sh::BlockLayoutMap, 2> layoutMap;
255 std::array<size_t, 2> requiredBufferSize = {{0, 0}};
256
257 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
258 {
259 ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex),
260 &mDefaultUniformBlocks[shaderIndex].storage,
261 &layoutMap[shaderIndex],
262 &requiredBufferSize[shaderIndex]));
263 }
264
265 // Init the default block layout info.
266 const auto &locations = mState.getUniformLocations();
267 const auto &uniforms = mState.getUniforms();
268 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
269 {
270 std::array<sh::BlockMemberInfo, 2> layoutInfo;
271
272 const auto &location = locations[locationIndex];
273 if (location.used() && !location.ignored)
274 {
Jamie Madillde03e002017-10-21 14:04:20 -0400275 const auto &uniform = uniforms[location.index];
276
277 if (uniform.isSampler())
278 continue;
279
Jamie Madill76e471e2017-10-21 09:56:01 -0400280 std::string uniformName = uniform.name;
281 if (uniform.isArray())
282 {
283 uniformName += ArrayIndexString(location.arrayIndices);
284 }
285
286 bool found = false;
287
288 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
289 {
290 auto it = layoutMap[shaderIndex].find(uniformName);
291 if (it != layoutMap[shaderIndex].end())
292 {
293 found = true;
294 layoutInfo[shaderIndex] = it->second;
295 }
296 }
297
298 ASSERT(found);
299 }
300
301 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
302 {
303 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
304 }
305 }
306
307 bool anyDirty = false;
308 bool allDirty = true;
309
310 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
311 {
312 if (requiredBufferSize[shaderIndex] > 0)
313 {
314 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
315 requiredBufferSize[shaderIndex]))
316 {
317 return gl::OutOfMemory() << "Memory allocation failure.";
318 }
319 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
320 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
321
322 anyDirty = true;
323 }
324 else
325 {
326 allDirty = false;
327 }
328 }
329
330 if (anyDirty)
331 {
332 // Initialize the "empty" uniform block if necessary.
333 if (!allDirty)
334 {
335 VkBufferCreateInfo uniformBufferInfo;
336 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
337 uniformBufferInfo.pNext = nullptr;
338 uniformBufferInfo.flags = 0;
339 uniformBufferInfo.size = 1;
340 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
341 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
342 uniformBufferInfo.queueFamilyIndexCount = 0;
343 uniformBufferInfo.pQueueFamilyIndices = nullptr;
344
345 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
346
347 size_t requiredSize = 0;
348 ANGLE_TRY(AllocateBufferMemory(contextVk, 1, &mEmptyUniformBlockStorage.buffer,
349 &mEmptyUniformBlockStorage.memory, &requiredSize));
350 }
351
352 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
353 }
354
355 return gl::NoError();
356}
357
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400358GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
359{
360 UNIMPLEMENTED();
361 return GLboolean();
362}
363
Jamie Madill76e471e2017-10-21 09:56:01 -0400364template <typename T>
365void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
366{
367 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
368 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
369
370 if (linkedUniform.type == entryPointType)
371 {
372 for (auto &uniformBlock : mDefaultUniformBlocks)
373 {
374 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
375 UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
376 &uniformBlock.uniformData);
377 }
378 }
379 else
380 {
381 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
382 UNIMPLEMENTED();
383 }
384}
385
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400386void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
387{
Jamie Madill76e471e2017-10-21 09:56:01 -0400388 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400389}
390
391void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
392{
Jamie Madill76e471e2017-10-21 09:56:01 -0400393 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400394}
395
396void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
397{
Jamie Madill76e471e2017-10-21 09:56:01 -0400398 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400399}
400
401void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
402{
Jamie Madill76e471e2017-10-21 09:56:01 -0400403 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400404}
405
406void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
407{
408 UNIMPLEMENTED();
409}
410
411void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
412{
413 UNIMPLEMENTED();
414}
415
416void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
417{
418 UNIMPLEMENTED();
419}
420
421void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
422{
423 UNIMPLEMENTED();
424}
425
426void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
427{
428 UNIMPLEMENTED();
429}
430
431void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
432{
433 UNIMPLEMENTED();
434}
435
436void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
437{
438 UNIMPLEMENTED();
439}
440
441void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
442{
443 UNIMPLEMENTED();
444}
445
446void ProgramVk::setUniformMatrix2fv(GLint location,
447 GLsizei count,
448 GLboolean transpose,
449 const GLfloat *value)
450{
451 UNIMPLEMENTED();
452}
453
454void ProgramVk::setUniformMatrix3fv(GLint location,
455 GLsizei count,
456 GLboolean transpose,
457 const GLfloat *value)
458{
459 UNIMPLEMENTED();
460}
461
462void ProgramVk::setUniformMatrix4fv(GLint location,
463 GLsizei count,
464 GLboolean transpose,
465 const GLfloat *value)
466{
467 UNIMPLEMENTED();
468}
469
470void ProgramVk::setUniformMatrix2x3fv(GLint location,
471 GLsizei count,
472 GLboolean transpose,
473 const GLfloat *value)
474{
475 UNIMPLEMENTED();
476}
477
478void ProgramVk::setUniformMatrix3x2fv(GLint location,
479 GLsizei count,
480 GLboolean transpose,
481 const GLfloat *value)
482{
483 UNIMPLEMENTED();
484}
485
486void ProgramVk::setUniformMatrix2x4fv(GLint location,
487 GLsizei count,
488 GLboolean transpose,
489 const GLfloat *value)
490{
491 UNIMPLEMENTED();
492}
493
494void ProgramVk::setUniformMatrix4x2fv(GLint location,
495 GLsizei count,
496 GLboolean transpose,
497 const GLfloat *value)
498{
499 UNIMPLEMENTED();
500}
501
502void ProgramVk::setUniformMatrix3x4fv(GLint location,
503 GLsizei count,
504 GLboolean transpose,
505 const GLfloat *value)
506{
507 UNIMPLEMENTED();
508}
509
510void ProgramVk::setUniformMatrix4x3fv(GLint location,
511 GLsizei count,
512 GLboolean transpose,
513 const GLfloat *value)
514{
515 UNIMPLEMENTED();
516}
517
518void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
519{
520 UNIMPLEMENTED();
521}
522
Olli Etuaho855d9642017-05-17 14:05:06 +0300523bool ProgramVk::getUniformBlockSize(const std::string &blockName,
524 const std::string &blockMappedName,
525 size_t *sizeOut) const
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400526{
527 UNIMPLEMENTED();
528 return bool();
529}
530
531bool ProgramVk::getUniformBlockMemberInfo(const std::string &memberUniformName,
Olli Etuaho855d9642017-05-17 14:05:06 +0300532 const std::string &memberUniformMappedName,
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400533 sh::BlockMemberInfo *memberInfoOut) const
534{
535 UNIMPLEMENTED();
536 return bool();
537}
538
Sami Väisänen46eaa942016-06-29 10:26:37 +0300539void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
540 GLenum genMode,
541 GLint components,
542 const GLfloat *coeffs)
543{
544 UNIMPLEMENTED();
545}
546
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500547const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
548{
549 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
550 return mLinkedVertexModule;
551}
552
553const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
554{
555 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
556 return mLinkedFragmentModule;
557}
558
Jamie Madillc5143482017-10-15 20:20:06 -0400559const vk::PipelineLayout &ProgramVk::getPipelineLayout() const
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500560{
Jamie Madillc5143482017-10-15 20:20:06 -0400561 return mPipelineLayout;
562}
563
564vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
565{
566 ASSERT(!mPipelineLayout.valid());
567
568 VkDevice device = context->getDevice();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500569
Jamie Madill76e471e2017-10-21 09:56:01 -0400570 // Create two descriptor set layouts: one for default uniform info, and one for textures.
571 // Skip one or both if there are no uniforms.
572 VkDescriptorSetLayoutBinding uniformBindings[2];
573 uint32_t blockCount = 0;
574
575 {
576 auto &layoutBinding = uniformBindings[blockCount];
577
578 layoutBinding.binding = blockCount;
579 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
580 layoutBinding.descriptorCount = 1;
581 layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
582 layoutBinding.pImmutableSamplers = nullptr;
583
584 blockCount++;
585 }
586
587 {
588 auto &layoutBinding = uniformBindings[blockCount];
589
590 layoutBinding.binding = blockCount;
591 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
592 layoutBinding.descriptorCount = 1;
593 layoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
594 layoutBinding.pImmutableSamplers = nullptr;
595
596 blockCount++;
597 }
598
599 {
600 VkDescriptorSetLayoutCreateInfo uniformInfo;
601 uniformInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
602 uniformInfo.pNext = nullptr;
603 uniformInfo.flags = 0;
604 uniformInfo.bindingCount = blockCount;
605 uniformInfo.pBindings = uniformBindings;
606
607 vk::DescriptorSetLayout uniformLayout;
608 ANGLE_TRY(uniformLayout.init(device, uniformInfo));
609 mDescriptorSetLayouts.push_back(std::move(uniformLayout));
610 }
611
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500612 VkPipelineLayoutCreateInfo createInfo;
613 createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
614 createInfo.pNext = nullptr;
615 createInfo.flags = 0;
Jamie Madill76e471e2017-10-21 09:56:01 -0400616 createInfo.setLayoutCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
617 createInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500618 createInfo.pushConstantRangeCount = 0;
619 createInfo.pPushConstantRanges = nullptr;
620
Jamie Madillc5143482017-10-15 20:20:06 -0400621 ANGLE_TRY(mPipelineLayout.init(device, createInfo));
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500622
Jamie Madillc5143482017-10-15 20:20:06 -0400623 return vk::NoError();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500624}
625
Jamie Madill76e471e2017-10-21 09:56:01 -0400626vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
627{
628 ASSERT(mDescriptorSet == VK_NULL_HANDLE);
629
630 VkDevice device = contextVk->getDevice();
631
632 // Write out to a new a descriptor set.
633 // TODO(jmadill): Handle descriptor set lifetime.
634 vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
635
636 VkDescriptorSetAllocateInfo allocInfo;
637 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
638 allocInfo.pNext = nullptr;
639 allocInfo.descriptorPool = descriptorPool->getHandle();
640
641 // TODO(jmadill): Handle descriptor set layouts for textures.
642 allocInfo.descriptorSetCount = 1;
643 allocInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
644
645 ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSet));
646 return vk::NoError();
647}
648
Jamie Madill54164b02017-08-28 15:17:37 -0400649void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
650{
651 UNIMPLEMENTED();
652}
653
654void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
655{
656 UNIMPLEMENTED();
657}
658
659void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
660{
661 UNIMPLEMENTED();
662}
663
Jamie Madill76e471e2017-10-21 09:56:01 -0400664vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
665{
666 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
667 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
668 {
669 return vk::NoError();
670 }
671
672 VkDevice device = contextVk->getDevice();
673
674 // Update buffer memory by immediate mapping. This immediate update only works once.
675 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
676 for (auto &uniformBlock : mDefaultUniformBlocks)
677 {
678 if (uniformBlock.uniformsDirty)
679 {
680 ANGLE_TRY(SyncDefaultUniformBlock(device, &uniformBlock.storage.memory,
681 uniformBlock.uniformData));
682 uniformBlock.uniformsDirty = false;
683 }
684 }
685
686 return vk::NoError();
687}
688
689vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
690{
691 std::array<VkDescriptorBufferInfo, 2> descriptorBufferInfo;
692 std::array<VkWriteDescriptorSet, 2> writeDescriptorInfo;
693 uint32_t bufferCount = 0;
694
695 for (auto &uniformBlock : mDefaultUniformBlocks)
696 {
697 auto &bufferInfo = descriptorBufferInfo[bufferCount];
698
699 if (!uniformBlock.uniformData.empty())
700 {
701 bufferInfo.buffer = uniformBlock.storage.buffer.getHandle();
702 }
703 else
704 {
705 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
706 }
707
708 bufferInfo.offset = 0;
709 bufferInfo.range = VK_WHOLE_SIZE;
710
711 auto &writeInfo = writeDescriptorInfo[bufferCount];
712
713 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
714 writeInfo.pNext = nullptr;
715 writeInfo.dstSet = mDescriptorSet;
716 writeInfo.dstBinding = bufferCount;
717 writeInfo.dstArrayElement = 0;
718 writeInfo.descriptorCount = 1;
719 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
720 writeInfo.pImageInfo = nullptr;
721 writeInfo.pBufferInfo = &bufferInfo;
722 writeInfo.pTexelBufferView = nullptr;
723
724 bufferCount++;
725 }
726
727 VkDevice device = contextVk->getDevice();
728
729 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
730
731 return vk::NoError();
732}
733
734VkDescriptorSet ProgramVk::getDescriptorSet() const
735{
736 return mDescriptorSet;
737}
738
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400739} // namespace rx