blob: 01d11a31bef43efcfdb03f9ceeb881d4aa78d4e1 [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;
42 sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, false, blockLayoutMapOut);
43
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 Madille1f3ad42017-10-28 23:00:42 -040065 ANGLE_TRY(AllocateBufferMemory(vk::GetImpl(context), blockSize, &storageOut->buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -040066 &storageOut->memory, requiredSizeOut));
67
68 return gl::NoError();
69}
70
71template <typename T>
72void UpdateDefaultUniformBlock(GLsizei count,
73 int componentCount,
74 const T *v,
75 const sh::BlockMemberInfo &layoutInfo,
76 angle::MemoryBuffer *uniformData)
77{
78 // Assume an offset of -1 means the block is unused.
79 if (layoutInfo.offset == -1)
80 {
81 return;
82 }
83
84 int elementSize = sizeof(T) * componentCount;
85 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
86 {
87 uint8_t *writePtr = uniformData->data() + layoutInfo.offset;
88 memcpy(writePtr, v, elementSize * count);
89 }
90 else
91 {
92 UNIMPLEMENTED();
93 }
94}
95
96vk::Error SyncDefaultUniformBlock(VkDevice device,
97 vk::DeviceMemory *bufferMemory,
98 const angle::MemoryBuffer &bufferData)
99{
100 ASSERT(bufferMemory->valid() && !bufferData.empty());
101 uint8_t *mapPointer = nullptr;
102 ANGLE_TRY(bufferMemory->map(device, 0, bufferData.size(), 0, &mapPointer));
103 memcpy(mapPointer, bufferData.data(), bufferData.size());
104 bufferMemory->unmap(device);
105 return vk::NoError();
106}
107
108enum ShaderIndex : uint32_t
109{
110 MinShaderIndex = 0,
111 VertexShader = MinShaderIndex,
112 FragmentShader = 1,
113 MaxShaderIndex = 2,
114};
115
116gl::Shader *GetShader(const gl::ProgramState &programState, uint32_t shaderIndex)
117{
118 switch (shaderIndex)
119 {
120 case VertexShader:
121 return programState.getAttachedVertexShader();
122 case FragmentShader:
123 return programState.getAttachedFragmentShader();
124 default:
125 UNREACHABLE();
126 return nullptr;
127 }
128}
129
130} // anonymous namespace
131
132ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
133 : storage(), uniformData(), uniformsDirty(false), uniformLayout()
134{
135}
136
137ProgramVk::ProgramVk(const gl::ProgramState &state)
Jamie Madill5547b382017-10-23 18:16:01 -0400138 : ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSetOffset(0), mDirtyTextures(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400139{
140}
141
142ProgramVk::~ProgramVk()
143{
144}
145
Jamie Madillc564c072017-06-01 12:45:42 -0400146void ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500147{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400148 VkDevice device = vk::GetImpl(contextImpl)->getDevice();
Jamie Madillc5143482017-10-15 20:20:06 -0400149 reset(device);
150}
Jamie Madill5deea722017-02-16 10:44:46 -0500151
Jamie Madillc5143482017-10-15 20:20:06 -0400152void ProgramVk::reset(VkDevice device)
153{
Jamie Madill76e471e2017-10-21 09:56:01 -0400154 for (auto &uniformBlock : mDefaultUniformBlocks)
155 {
156 uniformBlock.storage.memory.destroy(device);
157 uniformBlock.storage.buffer.destroy(device);
158 }
159
160 mEmptyUniformBlockStorage.memory.destroy(device);
161 mEmptyUniformBlockStorage.buffer.destroy(device);
162
163 for (auto &descriptorSetLayout : mDescriptorSetLayouts)
164 {
165 descriptorSetLayout.destroy(device);
166 }
167
Jamie Madill5deea722017-02-16 10:44:46 -0500168 mLinkedFragmentModule.destroy(device);
169 mLinkedVertexModule.destroy(device);
170 mPipelineLayout.destroy(device);
Jamie Madill76e471e2017-10-21 09:56:01 -0400171
172 // Descriptor Sets are pool allocated, so do not need to be explicitly freed.
Jamie Madill5547b382017-10-23 18:16:01 -0400173 mDescriptorSets.clear();
174 mDescriptorSetOffset = 0;
175 mDirtyTextures = false;
Jamie Madill5deea722017-02-16 10:44:46 -0500176}
177
Jamie Madill9cf9e872017-06-05 12:59:25 -0400178gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
179 gl::InfoLog &infoLog,
180 gl::BinaryInputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400181{
182 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500183 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400184}
185
Jamie Madill27a60632017-06-30 15:12:01 -0400186void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400187{
188 UNIMPLEMENTED();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400189}
190
191void ProgramVk::setBinaryRetrievableHint(bool retrievable)
192{
193 UNIMPLEMENTED();
194}
195
Yunchao He61afff12017-03-14 15:34:03 +0800196void ProgramVk::setSeparable(bool separable)
197{
198 UNIMPLEMENTED();
199}
200
Jamie Madill9cf9e872017-06-05 12:59:25 -0400201gl::LinkResult ProgramVk::link(const gl::Context *glContext,
Jamie Madillc9727f32017-11-07 12:37:07 -0500202 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400203 gl::InfoLog &infoLog)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400204{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400205 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madillc5143482017-10-15 20:20:06 -0400206 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500207 GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
Jamie Madillc5143482017-10-15 20:20:06 -0400208 VkDevice device = renderer->getDevice();
209
210 reset(device);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500211
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500212 std::vector<uint32_t> vertexCode;
213 std::vector<uint32_t> fragmentCode;
214 bool linkSuccess = false;
Jamie Madill4dd167f2017-11-09 13:08:31 -0500215 ANGLE_TRY_RESULT(
216 glslangWrapper->linkProgram(glContext, mState, resources, &vertexCode, &fragmentCode),
217 linkSuccess);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500218 if (!linkSuccess)
219 {
220 return false;
221 }
222
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500223 {
224 VkShaderModuleCreateInfo vertexShaderInfo;
225 vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
226 vertexShaderInfo.pNext = nullptr;
227 vertexShaderInfo.flags = 0;
228 vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
229 vertexShaderInfo.pCode = vertexCode.data();
Jamie Madillc5143482017-10-15 20:20:06 -0400230
231 ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500232 }
233
234 {
235 VkShaderModuleCreateInfo fragmentShaderInfo;
236 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
237 fragmentShaderInfo.pNext = nullptr;
238 fragmentShaderInfo.flags = 0;
239 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
240 fragmentShaderInfo.pCode = fragmentCode.data();
241
Jamie Madillc5143482017-10-15 20:20:06 -0400242 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500243 }
244
Jamie Madillc5143482017-10-15 20:20:06 -0400245 ANGLE_TRY(initPipelineLayout(contextVk));
Jamie Madill76e471e2017-10-21 09:56:01 -0400246 ANGLE_TRY(initDescriptorSets(contextVk));
247 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500248
249 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400250}
251
Jamie Madill76e471e2017-10-21 09:56:01 -0400252gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
253{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400254 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madill76e471e2017-10-21 09:56:01 -0400255 VkDevice device = contextVk->getDevice();
256
257 // Process vertex and fragment uniforms into std140 packing.
258 std::array<sh::BlockLayoutMap, 2> layoutMap;
259 std::array<size_t, 2> requiredBufferSize = {{0, 0}};
260
261 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
262 {
263 ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex),
264 &mDefaultUniformBlocks[shaderIndex].storage,
265 &layoutMap[shaderIndex],
266 &requiredBufferSize[shaderIndex]));
267 }
268
269 // Init the default block layout info.
270 const auto &locations = mState.getUniformLocations();
271 const auto &uniforms = mState.getUniforms();
272 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
273 {
274 std::array<sh::BlockMemberInfo, 2> layoutInfo;
275
276 const auto &location = locations[locationIndex];
277 if (location.used() && !location.ignored)
278 {
Jamie Madillde03e002017-10-21 14:04:20 -0400279 const auto &uniform = uniforms[location.index];
280
281 if (uniform.isSampler())
282 continue;
283
Jamie Madill76e471e2017-10-21 09:56:01 -0400284 std::string uniformName = uniform.name;
285 if (uniform.isArray())
286 {
Olli Etuaho1734e172017-10-27 15:30:27 +0300287 uniformName += ArrayString(location.arrayIndex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400288 }
289
290 bool found = false;
291
292 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
293 {
294 auto it = layoutMap[shaderIndex].find(uniformName);
295 if (it != layoutMap[shaderIndex].end())
296 {
297 found = true;
298 layoutInfo[shaderIndex] = it->second;
299 }
300 }
301
302 ASSERT(found);
303 }
304
305 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
306 {
307 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
308 }
309 }
310
311 bool anyDirty = false;
312 bool allDirty = true;
313
314 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
315 {
316 if (requiredBufferSize[shaderIndex] > 0)
317 {
318 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
319 requiredBufferSize[shaderIndex]))
320 {
321 return gl::OutOfMemory() << "Memory allocation failure.";
322 }
323 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
324 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
325
326 anyDirty = true;
327 }
328 else
329 {
330 allDirty = false;
331 }
332 }
333
334 if (anyDirty)
335 {
336 // Initialize the "empty" uniform block if necessary.
337 if (!allDirty)
338 {
339 VkBufferCreateInfo uniformBufferInfo;
340 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
341 uniformBufferInfo.pNext = nullptr;
342 uniformBufferInfo.flags = 0;
343 uniformBufferInfo.size = 1;
344 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
345 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
346 uniformBufferInfo.queueFamilyIndexCount = 0;
347 uniformBufferInfo.pQueueFamilyIndices = nullptr;
348
349 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
350
351 size_t requiredSize = 0;
352 ANGLE_TRY(AllocateBufferMemory(contextVk, 1, &mEmptyUniformBlockStorage.buffer,
353 &mEmptyUniformBlockStorage.memory, &requiredSize));
354 }
355
356 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
357 }
Jamie Madill5547b382017-10-23 18:16:01 -0400358 else
359 {
360 // If the program has no uniforms, note this in the offset.
361 mDescriptorSetOffset = 1;
362 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400363
364 return gl::NoError();
365}
366
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400367GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
368{
369 UNIMPLEMENTED();
370 return GLboolean();
371}
372
Jamie Madill76e471e2017-10-21 09:56:01 -0400373template <typename T>
374void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
375{
376 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
377 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
378
379 if (linkedUniform.type == entryPointType)
380 {
381 for (auto &uniformBlock : mDefaultUniformBlocks)
382 {
383 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
384 UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
385 &uniformBlock.uniformData);
386 }
387 }
388 else
389 {
390 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
391 UNIMPLEMENTED();
392 }
393}
394
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400395void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
396{
Jamie Madill76e471e2017-10-21 09:56:01 -0400397 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400398}
399
400void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
401{
Jamie Madill76e471e2017-10-21 09:56:01 -0400402 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400403}
404
405void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
406{
Jamie Madill76e471e2017-10-21 09:56:01 -0400407 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400408}
409
410void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
411{
Jamie Madill76e471e2017-10-21 09:56:01 -0400412 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400413}
414
415void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
416{
417 UNIMPLEMENTED();
418}
419
420void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
421{
422 UNIMPLEMENTED();
423}
424
425void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
426{
427 UNIMPLEMENTED();
428}
429
430void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
431{
432 UNIMPLEMENTED();
433}
434
435void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
436{
437 UNIMPLEMENTED();
438}
439
440void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
441{
442 UNIMPLEMENTED();
443}
444
445void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
446{
447 UNIMPLEMENTED();
448}
449
450void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
451{
452 UNIMPLEMENTED();
453}
454
455void ProgramVk::setUniformMatrix2fv(GLint location,
456 GLsizei count,
457 GLboolean transpose,
458 const GLfloat *value)
459{
460 UNIMPLEMENTED();
461}
462
463void ProgramVk::setUniformMatrix3fv(GLint location,
464 GLsizei count,
465 GLboolean transpose,
466 const GLfloat *value)
467{
468 UNIMPLEMENTED();
469}
470
471void ProgramVk::setUniformMatrix4fv(GLint location,
472 GLsizei count,
473 GLboolean transpose,
474 const GLfloat *value)
475{
476 UNIMPLEMENTED();
477}
478
479void ProgramVk::setUniformMatrix2x3fv(GLint location,
480 GLsizei count,
481 GLboolean transpose,
482 const GLfloat *value)
483{
484 UNIMPLEMENTED();
485}
486
487void ProgramVk::setUniformMatrix3x2fv(GLint location,
488 GLsizei count,
489 GLboolean transpose,
490 const GLfloat *value)
491{
492 UNIMPLEMENTED();
493}
494
495void ProgramVk::setUniformMatrix2x4fv(GLint location,
496 GLsizei count,
497 GLboolean transpose,
498 const GLfloat *value)
499{
500 UNIMPLEMENTED();
501}
502
503void ProgramVk::setUniformMatrix4x2fv(GLint location,
504 GLsizei count,
505 GLboolean transpose,
506 const GLfloat *value)
507{
508 UNIMPLEMENTED();
509}
510
511void ProgramVk::setUniformMatrix3x4fv(GLint location,
512 GLsizei count,
513 GLboolean transpose,
514 const GLfloat *value)
515{
516 UNIMPLEMENTED();
517}
518
519void ProgramVk::setUniformMatrix4x3fv(GLint location,
520 GLsizei count,
521 GLboolean transpose,
522 const GLfloat *value)
523{
524 UNIMPLEMENTED();
525}
526
527void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
528{
529 UNIMPLEMENTED();
530}
531
Sami Väisänen46eaa942016-06-29 10:26:37 +0300532void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
533 GLenum genMode,
534 GLint components,
535 const GLfloat *coeffs)
536{
537 UNIMPLEMENTED();
538}
539
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500540const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
541{
542 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
543 return mLinkedVertexModule;
544}
545
546const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
547{
548 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
549 return mLinkedFragmentModule;
550}
551
Jamie Madillc5143482017-10-15 20:20:06 -0400552const vk::PipelineLayout &ProgramVk::getPipelineLayout() const
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500553{
Jamie Madillc5143482017-10-15 20:20:06 -0400554 return mPipelineLayout;
555}
556
557vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
558{
559 ASSERT(!mPipelineLayout.valid());
560
561 VkDevice device = context->getDevice();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500562
Jamie Madill76e471e2017-10-21 09:56:01 -0400563 // Create two descriptor set layouts: one for default uniform info, and one for textures.
564 // Skip one or both if there are no uniforms.
565 VkDescriptorSetLayoutBinding uniformBindings[2];
566 uint32_t blockCount = 0;
567
568 {
569 auto &layoutBinding = uniformBindings[blockCount];
570
571 layoutBinding.binding = blockCount;
572 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
573 layoutBinding.descriptorCount = 1;
574 layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
575 layoutBinding.pImmutableSamplers = nullptr;
576
577 blockCount++;
578 }
579
580 {
581 auto &layoutBinding = uniformBindings[blockCount];
582
583 layoutBinding.binding = blockCount;
584 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
585 layoutBinding.descriptorCount = 1;
586 layoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
587 layoutBinding.pImmutableSamplers = nullptr;
588
589 blockCount++;
590 }
591
592 {
593 VkDescriptorSetLayoutCreateInfo uniformInfo;
594 uniformInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
595 uniformInfo.pNext = nullptr;
596 uniformInfo.flags = 0;
597 uniformInfo.bindingCount = blockCount;
598 uniformInfo.pBindings = uniformBindings;
599
600 vk::DescriptorSetLayout uniformLayout;
601 ANGLE_TRY(uniformLayout.init(device, uniformInfo));
602 mDescriptorSetLayouts.push_back(std::move(uniformLayout));
603 }
604
Jamie Madill5547b382017-10-23 18:16:01 -0400605 const auto &samplerBindings = mState.getSamplerBindings();
606
607 if (!samplerBindings.empty())
608 {
609 std::vector<VkDescriptorSetLayoutBinding> textureBindings;
610 uint32_t textureCount = 0;
611 const auto &uniforms = mState.getUniforms();
612 for (unsigned int uniformIndex : mState.getSamplerUniformRange())
613 {
614 const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
615 unsigned int samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformIndex);
616 const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
617
618 ASSERT(!samplerBinding.unreferenced);
619
620 VkDescriptorSetLayoutBinding layoutBinding;
621
622 uint32_t elementCount = samplerUniform.elementCount();
623
624 layoutBinding.binding = textureCount;
625 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
626 layoutBinding.descriptorCount = elementCount;
627
628 layoutBinding.stageFlags = 0;
629 if (samplerUniform.vertexStaticUse)
630 {
631 layoutBinding.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
632 }
633 if (samplerUniform.fragmentStaticUse)
634 {
635 layoutBinding.stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
636 }
637
638 layoutBinding.pImmutableSamplers = nullptr;
639
640 textureCount += elementCount;
641
642 textureBindings.push_back(layoutBinding);
643 }
644
645 VkDescriptorSetLayoutCreateInfo textureInfo;
646 textureInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
647 textureInfo.pNext = nullptr;
648 textureInfo.flags = 0;
649 textureInfo.bindingCount = static_cast<uint32_t>(textureBindings.size());
650 textureInfo.pBindings = textureBindings.data();
651
652 vk::DescriptorSetLayout textureLayout;
653 ANGLE_TRY(textureLayout.init(device, textureInfo));
654 mDescriptorSetLayouts.push_back(std::move(textureLayout));
655
656 mDirtyTextures = true;
657 }
658
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500659 VkPipelineLayoutCreateInfo createInfo;
660 createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
661 createInfo.pNext = nullptr;
662 createInfo.flags = 0;
Jamie Madill76e471e2017-10-21 09:56:01 -0400663 createInfo.setLayoutCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
664 createInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500665 createInfo.pushConstantRangeCount = 0;
666 createInfo.pPushConstantRanges = nullptr;
667
Jamie Madillc5143482017-10-15 20:20:06 -0400668 ANGLE_TRY(mPipelineLayout.init(device, createInfo));
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500669
Jamie Madillc5143482017-10-15 20:20:06 -0400670 return vk::NoError();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500671}
672
Jamie Madill76e471e2017-10-21 09:56:01 -0400673vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
674{
Jamie Madill5547b382017-10-23 18:16:01 -0400675 ASSERT(mDescriptorSets.empty());
Jamie Madill76e471e2017-10-21 09:56:01 -0400676
677 VkDevice device = contextVk->getDevice();
678
679 // Write out to a new a descriptor set.
680 // TODO(jmadill): Handle descriptor set lifetime.
681 vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
682
Jamie Madill5547b382017-10-23 18:16:01 -0400683 uint32_t descriptorSetCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
Jamie Madill76e471e2017-10-21 09:56:01 -0400684
Jamie Madill5547b382017-10-23 18:16:01 -0400685 VkDescriptorSetAllocateInfo allocInfo;
686 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
687 allocInfo.pNext = nullptr;
688 allocInfo.descriptorPool = descriptorPool->getHandle();
689 allocInfo.descriptorSetCount = descriptorSetCount;
Jamie Madill76e471e2017-10-21 09:56:01 -0400690 allocInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
691
Jamie Madill5547b382017-10-23 18:16:01 -0400692 mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
693 ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
Jamie Madill76e471e2017-10-21 09:56:01 -0400694 return vk::NoError();
695}
696
Jamie Madill54164b02017-08-28 15:17:37 -0400697void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
698{
699 UNIMPLEMENTED();
700}
701
702void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
703{
704 UNIMPLEMENTED();
705}
706
707void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
708{
709 UNIMPLEMENTED();
710}
711
Jamie Madill76e471e2017-10-21 09:56:01 -0400712vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
713{
714 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
715 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
716 {
717 return vk::NoError();
718 }
719
Jamie Madill5547b382017-10-23 18:16:01 -0400720 ASSERT(mDescriptorSetOffset == 0);
721
Jamie Madill76e471e2017-10-21 09:56:01 -0400722 VkDevice device = contextVk->getDevice();
723
724 // Update buffer memory by immediate mapping. This immediate update only works once.
725 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
726 for (auto &uniformBlock : mDefaultUniformBlocks)
727 {
728 if (uniformBlock.uniformsDirty)
729 {
730 ANGLE_TRY(SyncDefaultUniformBlock(device, &uniformBlock.storage.memory,
731 uniformBlock.uniformData));
732 uniformBlock.uniformsDirty = false;
733 }
734 }
735
736 return vk::NoError();
737}
738
739vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
740{
741 std::array<VkDescriptorBufferInfo, 2> descriptorBufferInfo;
742 std::array<VkWriteDescriptorSet, 2> writeDescriptorInfo;
743 uint32_t bufferCount = 0;
744
745 for (auto &uniformBlock : mDefaultUniformBlocks)
746 {
747 auto &bufferInfo = descriptorBufferInfo[bufferCount];
748
749 if (!uniformBlock.uniformData.empty())
750 {
751 bufferInfo.buffer = uniformBlock.storage.buffer.getHandle();
752 }
753 else
754 {
755 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
756 }
757
758 bufferInfo.offset = 0;
759 bufferInfo.range = VK_WHOLE_SIZE;
760
761 auto &writeInfo = writeDescriptorInfo[bufferCount];
762
763 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
764 writeInfo.pNext = nullptr;
Jamie Madill5547b382017-10-23 18:16:01 -0400765 writeInfo.dstSet = mDescriptorSets[0];
Jamie Madill76e471e2017-10-21 09:56:01 -0400766 writeInfo.dstBinding = bufferCount;
767 writeInfo.dstArrayElement = 0;
768 writeInfo.descriptorCount = 1;
769 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
770 writeInfo.pImageInfo = nullptr;
771 writeInfo.pBufferInfo = &bufferInfo;
772 writeInfo.pTexelBufferView = nullptr;
773
774 bufferCount++;
775 }
776
777 VkDevice device = contextVk->getDevice();
778
779 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
780
781 return vk::NoError();
782}
783
Jamie Madill5547b382017-10-23 18:16:01 -0400784const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
Jamie Madill76e471e2017-10-21 09:56:01 -0400785{
Jamie Madill5547b382017-10-23 18:16:01 -0400786 return mDescriptorSets;
787}
788
789uint32_t ProgramVk::getDescriptorSetOffset() const
790{
791 return mDescriptorSetOffset;
792}
793
794void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
795{
796 if (mState.getSamplerBindings().empty() || !mDirtyTextures)
797 {
798 return;
799 }
800
801 VkDescriptorSet descriptorSet = mDescriptorSets.back();
802
803 // TODO(jmadill): Don't hard-code the texture limit.
804 ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
805 ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
806 uint32_t imageCount = 0;
807
808 const gl::State &glState = contextVk->getGLState();
809 const auto &completeTextures = glState.getCompleteTextureCache();
810
811 for (const auto &samplerBinding : mState.getSamplerBindings())
812 {
813 ASSERT(!samplerBinding.unreferenced);
814
815 // TODO(jmadill): Sampler arrays
816 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
817
818 GLuint textureUnit = samplerBinding.boundTextureUnits[0];
819 const gl::Texture *texture = completeTextures[textureUnit];
820
821 // TODO(jmadill): Incomplete textures handling.
822 ASSERT(texture);
823
Jamie Madille1f3ad42017-10-28 23:00:42 -0400824 TextureVk *textureVk = vk::GetImpl(texture);
Jamie Madill5547b382017-10-23 18:16:01 -0400825 const vk::Image &image = textureVk->getImage();
826
827 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
828
829 imageInfo.sampler = textureVk->getSampler().getHandle();
830 imageInfo.imageView = textureVk->getImageView().getHandle();
831 imageInfo.imageLayout = image.getCurrentLayout();
832
833 auto &writeInfo = writeDescriptorInfo[imageCount];
834
835 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
836 writeInfo.pNext = nullptr;
837 writeInfo.dstSet = descriptorSet;
838 writeInfo.dstBinding = imageCount;
839 writeInfo.dstArrayElement = 0;
840 writeInfo.descriptorCount = 1;
841 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
842 writeInfo.pImageInfo = &imageInfo;
843 writeInfo.pBufferInfo = nullptr;
844 writeInfo.pTexelBufferView = nullptr;
845
846 imageCount++;
847 }
848
849 VkDevice device = contextVk->getDevice();
850
851 ASSERT(imageCount > 0);
852 vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
853
854 mDirtyTextures = false;
855}
856
857void ProgramVk::invalidateTextures()
858{
859 mDirtyTextures = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400860}
861
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400862} // namespace rx