blob: 9e15ee7a96fa0abea9a3ee7b81af29d7cbc2d5b7 [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 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 Madill8c3988c2017-12-21 14:44:56 -0500142 : ProgramImpl(state), mDefaultUniformBlocks(), mUsedDescriptorSetRange(), mDirtyTextures(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400143{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500144 mUsedDescriptorSetRange.invalidate();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400145}
146
147ProgramVk::~ProgramVk()
148{
149}
150
Jamie Madillc564c072017-06-01 12:45:42 -0400151void ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500152{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400153 VkDevice device = vk::GetImpl(contextImpl)->getDevice();
Jamie Madillc5143482017-10-15 20:20:06 -0400154 reset(device);
155}
Jamie Madill5deea722017-02-16 10:44:46 -0500156
Jamie Madillc5143482017-10-15 20:20:06 -0400157void ProgramVk::reset(VkDevice device)
158{
Jamie Madill76e471e2017-10-21 09:56:01 -0400159 for (auto &uniformBlock : mDefaultUniformBlocks)
160 {
161 uniformBlock.storage.memory.destroy(device);
162 uniformBlock.storage.buffer.destroy(device);
163 }
164
165 mEmptyUniformBlockStorage.memory.destroy(device);
166 mEmptyUniformBlockStorage.buffer.destroy(device);
167
Jamie Madill5deea722017-02-16 10:44:46 -0500168 mLinkedFragmentModule.destroy(device);
169 mLinkedVertexModule.destroy(device);
Jamie Madill76e471e2017-10-21 09:56:01 -0400170
171 // Descriptor Sets are pool allocated, so do not need to be explicitly freed.
Jamie Madill5547b382017-10-23 18:16:01 -0400172 mDescriptorSets.clear();
Jamie Madill8c3988c2017-12-21 14:44:56 -0500173 mUsedDescriptorSetRange.invalidate();
Jamie Madill5547b382017-10-23 18:16:01 -0400174 mDirtyTextures = false;
Jamie Madill5deea722017-02-16 10:44:46 -0500175}
176
Jamie Madill9cf9e872017-06-05 12:59:25 -0400177gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
178 gl::InfoLog &infoLog,
179 gl::BinaryInputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400180{
181 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500182 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400183}
184
Jamie Madill27a60632017-06-30 15:12:01 -0400185void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400186{
187 UNIMPLEMENTED();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400188}
189
190void ProgramVk::setBinaryRetrievableHint(bool retrievable)
191{
192 UNIMPLEMENTED();
193}
194
Yunchao He61afff12017-03-14 15:34:03 +0800195void ProgramVk::setSeparable(bool separable)
196{
197 UNIMPLEMENTED();
198}
199
Jamie Madill9cf9e872017-06-05 12:59:25 -0400200gl::LinkResult ProgramVk::link(const gl::Context *glContext,
Jamie Madillc9727f32017-11-07 12:37:07 -0500201 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400202 gl::InfoLog &infoLog)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400203{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400204 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madillc5143482017-10-15 20:20:06 -0400205 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500206 GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
Jamie Madillc5143482017-10-15 20:20:06 -0400207 VkDevice device = renderer->getDevice();
208
209 reset(device);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500210
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500211 std::vector<uint32_t> vertexCode;
212 std::vector<uint32_t> fragmentCode;
213 bool linkSuccess = false;
Jamie Madill4dd167f2017-11-09 13:08:31 -0500214 ANGLE_TRY_RESULT(
215 glslangWrapper->linkProgram(glContext, mState, resources, &vertexCode, &fragmentCode),
216 linkSuccess);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500217 if (!linkSuccess)
218 {
219 return false;
220 }
221
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500222 {
223 VkShaderModuleCreateInfo vertexShaderInfo;
224 vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
225 vertexShaderInfo.pNext = nullptr;
226 vertexShaderInfo.flags = 0;
227 vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
228 vertexShaderInfo.pCode = vertexCode.data();
Jamie Madillc5143482017-10-15 20:20:06 -0400229
230 ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500231 }
232
233 {
234 VkShaderModuleCreateInfo fragmentShaderInfo;
235 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
236 fragmentShaderInfo.pNext = nullptr;
237 fragmentShaderInfo.flags = 0;
238 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
239 fragmentShaderInfo.pCode = fragmentCode.data();
240
Jamie Madillc5143482017-10-15 20:20:06 -0400241 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500242 }
243
Jamie Madill76e471e2017-10-21 09:56:01 -0400244 ANGLE_TRY(initDescriptorSets(contextVk));
245 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500246
Jamie Madill8c3988c2017-12-21 14:44:56 -0500247 if (!mState.getSamplerUniformRange().empty())
248 {
249 // Ensure the descriptor set range includes the textures at position 1.
250 mUsedDescriptorSetRange.extend(1);
251 mDirtyTextures = true;
252 }
253
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500254 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400255}
256
Jamie Madill76e471e2017-10-21 09:56:01 -0400257gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
258{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400259 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madill76e471e2017-10-21 09:56:01 -0400260 VkDevice device = contextVk->getDevice();
261
262 // Process vertex and fragment uniforms into std140 packing.
263 std::array<sh::BlockLayoutMap, 2> layoutMap;
264 std::array<size_t, 2> requiredBufferSize = {{0, 0}};
265
266 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
267 {
268 ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex),
269 &mDefaultUniformBlocks[shaderIndex].storage,
270 &layoutMap[shaderIndex],
271 &requiredBufferSize[shaderIndex]));
272 }
273
274 // Init the default block layout info.
275 const auto &locations = mState.getUniformLocations();
276 const auto &uniforms = mState.getUniforms();
277 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
278 {
279 std::array<sh::BlockMemberInfo, 2> layoutInfo;
280
281 const auto &location = locations[locationIndex];
282 if (location.used() && !location.ignored)
283 {
Jamie Madillde03e002017-10-21 14:04:20 -0400284 const auto &uniform = uniforms[location.index];
285
286 if (uniform.isSampler())
287 continue;
288
Jamie Madill76e471e2017-10-21 09:56:01 -0400289 std::string uniformName = uniform.name;
290 if (uniform.isArray())
291 {
Olli Etuaho1734e172017-10-27 15:30:27 +0300292 uniformName += ArrayString(location.arrayIndex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400293 }
294
295 bool found = false;
296
297 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
298 {
299 auto it = layoutMap[shaderIndex].find(uniformName);
300 if (it != layoutMap[shaderIndex].end())
301 {
302 found = true;
303 layoutInfo[shaderIndex] = it->second;
304 }
305 }
306
307 ASSERT(found);
308 }
309
310 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
311 {
312 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
313 }
314 }
315
316 bool anyDirty = false;
317 bool allDirty = true;
318
319 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
320 {
321 if (requiredBufferSize[shaderIndex] > 0)
322 {
323 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
324 requiredBufferSize[shaderIndex]))
325 {
326 return gl::OutOfMemory() << "Memory allocation failure.";
327 }
328 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
329 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
330
331 anyDirty = true;
332 }
333 else
334 {
335 allDirty = false;
336 }
337 }
338
339 if (anyDirty)
340 {
341 // Initialize the "empty" uniform block if necessary.
342 if (!allDirty)
343 {
344 VkBufferCreateInfo uniformBufferInfo;
345 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
346 uniformBufferInfo.pNext = nullptr;
347 uniformBufferInfo.flags = 0;
348 uniformBufferInfo.size = 1;
349 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
350 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
351 uniformBufferInfo.queueFamilyIndexCount = 0;
352 uniformBufferInfo.pQueueFamilyIndices = nullptr;
353
354 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
355
356 size_t requiredSize = 0;
357 ANGLE_TRY(AllocateBufferMemory(contextVk, 1, &mEmptyUniformBlockStorage.buffer,
358 &mEmptyUniformBlockStorage.memory, &requiredSize));
359 }
360
361 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
Jamie Madill8c3988c2017-12-21 14:44:56 -0500362
363 // Ensure the descriptor set range includes the uniform buffers at position 0.
364 mUsedDescriptorSetRange.extend(0);
Jamie Madill5547b382017-10-23 18:16:01 -0400365 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400366
367 return gl::NoError();
368}
369
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400370GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
371{
372 UNIMPLEMENTED();
373 return GLboolean();
374}
375
Jamie Madill76e471e2017-10-21 09:56:01 -0400376template <typename T>
377void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
378{
379 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
380 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
381
382 if (linkedUniform.type == entryPointType)
383 {
384 for (auto &uniformBlock : mDefaultUniformBlocks)
385 {
386 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
387 UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
388 &uniformBlock.uniformData);
389 }
390 }
391 else
392 {
393 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
394 UNIMPLEMENTED();
395 }
396}
397
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400398void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
399{
Jamie Madill76e471e2017-10-21 09:56:01 -0400400 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400401}
402
403void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
404{
Jamie Madill76e471e2017-10-21 09:56:01 -0400405 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400406}
407
408void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
409{
Jamie Madill76e471e2017-10-21 09:56:01 -0400410 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400411}
412
413void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
414{
Jamie Madill76e471e2017-10-21 09:56:01 -0400415 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400416}
417
418void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
419{
420 UNIMPLEMENTED();
421}
422
423void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
424{
425 UNIMPLEMENTED();
426}
427
428void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
429{
430 UNIMPLEMENTED();
431}
432
433void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
434{
435 UNIMPLEMENTED();
436}
437
438void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
439{
440 UNIMPLEMENTED();
441}
442
443void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
444{
445 UNIMPLEMENTED();
446}
447
448void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
449{
450 UNIMPLEMENTED();
451}
452
453void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
454{
455 UNIMPLEMENTED();
456}
457
458void ProgramVk::setUniformMatrix2fv(GLint location,
459 GLsizei count,
460 GLboolean transpose,
461 const GLfloat *value)
462{
463 UNIMPLEMENTED();
464}
465
466void ProgramVk::setUniformMatrix3fv(GLint location,
467 GLsizei count,
468 GLboolean transpose,
469 const GLfloat *value)
470{
471 UNIMPLEMENTED();
472}
473
474void ProgramVk::setUniformMatrix4fv(GLint location,
475 GLsizei count,
476 GLboolean transpose,
477 const GLfloat *value)
478{
479 UNIMPLEMENTED();
480}
481
482void ProgramVk::setUniformMatrix2x3fv(GLint location,
483 GLsizei count,
484 GLboolean transpose,
485 const GLfloat *value)
486{
487 UNIMPLEMENTED();
488}
489
490void ProgramVk::setUniformMatrix3x2fv(GLint location,
491 GLsizei count,
492 GLboolean transpose,
493 const GLfloat *value)
494{
495 UNIMPLEMENTED();
496}
497
498void ProgramVk::setUniformMatrix2x4fv(GLint location,
499 GLsizei count,
500 GLboolean transpose,
501 const GLfloat *value)
502{
503 UNIMPLEMENTED();
504}
505
506void ProgramVk::setUniformMatrix4x2fv(GLint location,
507 GLsizei count,
508 GLboolean transpose,
509 const GLfloat *value)
510{
511 UNIMPLEMENTED();
512}
513
514void ProgramVk::setUniformMatrix3x4fv(GLint location,
515 GLsizei count,
516 GLboolean transpose,
517 const GLfloat *value)
518{
519 UNIMPLEMENTED();
520}
521
522void ProgramVk::setUniformMatrix4x3fv(GLint location,
523 GLsizei count,
524 GLboolean transpose,
525 const GLfloat *value)
526{
527 UNIMPLEMENTED();
528}
529
530void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
531{
532 UNIMPLEMENTED();
533}
534
Sami Väisänen46eaa942016-06-29 10:26:37 +0300535void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
536 GLenum genMode,
537 GLint components,
538 const GLfloat *coeffs)
539{
540 UNIMPLEMENTED();
541}
542
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500543const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
544{
545 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
546 return mLinkedVertexModule;
547}
548
549const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
550{
551 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
552 return mLinkedFragmentModule;
553}
554
Jamie Madill76e471e2017-10-21 09:56:01 -0400555vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
556{
Jamie Madill5547b382017-10-23 18:16:01 -0400557 ASSERT(mDescriptorSets.empty());
Jamie Madill76e471e2017-10-21 09:56:01 -0400558
Jamie Madill8c3988c2017-12-21 14:44:56 -0500559 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400560 VkDevice device = contextVk->getDevice();
561
562 // Write out to a new a descriptor set.
563 // TODO(jmadill): Handle descriptor set lifetime.
564 vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
565
Jamie Madill8c3988c2017-12-21 14:44:56 -0500566 const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
567
568 uint32_t descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
Jamie Madill76e471e2017-10-21 09:56:01 -0400569
Jamie Madill5547b382017-10-23 18:16:01 -0400570 VkDescriptorSetAllocateInfo allocInfo;
571 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
572 allocInfo.pNext = nullptr;
573 allocInfo.descriptorPool = descriptorPool->getHandle();
574 allocInfo.descriptorSetCount = descriptorSetCount;
Jamie Madill8c3988c2017-12-21 14:44:56 -0500575 allocInfo.pSetLayouts = descriptorSetLayouts[0].ptr();
Jamie Madill76e471e2017-10-21 09:56:01 -0400576
Jamie Madill5547b382017-10-23 18:16:01 -0400577 mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
578 ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
Jamie Madill76e471e2017-10-21 09:56:01 -0400579 return vk::NoError();
580}
581
Jamie Madill54164b02017-08-28 15:17:37 -0400582void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
583{
584 UNIMPLEMENTED();
585}
586
587void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
588{
589 UNIMPLEMENTED();
590}
591
592void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
593{
594 UNIMPLEMENTED();
595}
596
Jamie Madill76e471e2017-10-21 09:56:01 -0400597vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
598{
599 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
600 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
601 {
602 return vk::NoError();
603 }
604
Jamie Madill8c3988c2017-12-21 14:44:56 -0500605 ASSERT(mUsedDescriptorSetRange.contains(0));
Jamie Madill5547b382017-10-23 18:16:01 -0400606
Jamie Madill76e471e2017-10-21 09:56:01 -0400607 VkDevice device = contextVk->getDevice();
608
609 // Update buffer memory by immediate mapping. This immediate update only works once.
610 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
611 for (auto &uniformBlock : mDefaultUniformBlocks)
612 {
613 if (uniformBlock.uniformsDirty)
614 {
615 ANGLE_TRY(SyncDefaultUniformBlock(device, &uniformBlock.storage.memory,
616 uniformBlock.uniformData));
617 uniformBlock.uniformsDirty = false;
618 }
619 }
620
621 return vk::NoError();
622}
623
624vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
625{
626 std::array<VkDescriptorBufferInfo, 2> descriptorBufferInfo;
627 std::array<VkWriteDescriptorSet, 2> writeDescriptorInfo;
628 uint32_t bufferCount = 0;
629
630 for (auto &uniformBlock : mDefaultUniformBlocks)
631 {
632 auto &bufferInfo = descriptorBufferInfo[bufferCount];
633
634 if (!uniformBlock.uniformData.empty())
635 {
636 bufferInfo.buffer = uniformBlock.storage.buffer.getHandle();
637 }
638 else
639 {
640 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
641 }
642
643 bufferInfo.offset = 0;
644 bufferInfo.range = VK_WHOLE_SIZE;
645
646 auto &writeInfo = writeDescriptorInfo[bufferCount];
647
648 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
649 writeInfo.pNext = nullptr;
Jamie Madill5547b382017-10-23 18:16:01 -0400650 writeInfo.dstSet = mDescriptorSets[0];
Jamie Madill76e471e2017-10-21 09:56:01 -0400651 writeInfo.dstBinding = bufferCount;
652 writeInfo.dstArrayElement = 0;
653 writeInfo.descriptorCount = 1;
654 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
655 writeInfo.pImageInfo = nullptr;
656 writeInfo.pBufferInfo = &bufferInfo;
657 writeInfo.pTexelBufferView = nullptr;
658
659 bufferCount++;
660 }
661
662 VkDevice device = contextVk->getDevice();
663
664 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
665
666 return vk::NoError();
667}
668
Jamie Madill5547b382017-10-23 18:16:01 -0400669const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
Jamie Madill76e471e2017-10-21 09:56:01 -0400670{
Jamie Madill5547b382017-10-23 18:16:01 -0400671 return mDescriptorSets;
672}
673
Jamie Madill8c3988c2017-12-21 14:44:56 -0500674const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
Jamie Madill5547b382017-10-23 18:16:01 -0400675{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500676 return mUsedDescriptorSetRange;
Jamie Madill5547b382017-10-23 18:16:01 -0400677}
678
679void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
680{
681 if (mState.getSamplerBindings().empty() || !mDirtyTextures)
682 {
683 return;
684 }
685
Jamie Madill8c3988c2017-12-21 14:44:56 -0500686 ASSERT(mUsedDescriptorSetRange.contains(1));
687 VkDescriptorSet descriptorSet = mDescriptorSets[1];
Jamie Madill5547b382017-10-23 18:16:01 -0400688
689 // TODO(jmadill): Don't hard-code the texture limit.
690 ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
691 ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
692 uint32_t imageCount = 0;
693
694 const gl::State &glState = contextVk->getGLState();
695 const auto &completeTextures = glState.getCompleteTextureCache();
696
697 for (const auto &samplerBinding : mState.getSamplerBindings())
698 {
699 ASSERT(!samplerBinding.unreferenced);
700
701 // TODO(jmadill): Sampler arrays
702 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
703
704 GLuint textureUnit = samplerBinding.boundTextureUnits[0];
705 const gl::Texture *texture = completeTextures[textureUnit];
706
707 // TODO(jmadill): Incomplete textures handling.
708 ASSERT(texture);
709
Jamie Madille1f3ad42017-10-28 23:00:42 -0400710 TextureVk *textureVk = vk::GetImpl(texture);
Jamie Madill5547b382017-10-23 18:16:01 -0400711 const vk::Image &image = textureVk->getImage();
712
713 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
714
715 imageInfo.sampler = textureVk->getSampler().getHandle();
716 imageInfo.imageView = textureVk->getImageView().getHandle();
717 imageInfo.imageLayout = image.getCurrentLayout();
718
719 auto &writeInfo = writeDescriptorInfo[imageCount];
720
721 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
722 writeInfo.pNext = nullptr;
723 writeInfo.dstSet = descriptorSet;
724 writeInfo.dstBinding = imageCount;
725 writeInfo.dstArrayElement = 0;
726 writeInfo.descriptorCount = 1;
727 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
728 writeInfo.pImageInfo = &imageInfo;
729 writeInfo.pBufferInfo = nullptr;
730 writeInfo.pTexelBufferView = nullptr;
731
732 imageCount++;
733 }
734
735 VkDevice device = contextVk->getDevice();
736
737 ASSERT(imageCount > 0);
738 vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
739
740 mDirtyTextures = false;
741}
742
743void ProgramVk::invalidateTextures()
744{
745 mDirtyTextures = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400746}
747
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400748} // namespace rx