blob: c102ae97c1664e8e2fb95f70d6c5b7a1a6f19dfb [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
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500137ProgramVk::DefaultUniformBlock::~DefaultUniformBlock()
138{
139}
140
Jamie Madill76e471e2017-10-21 09:56:01 -0400141ProgramVk::ProgramVk(const gl::ProgramState &state)
Jamie Madill5547b382017-10-23 18:16:01 -0400142 : ProgramImpl(state), mDefaultUniformBlocks(), mDescriptorSetOffset(0), mDirtyTextures(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400143{
144}
145
146ProgramVk::~ProgramVk()
147{
148}
149
Jamie Madillc564c072017-06-01 12:45:42 -0400150void ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500151{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400152 VkDevice device = vk::GetImpl(contextImpl)->getDevice();
Jamie Madillc5143482017-10-15 20:20:06 -0400153 reset(device);
154}
Jamie Madill5deea722017-02-16 10:44:46 -0500155
Jamie Madillc5143482017-10-15 20:20:06 -0400156void ProgramVk::reset(VkDevice device)
157{
Jamie Madill76e471e2017-10-21 09:56:01 -0400158 for (auto &uniformBlock : mDefaultUniformBlocks)
159 {
160 uniformBlock.storage.memory.destroy(device);
161 uniformBlock.storage.buffer.destroy(device);
162 }
163
164 mEmptyUniformBlockStorage.memory.destroy(device);
165 mEmptyUniformBlockStorage.buffer.destroy(device);
166
167 for (auto &descriptorSetLayout : mDescriptorSetLayouts)
168 {
169 descriptorSetLayout.destroy(device);
170 }
171
Jamie Madill5deea722017-02-16 10:44:46 -0500172 mLinkedFragmentModule.destroy(device);
173 mLinkedVertexModule.destroy(device);
174 mPipelineLayout.destroy(device);
Jamie Madill76e471e2017-10-21 09:56:01 -0400175
176 // Descriptor Sets are pool allocated, so do not need to be explicitly freed.
Jamie Madill5547b382017-10-23 18:16:01 -0400177 mDescriptorSets.clear();
178 mDescriptorSetOffset = 0;
179 mDirtyTextures = false;
Jamie Madill5deea722017-02-16 10:44:46 -0500180}
181
Jamie Madill9cf9e872017-06-05 12:59:25 -0400182gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
183 gl::InfoLog &infoLog,
184 gl::BinaryInputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400185{
186 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500187 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400188}
189
Jamie Madill27a60632017-06-30 15:12:01 -0400190void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400191{
192 UNIMPLEMENTED();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400193}
194
195void ProgramVk::setBinaryRetrievableHint(bool retrievable)
196{
197 UNIMPLEMENTED();
198}
199
Yunchao He61afff12017-03-14 15:34:03 +0800200void ProgramVk::setSeparable(bool separable)
201{
202 UNIMPLEMENTED();
203}
204
Jamie Madill9cf9e872017-06-05 12:59:25 -0400205gl::LinkResult ProgramVk::link(const gl::Context *glContext,
Jamie Madillc9727f32017-11-07 12:37:07 -0500206 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400207 gl::InfoLog &infoLog)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400208{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400209 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madillc5143482017-10-15 20:20:06 -0400210 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500211 GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
Jamie Madillc5143482017-10-15 20:20:06 -0400212 VkDevice device = renderer->getDevice();
213
214 reset(device);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500215
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500216 std::vector<uint32_t> vertexCode;
217 std::vector<uint32_t> fragmentCode;
218 bool linkSuccess = false;
Jamie Madill4dd167f2017-11-09 13:08:31 -0500219 ANGLE_TRY_RESULT(
220 glslangWrapper->linkProgram(glContext, mState, resources, &vertexCode, &fragmentCode),
221 linkSuccess);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500222 if (!linkSuccess)
223 {
224 return false;
225 }
226
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500227 {
228 VkShaderModuleCreateInfo vertexShaderInfo;
229 vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
230 vertexShaderInfo.pNext = nullptr;
231 vertexShaderInfo.flags = 0;
232 vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
233 vertexShaderInfo.pCode = vertexCode.data();
Jamie Madillc5143482017-10-15 20:20:06 -0400234
235 ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500236 }
237
238 {
239 VkShaderModuleCreateInfo fragmentShaderInfo;
240 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
241 fragmentShaderInfo.pNext = nullptr;
242 fragmentShaderInfo.flags = 0;
243 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
244 fragmentShaderInfo.pCode = fragmentCode.data();
245
Jamie Madillc5143482017-10-15 20:20:06 -0400246 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500247 }
248
Jamie Madillc5143482017-10-15 20:20:06 -0400249 ANGLE_TRY(initPipelineLayout(contextVk));
Jamie Madill76e471e2017-10-21 09:56:01 -0400250 ANGLE_TRY(initDescriptorSets(contextVk));
251 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500252
253 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400254}
255
Jamie Madill76e471e2017-10-21 09:56:01 -0400256gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
257{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400258 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madill76e471e2017-10-21 09:56:01 -0400259 VkDevice device = contextVk->getDevice();
260
261 // Process vertex and fragment uniforms into std140 packing.
262 std::array<sh::BlockLayoutMap, 2> layoutMap;
263 std::array<size_t, 2> requiredBufferSize = {{0, 0}};
264
265 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
266 {
267 ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex),
268 &mDefaultUniformBlocks[shaderIndex].storage,
269 &layoutMap[shaderIndex],
270 &requiredBufferSize[shaderIndex]));
271 }
272
273 // Init the default block layout info.
274 const auto &locations = mState.getUniformLocations();
275 const auto &uniforms = mState.getUniforms();
276 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
277 {
278 std::array<sh::BlockMemberInfo, 2> layoutInfo;
279
280 const auto &location = locations[locationIndex];
281 if (location.used() && !location.ignored)
282 {
Jamie Madillde03e002017-10-21 14:04:20 -0400283 const auto &uniform = uniforms[location.index];
284
285 if (uniform.isSampler())
286 continue;
287
Jamie Madill76e471e2017-10-21 09:56:01 -0400288 std::string uniformName = uniform.name;
289 if (uniform.isArray())
290 {
Olli Etuaho1734e172017-10-27 15:30:27 +0300291 uniformName += ArrayString(location.arrayIndex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400292 }
293
294 bool found = false;
295
296 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
297 {
298 auto it = layoutMap[shaderIndex].find(uniformName);
299 if (it != layoutMap[shaderIndex].end())
300 {
301 found = true;
302 layoutInfo[shaderIndex] = it->second;
303 }
304 }
305
306 ASSERT(found);
307 }
308
309 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
310 {
311 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
312 }
313 }
314
315 bool anyDirty = false;
316 bool allDirty = true;
317
318 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
319 {
320 if (requiredBufferSize[shaderIndex] > 0)
321 {
322 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
323 requiredBufferSize[shaderIndex]))
324 {
325 return gl::OutOfMemory() << "Memory allocation failure.";
326 }
327 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
328 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
329
330 anyDirty = true;
331 }
332 else
333 {
334 allDirty = false;
335 }
336 }
337
338 if (anyDirty)
339 {
340 // Initialize the "empty" uniform block if necessary.
341 if (!allDirty)
342 {
343 VkBufferCreateInfo uniformBufferInfo;
344 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
345 uniformBufferInfo.pNext = nullptr;
346 uniformBufferInfo.flags = 0;
347 uniformBufferInfo.size = 1;
348 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
349 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
350 uniformBufferInfo.queueFamilyIndexCount = 0;
351 uniformBufferInfo.pQueueFamilyIndices = nullptr;
352
353 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
354
355 size_t requiredSize = 0;
356 ANGLE_TRY(AllocateBufferMemory(contextVk, 1, &mEmptyUniformBlockStorage.buffer,
357 &mEmptyUniformBlockStorage.memory, &requiredSize));
358 }
359
360 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
361 }
Jamie Madill5547b382017-10-23 18:16:01 -0400362 else
363 {
364 // If the program has no uniforms, note this in the offset.
365 mDescriptorSetOffset = 1;
366 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400367
368 return gl::NoError();
369}
370
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400371GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
372{
373 UNIMPLEMENTED();
374 return GLboolean();
375}
376
Jamie Madill76e471e2017-10-21 09:56:01 -0400377template <typename T>
378void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
379{
380 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
381 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
382
383 if (linkedUniform.type == entryPointType)
384 {
385 for (auto &uniformBlock : mDefaultUniformBlocks)
386 {
387 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
388 UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
389 &uniformBlock.uniformData);
390 }
391 }
392 else
393 {
394 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
395 UNIMPLEMENTED();
396 }
397}
398
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400399void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
400{
Jamie Madill76e471e2017-10-21 09:56:01 -0400401 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400402}
403
404void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
405{
Jamie Madill76e471e2017-10-21 09:56:01 -0400406 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400407}
408
409void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
410{
Jamie Madill76e471e2017-10-21 09:56:01 -0400411 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400412}
413
414void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
415{
Jamie Madill76e471e2017-10-21 09:56:01 -0400416 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400417}
418
419void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
420{
421 UNIMPLEMENTED();
422}
423
424void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
425{
426 UNIMPLEMENTED();
427}
428
429void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
430{
431 UNIMPLEMENTED();
432}
433
434void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
435{
436 UNIMPLEMENTED();
437}
438
439void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
440{
441 UNIMPLEMENTED();
442}
443
444void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
445{
446 UNIMPLEMENTED();
447}
448
449void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
450{
451 UNIMPLEMENTED();
452}
453
454void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
455{
456 UNIMPLEMENTED();
457}
458
459void ProgramVk::setUniformMatrix2fv(GLint location,
460 GLsizei count,
461 GLboolean transpose,
462 const GLfloat *value)
463{
464 UNIMPLEMENTED();
465}
466
467void ProgramVk::setUniformMatrix3fv(GLint location,
468 GLsizei count,
469 GLboolean transpose,
470 const GLfloat *value)
471{
472 UNIMPLEMENTED();
473}
474
475void ProgramVk::setUniformMatrix4fv(GLint location,
476 GLsizei count,
477 GLboolean transpose,
478 const GLfloat *value)
479{
480 UNIMPLEMENTED();
481}
482
483void ProgramVk::setUniformMatrix2x3fv(GLint location,
484 GLsizei count,
485 GLboolean transpose,
486 const GLfloat *value)
487{
488 UNIMPLEMENTED();
489}
490
491void ProgramVk::setUniformMatrix3x2fv(GLint location,
492 GLsizei count,
493 GLboolean transpose,
494 const GLfloat *value)
495{
496 UNIMPLEMENTED();
497}
498
499void ProgramVk::setUniformMatrix2x4fv(GLint location,
500 GLsizei count,
501 GLboolean transpose,
502 const GLfloat *value)
503{
504 UNIMPLEMENTED();
505}
506
507void ProgramVk::setUniformMatrix4x2fv(GLint location,
508 GLsizei count,
509 GLboolean transpose,
510 const GLfloat *value)
511{
512 UNIMPLEMENTED();
513}
514
515void ProgramVk::setUniformMatrix3x4fv(GLint location,
516 GLsizei count,
517 GLboolean transpose,
518 const GLfloat *value)
519{
520 UNIMPLEMENTED();
521}
522
523void ProgramVk::setUniformMatrix4x3fv(GLint location,
524 GLsizei count,
525 GLboolean transpose,
526 const GLfloat *value)
527{
528 UNIMPLEMENTED();
529}
530
531void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
532{
533 UNIMPLEMENTED();
534}
535
Sami Väisänen46eaa942016-06-29 10:26:37 +0300536void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
537 GLenum genMode,
538 GLint components,
539 const GLfloat *coeffs)
540{
541 UNIMPLEMENTED();
542}
543
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500544const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
545{
546 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
547 return mLinkedVertexModule;
548}
549
550const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
551{
552 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
553 return mLinkedFragmentModule;
554}
555
Jamie Madillc5143482017-10-15 20:20:06 -0400556const vk::PipelineLayout &ProgramVk::getPipelineLayout() const
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500557{
Jamie Madillc5143482017-10-15 20:20:06 -0400558 return mPipelineLayout;
559}
560
561vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
562{
563 ASSERT(!mPipelineLayout.valid());
564
565 VkDevice device = context->getDevice();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500566
Jamie Madill76e471e2017-10-21 09:56:01 -0400567 // Create two descriptor set layouts: one for default uniform info, and one for textures.
568 // Skip one or both if there are no uniforms.
569 VkDescriptorSetLayoutBinding uniformBindings[2];
570 uint32_t blockCount = 0;
571
572 {
573 auto &layoutBinding = uniformBindings[blockCount];
574
575 layoutBinding.binding = blockCount;
576 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
577 layoutBinding.descriptorCount = 1;
578 layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
579 layoutBinding.pImmutableSamplers = nullptr;
580
581 blockCount++;
582 }
583
584 {
585 auto &layoutBinding = uniformBindings[blockCount];
586
587 layoutBinding.binding = blockCount;
588 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
589 layoutBinding.descriptorCount = 1;
590 layoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
591 layoutBinding.pImmutableSamplers = nullptr;
592
593 blockCount++;
594 }
595
596 {
597 VkDescriptorSetLayoutCreateInfo uniformInfo;
598 uniformInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
599 uniformInfo.pNext = nullptr;
600 uniformInfo.flags = 0;
601 uniformInfo.bindingCount = blockCount;
602 uniformInfo.pBindings = uniformBindings;
603
604 vk::DescriptorSetLayout uniformLayout;
605 ANGLE_TRY(uniformLayout.init(device, uniformInfo));
606 mDescriptorSetLayouts.push_back(std::move(uniformLayout));
607 }
608
Jamie Madill5547b382017-10-23 18:16:01 -0400609 const auto &samplerBindings = mState.getSamplerBindings();
610
611 if (!samplerBindings.empty())
612 {
613 std::vector<VkDescriptorSetLayoutBinding> textureBindings;
614 uint32_t textureCount = 0;
615 const auto &uniforms = mState.getUniforms();
616 for (unsigned int uniformIndex : mState.getSamplerUniformRange())
617 {
618 const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
619 unsigned int samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformIndex);
620 const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
621
622 ASSERT(!samplerBinding.unreferenced);
623
624 VkDescriptorSetLayoutBinding layoutBinding;
625
626 uint32_t elementCount = samplerUniform.elementCount();
627
628 layoutBinding.binding = textureCount;
629 layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
630 layoutBinding.descriptorCount = elementCount;
631
632 layoutBinding.stageFlags = 0;
633 if (samplerUniform.vertexStaticUse)
634 {
635 layoutBinding.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
636 }
637 if (samplerUniform.fragmentStaticUse)
638 {
639 layoutBinding.stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
640 }
641
642 layoutBinding.pImmutableSamplers = nullptr;
643
644 textureCount += elementCount;
645
646 textureBindings.push_back(layoutBinding);
647 }
648
649 VkDescriptorSetLayoutCreateInfo textureInfo;
650 textureInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
651 textureInfo.pNext = nullptr;
652 textureInfo.flags = 0;
653 textureInfo.bindingCount = static_cast<uint32_t>(textureBindings.size());
654 textureInfo.pBindings = textureBindings.data();
655
656 vk::DescriptorSetLayout textureLayout;
657 ANGLE_TRY(textureLayout.init(device, textureInfo));
658 mDescriptorSetLayouts.push_back(std::move(textureLayout));
659
660 mDirtyTextures = true;
661 }
662
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500663 VkPipelineLayoutCreateInfo createInfo;
664 createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
665 createInfo.pNext = nullptr;
666 createInfo.flags = 0;
Jamie Madill76e471e2017-10-21 09:56:01 -0400667 createInfo.setLayoutCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
668 createInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500669 createInfo.pushConstantRangeCount = 0;
670 createInfo.pPushConstantRanges = nullptr;
671
Jamie Madillc5143482017-10-15 20:20:06 -0400672 ANGLE_TRY(mPipelineLayout.init(device, createInfo));
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500673
Jamie Madillc5143482017-10-15 20:20:06 -0400674 return vk::NoError();
Jamie Madilldf68a6f2017-01-13 17:29:53 -0500675}
676
Jamie Madill76e471e2017-10-21 09:56:01 -0400677vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
678{
Jamie Madill5547b382017-10-23 18:16:01 -0400679 ASSERT(mDescriptorSets.empty());
Jamie Madill76e471e2017-10-21 09:56:01 -0400680
681 VkDevice device = contextVk->getDevice();
682
683 // Write out to a new a descriptor set.
684 // TODO(jmadill): Handle descriptor set lifetime.
685 vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
686
Jamie Madill5547b382017-10-23 18:16:01 -0400687 uint32_t descriptorSetCount = static_cast<uint32_t>(mDescriptorSetLayouts.size());
Jamie Madill76e471e2017-10-21 09:56:01 -0400688
Jamie Madill5547b382017-10-23 18:16:01 -0400689 VkDescriptorSetAllocateInfo allocInfo;
690 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
691 allocInfo.pNext = nullptr;
692 allocInfo.descriptorPool = descriptorPool->getHandle();
693 allocInfo.descriptorSetCount = descriptorSetCount;
Jamie Madill76e471e2017-10-21 09:56:01 -0400694 allocInfo.pSetLayouts = mDescriptorSetLayouts[0].ptr();
695
Jamie Madill5547b382017-10-23 18:16:01 -0400696 mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
697 ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
Jamie Madill76e471e2017-10-21 09:56:01 -0400698 return vk::NoError();
699}
700
Jamie Madill54164b02017-08-28 15:17:37 -0400701void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
702{
703 UNIMPLEMENTED();
704}
705
706void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
707{
708 UNIMPLEMENTED();
709}
710
711void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
712{
713 UNIMPLEMENTED();
714}
715
Jamie Madill76e471e2017-10-21 09:56:01 -0400716vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
717{
718 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
719 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
720 {
721 return vk::NoError();
722 }
723
Jamie Madill5547b382017-10-23 18:16:01 -0400724 ASSERT(mDescriptorSetOffset == 0);
725
Jamie Madill76e471e2017-10-21 09:56:01 -0400726 VkDevice device = contextVk->getDevice();
727
728 // Update buffer memory by immediate mapping. This immediate update only works once.
729 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
730 for (auto &uniformBlock : mDefaultUniformBlocks)
731 {
732 if (uniformBlock.uniformsDirty)
733 {
734 ANGLE_TRY(SyncDefaultUniformBlock(device, &uniformBlock.storage.memory,
735 uniformBlock.uniformData));
736 uniformBlock.uniformsDirty = false;
737 }
738 }
739
740 return vk::NoError();
741}
742
743vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
744{
745 std::array<VkDescriptorBufferInfo, 2> descriptorBufferInfo;
746 std::array<VkWriteDescriptorSet, 2> writeDescriptorInfo;
747 uint32_t bufferCount = 0;
748
749 for (auto &uniformBlock : mDefaultUniformBlocks)
750 {
751 auto &bufferInfo = descriptorBufferInfo[bufferCount];
752
753 if (!uniformBlock.uniformData.empty())
754 {
755 bufferInfo.buffer = uniformBlock.storage.buffer.getHandle();
756 }
757 else
758 {
759 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
760 }
761
762 bufferInfo.offset = 0;
763 bufferInfo.range = VK_WHOLE_SIZE;
764
765 auto &writeInfo = writeDescriptorInfo[bufferCount];
766
767 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
768 writeInfo.pNext = nullptr;
Jamie Madill5547b382017-10-23 18:16:01 -0400769 writeInfo.dstSet = mDescriptorSets[0];
Jamie Madill76e471e2017-10-21 09:56:01 -0400770 writeInfo.dstBinding = bufferCount;
771 writeInfo.dstArrayElement = 0;
772 writeInfo.descriptorCount = 1;
773 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
774 writeInfo.pImageInfo = nullptr;
775 writeInfo.pBufferInfo = &bufferInfo;
776 writeInfo.pTexelBufferView = nullptr;
777
778 bufferCount++;
779 }
780
781 VkDevice device = contextVk->getDevice();
782
783 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
784
785 return vk::NoError();
786}
787
Jamie Madill5547b382017-10-23 18:16:01 -0400788const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
Jamie Madill76e471e2017-10-21 09:56:01 -0400789{
Jamie Madill5547b382017-10-23 18:16:01 -0400790 return mDescriptorSets;
791}
792
793uint32_t ProgramVk::getDescriptorSetOffset() const
794{
795 return mDescriptorSetOffset;
796}
797
798void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
799{
800 if (mState.getSamplerBindings().empty() || !mDirtyTextures)
801 {
802 return;
803 }
804
805 VkDescriptorSet descriptorSet = mDescriptorSets.back();
806
807 // TODO(jmadill): Don't hard-code the texture limit.
808 ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
809 ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
810 uint32_t imageCount = 0;
811
812 const gl::State &glState = contextVk->getGLState();
813 const auto &completeTextures = glState.getCompleteTextureCache();
814
815 for (const auto &samplerBinding : mState.getSamplerBindings())
816 {
817 ASSERT(!samplerBinding.unreferenced);
818
819 // TODO(jmadill): Sampler arrays
820 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
821
822 GLuint textureUnit = samplerBinding.boundTextureUnits[0];
823 const gl::Texture *texture = completeTextures[textureUnit];
824
825 // TODO(jmadill): Incomplete textures handling.
826 ASSERT(texture);
827
Jamie Madille1f3ad42017-10-28 23:00:42 -0400828 TextureVk *textureVk = vk::GetImpl(texture);
Jamie Madill5547b382017-10-23 18:16:01 -0400829 const vk::Image &image = textureVk->getImage();
830
831 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
832
833 imageInfo.sampler = textureVk->getSampler().getHandle();
834 imageInfo.imageView = textureVk->getImageView().getHandle();
835 imageInfo.imageLayout = image.getCurrentLayout();
836
837 auto &writeInfo = writeDescriptorInfo[imageCount];
838
839 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
840 writeInfo.pNext = nullptr;
841 writeInfo.dstSet = descriptorSet;
842 writeInfo.dstBinding = imageCount;
843 writeInfo.dstArrayElement = 0;
844 writeInfo.descriptorCount = 1;
845 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
846 writeInfo.pImageInfo = &imageInfo;
847 writeInfo.pBufferInfo = nullptr;
848 writeInfo.pTexelBufferView = nullptr;
849
850 imageCount++;
851 }
852
853 VkDevice device = contextVk->getDevice();
854
855 ASSERT(imageCount > 0);
856 vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
857
858 mDirtyTextures = false;
859}
860
861void ProgramVk::invalidateTextures()
862{
863 mDirtyTextures = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400864}
865
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400866} // namespace rx