blob: 341034f67b84f494d90c6e7b0483e8e5b2af15ef [file] [log] [blame]
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001//
2// Copyright 2016 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// ProgramVk.cpp:
7// Implements the class methods for ProgramVk.
8//
9
10#include "libANGLE/renderer/vulkan/ProgramVk.h"
11
12#include "common/debug.h"
Jamie Madill76e471e2017-10-21 09:56:01 -040013#include "common/utilities.h"
Jamie Madillc564c072017-06-01 12:45:42 -040014#include "libANGLE/Context.h"
Jamie Madill8ecf7f92017-01-13 17:29:52 -050015#include "libANGLE/renderer/vulkan/ContextVk.h"
16#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
17#include "libANGLE/renderer/vulkan/RendererVk.h"
Jamie Madill5547b382017-10-23 18:16:01 -040018#include "libANGLE/renderer/vulkan/TextureVk.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040019
20namespace rx
21{
22
Jamie Madill76e471e2017-10-21 09:56:01 -040023namespace
24{
25
26gl::Error InitDefaultUniformBlock(const gl::Context *context,
27 VkDevice device,
28 gl::Shader *shader,
29 vk::BufferAndMemory *storageOut,
30 sh::BlockLayoutMap *blockLayoutMapOut,
31 size_t *requiredSizeOut)
32{
33 const auto &uniforms = shader->getUniforms(context);
34
35 if (uniforms.empty())
36 {
37 *requiredSizeOut = 0;
38 return gl::NoError();
39 }
40
41 sh::Std140BlockEncoder blockEncoder;
Olli Etuaho3de27032017-11-30 12:16:47 +020042 sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
Jamie Madill76e471e2017-10-21 09:56:01 -040043
44 size_t blockSize = blockEncoder.getBlockSize();
45
46 // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
47 if (blockSize == 0)
48 {
49 *requiredSizeOut = 0;
50 return gl::NoError();
51 }
52
53 VkBufferCreateInfo uniformBufferInfo;
54 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
55 uniformBufferInfo.pNext = nullptr;
56 uniformBufferInfo.flags = 0;
57 uniformBufferInfo.size = blockSize;
58 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
59 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
60 uniformBufferInfo.queueFamilyIndexCount = 0;
61 uniformBufferInfo.pQueueFamilyIndices = nullptr;
62
63 ANGLE_TRY(storageOut->buffer.init(device, uniformBufferInfo));
64
Jamie Madill57dd97a2018-02-06 17:10:49 -050065 // Assume host vislble/coherent memory available.
66 VkMemoryPropertyFlags flags =
67 (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
68 ANGLE_TRY(AllocateBufferMemory(vk::GetImpl(context), flags, &storageOut->buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -040069 &storageOut->memory, requiredSizeOut));
70
71 return gl::NoError();
72}
73
74template <typename T>
75void UpdateDefaultUniformBlock(GLsizei count,
76 int componentCount,
77 const T *v,
78 const sh::BlockMemberInfo &layoutInfo,
79 angle::MemoryBuffer *uniformData)
80{
81 // Assume an offset of -1 means the block is unused.
82 if (layoutInfo.offset == -1)
83 {
84 return;
85 }
86
87 int elementSize = sizeof(T) * componentCount;
88 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
89 {
90 uint8_t *writePtr = uniformData->data() + layoutInfo.offset;
91 memcpy(writePtr, v, elementSize * count);
92 }
93 else
94 {
95 UNIMPLEMENTED();
96 }
97}
98
99vk::Error SyncDefaultUniformBlock(VkDevice device,
100 vk::DeviceMemory *bufferMemory,
101 const angle::MemoryBuffer &bufferData)
102{
103 ASSERT(bufferMemory->valid() && !bufferData.empty());
104 uint8_t *mapPointer = nullptr;
105 ANGLE_TRY(bufferMemory->map(device, 0, bufferData.size(), 0, &mapPointer));
106 memcpy(mapPointer, bufferData.data(), bufferData.size());
107 bufferMemory->unmap(device);
108 return vk::NoError();
109}
110
111enum ShaderIndex : uint32_t
112{
113 MinShaderIndex = 0,
114 VertexShader = MinShaderIndex,
115 FragmentShader = 1,
116 MaxShaderIndex = 2,
117};
118
119gl::Shader *GetShader(const gl::ProgramState &programState, uint32_t shaderIndex)
120{
121 switch (shaderIndex)
122 {
123 case VertexShader:
124 return programState.getAttachedVertexShader();
125 case FragmentShader:
126 return programState.getAttachedFragmentShader();
127 default:
128 UNREACHABLE();
129 return nullptr;
130 }
131}
132
133} // anonymous namespace
134
135ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
136 : storage(), uniformData(), uniformsDirty(false), uniformLayout()
137{
138}
139
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500140ProgramVk::DefaultUniformBlock::~DefaultUniformBlock()
141{
142}
143
Jamie Madill76e471e2017-10-21 09:56:01 -0400144ProgramVk::ProgramVk(const gl::ProgramState &state)
Jamie Madill8c3988c2017-12-21 14:44:56 -0500145 : ProgramImpl(state), mDefaultUniformBlocks(), mUsedDescriptorSetRange(), mDirtyTextures(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400146{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500147 mUsedDescriptorSetRange.invalidate();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400148}
149
150ProgramVk::~ProgramVk()
151{
152}
153
Jamie Madillc564c072017-06-01 12:45:42 -0400154void ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500155{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400156 VkDevice device = vk::GetImpl(contextImpl)->getDevice();
Jamie Madillc5143482017-10-15 20:20:06 -0400157 reset(device);
158}
Jamie Madill5deea722017-02-16 10:44:46 -0500159
Jamie Madillc5143482017-10-15 20:20:06 -0400160void ProgramVk::reset(VkDevice device)
161{
Jamie Madill76e471e2017-10-21 09:56:01 -0400162 for (auto &uniformBlock : mDefaultUniformBlocks)
163 {
164 uniformBlock.storage.memory.destroy(device);
165 uniformBlock.storage.buffer.destroy(device);
166 }
167
168 mEmptyUniformBlockStorage.memory.destroy(device);
169 mEmptyUniformBlockStorage.buffer.destroy(device);
170
Jamie Madill5deea722017-02-16 10:44:46 -0500171 mLinkedFragmentModule.destroy(device);
172 mLinkedVertexModule.destroy(device);
Jamie Madillf2f6d372018-01-10 21:37:23 -0500173 mVertexModuleSerial = Serial();
174 mFragmentModuleSerial = Serial();
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();
Jamie Madill8c3988c2017-12-21 14:44:56 -0500178 mUsedDescriptorSetRange.invalidate();
Jamie Madill5547b382017-10-23 18:16:01 -0400179 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 Madillf2f6d372018-01-10 21:37:23 -0500236 mVertexModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500237 }
238
239 {
240 VkShaderModuleCreateInfo fragmentShaderInfo;
241 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
242 fragmentShaderInfo.pNext = nullptr;
243 fragmentShaderInfo.flags = 0;
244 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
245 fragmentShaderInfo.pCode = fragmentCode.data();
246
Jamie Madillc5143482017-10-15 20:20:06 -0400247 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madillf2f6d372018-01-10 21:37:23 -0500248 mFragmentModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500249 }
250
Jamie Madill76e471e2017-10-21 09:56:01 -0400251 ANGLE_TRY(initDescriptorSets(contextVk));
252 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500253
Jamie Madill8c3988c2017-12-21 14:44:56 -0500254 if (!mState.getSamplerUniformRange().empty())
255 {
256 // Ensure the descriptor set range includes the textures at position 1.
257 mUsedDescriptorSetRange.extend(1);
258 mDirtyTextures = true;
259 }
260
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500261 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400262}
263
Jamie Madill76e471e2017-10-21 09:56:01 -0400264gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
265{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400266 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madill76e471e2017-10-21 09:56:01 -0400267 VkDevice device = contextVk->getDevice();
268
269 // Process vertex and fragment uniforms into std140 packing.
270 std::array<sh::BlockLayoutMap, 2> layoutMap;
271 std::array<size_t, 2> requiredBufferSize = {{0, 0}};
272
273 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
274 {
275 ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex),
276 &mDefaultUniformBlocks[shaderIndex].storage,
277 &layoutMap[shaderIndex],
278 &requiredBufferSize[shaderIndex]));
279 }
280
281 // Init the default block layout info.
282 const auto &locations = mState.getUniformLocations();
283 const auto &uniforms = mState.getUniforms();
284 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
285 {
286 std::array<sh::BlockMemberInfo, 2> layoutInfo;
287
288 const auto &location = locations[locationIndex];
289 if (location.used() && !location.ignored)
290 {
Jamie Madillde03e002017-10-21 14:04:20 -0400291 const auto &uniform = uniforms[location.index];
292
293 if (uniform.isSampler())
294 continue;
295
Jamie Madill76e471e2017-10-21 09:56:01 -0400296 std::string uniformName = uniform.name;
297 if (uniform.isArray())
298 {
Olli Etuaho1734e172017-10-27 15:30:27 +0300299 uniformName += ArrayString(location.arrayIndex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400300 }
301
302 bool found = false;
303
304 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
305 {
306 auto it = layoutMap[shaderIndex].find(uniformName);
307 if (it != layoutMap[shaderIndex].end())
308 {
309 found = true;
310 layoutInfo[shaderIndex] = it->second;
311 }
312 }
313
314 ASSERT(found);
315 }
316
317 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
318 {
319 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
320 }
321 }
322
323 bool anyDirty = false;
324 bool allDirty = true;
325
326 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
327 {
328 if (requiredBufferSize[shaderIndex] > 0)
329 {
330 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
331 requiredBufferSize[shaderIndex]))
332 {
333 return gl::OutOfMemory() << "Memory allocation failure.";
334 }
335 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
336 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
337
338 anyDirty = true;
339 }
340 else
341 {
342 allDirty = false;
343 }
344 }
345
346 if (anyDirty)
347 {
348 // Initialize the "empty" uniform block if necessary.
349 if (!allDirty)
350 {
351 VkBufferCreateInfo uniformBufferInfo;
352 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
353 uniformBufferInfo.pNext = nullptr;
354 uniformBufferInfo.flags = 0;
355 uniformBufferInfo.size = 1;
356 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
357 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
358 uniformBufferInfo.queueFamilyIndexCount = 0;
359 uniformBufferInfo.pQueueFamilyIndices = nullptr;
360
361 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
362
Jamie Madill57dd97a2018-02-06 17:10:49 -0500363 // Assume host vislble/coherent memory available.
364 VkMemoryPropertyFlags flags =
365 (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Jamie Madill76e471e2017-10-21 09:56:01 -0400366 size_t requiredSize = 0;
Jamie Madill57dd97a2018-02-06 17:10:49 -0500367 ANGLE_TRY(AllocateBufferMemory(contextVk, flags, &mEmptyUniformBlockStorage.buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -0400368 &mEmptyUniformBlockStorage.memory, &requiredSize));
369 }
370
371 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
Jamie Madill8c3988c2017-12-21 14:44:56 -0500372
373 // Ensure the descriptor set range includes the uniform buffers at position 0.
374 mUsedDescriptorSetRange.extend(0);
Jamie Madill5547b382017-10-23 18:16:01 -0400375 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400376
377 return gl::NoError();
378}
379
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400380GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
381{
382 UNIMPLEMENTED();
383 return GLboolean();
384}
385
Jamie Madill76e471e2017-10-21 09:56:01 -0400386template <typename T>
387void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
388{
389 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
390 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
391
392 if (linkedUniform.type == entryPointType)
393 {
394 for (auto &uniformBlock : mDefaultUniformBlocks)
395 {
396 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
397 UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
398 &uniformBlock.uniformData);
399 }
400 }
401 else
402 {
403 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
404 UNIMPLEMENTED();
405 }
406}
407
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400408void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
409{
Jamie Madill76e471e2017-10-21 09:56:01 -0400410 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400411}
412
413void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
414{
Jamie Madill76e471e2017-10-21 09:56:01 -0400415 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400416}
417
418void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
419{
Jamie Madill76e471e2017-10-21 09:56:01 -0400420 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400421}
422
423void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
424{
Jamie Madill76e471e2017-10-21 09:56:01 -0400425 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400426}
427
428void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
429{
430 UNIMPLEMENTED();
431}
432
433void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
434{
435 UNIMPLEMENTED();
436}
437
438void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
439{
440 UNIMPLEMENTED();
441}
442
443void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
444{
445 UNIMPLEMENTED();
446}
447
448void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
449{
450 UNIMPLEMENTED();
451}
452
453void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
454{
455 UNIMPLEMENTED();
456}
457
458void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
459{
460 UNIMPLEMENTED();
461}
462
463void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
464{
465 UNIMPLEMENTED();
466}
467
468void ProgramVk::setUniformMatrix2fv(GLint location,
469 GLsizei count,
470 GLboolean transpose,
471 const GLfloat *value)
472{
473 UNIMPLEMENTED();
474}
475
476void ProgramVk::setUniformMatrix3fv(GLint location,
477 GLsizei count,
478 GLboolean transpose,
479 const GLfloat *value)
480{
481 UNIMPLEMENTED();
482}
483
484void ProgramVk::setUniformMatrix4fv(GLint location,
485 GLsizei count,
486 GLboolean transpose,
487 const GLfloat *value)
488{
489 UNIMPLEMENTED();
490}
491
492void ProgramVk::setUniformMatrix2x3fv(GLint location,
493 GLsizei count,
494 GLboolean transpose,
495 const GLfloat *value)
496{
497 UNIMPLEMENTED();
498}
499
500void ProgramVk::setUniformMatrix3x2fv(GLint location,
501 GLsizei count,
502 GLboolean transpose,
503 const GLfloat *value)
504{
505 UNIMPLEMENTED();
506}
507
508void ProgramVk::setUniformMatrix2x4fv(GLint location,
509 GLsizei count,
510 GLboolean transpose,
511 const GLfloat *value)
512{
513 UNIMPLEMENTED();
514}
515
516void ProgramVk::setUniformMatrix4x2fv(GLint location,
517 GLsizei count,
518 GLboolean transpose,
519 const GLfloat *value)
520{
521 UNIMPLEMENTED();
522}
523
524void ProgramVk::setUniformMatrix3x4fv(GLint location,
525 GLsizei count,
526 GLboolean transpose,
527 const GLfloat *value)
528{
529 UNIMPLEMENTED();
530}
531
532void ProgramVk::setUniformMatrix4x3fv(GLint location,
533 GLsizei count,
534 GLboolean transpose,
535 const GLfloat *value)
536{
537 UNIMPLEMENTED();
538}
539
540void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
541{
542 UNIMPLEMENTED();
543}
544
Sami Väisänen46eaa942016-06-29 10:26:37 +0300545void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
546 GLenum genMode,
547 GLint components,
548 const GLfloat *coeffs)
549{
550 UNIMPLEMENTED();
551}
552
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500553const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
554{
555 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
556 return mLinkedVertexModule;
557}
558
Jamie Madillf2f6d372018-01-10 21:37:23 -0500559Serial ProgramVk::getVertexModuleSerial() const
560{
561 return mVertexModuleSerial;
562}
563
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500564const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
565{
566 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
567 return mLinkedFragmentModule;
568}
569
Jamie Madillf2f6d372018-01-10 21:37:23 -0500570Serial ProgramVk::getFragmentModuleSerial() const
571{
572 return mFragmentModuleSerial;
573}
574
Jamie Madill76e471e2017-10-21 09:56:01 -0400575vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
576{
Jamie Madill5547b382017-10-23 18:16:01 -0400577 ASSERT(mDescriptorSets.empty());
Jamie Madill76e471e2017-10-21 09:56:01 -0400578
Jamie Madill8c3988c2017-12-21 14:44:56 -0500579 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400580 VkDevice device = contextVk->getDevice();
581
582 // Write out to a new a descriptor set.
583 // TODO(jmadill): Handle descriptor set lifetime.
584 vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
585
Jamie Madill8c3988c2017-12-21 14:44:56 -0500586 const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
587
588 uint32_t descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
Jamie Madill76e471e2017-10-21 09:56:01 -0400589
Jamie Madill5547b382017-10-23 18:16:01 -0400590 VkDescriptorSetAllocateInfo allocInfo;
591 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
592 allocInfo.pNext = nullptr;
593 allocInfo.descriptorPool = descriptorPool->getHandle();
594 allocInfo.descriptorSetCount = descriptorSetCount;
Jamie Madill8c3988c2017-12-21 14:44:56 -0500595 allocInfo.pSetLayouts = descriptorSetLayouts[0].ptr();
Jamie Madill76e471e2017-10-21 09:56:01 -0400596
Jamie Madill5547b382017-10-23 18:16:01 -0400597 mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
598 ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
Jamie Madill76e471e2017-10-21 09:56:01 -0400599 return vk::NoError();
600}
601
Jamie Madill54164b02017-08-28 15:17:37 -0400602void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
603{
604 UNIMPLEMENTED();
605}
606
607void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
608{
609 UNIMPLEMENTED();
610}
611
612void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
613{
614 UNIMPLEMENTED();
615}
616
Jamie Madill76e471e2017-10-21 09:56:01 -0400617vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
618{
619 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
620 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
621 {
622 return vk::NoError();
623 }
624
Jamie Madill8c3988c2017-12-21 14:44:56 -0500625 ASSERT(mUsedDescriptorSetRange.contains(0));
Jamie Madill5547b382017-10-23 18:16:01 -0400626
Jamie Madill76e471e2017-10-21 09:56:01 -0400627 VkDevice device = contextVk->getDevice();
628
629 // Update buffer memory by immediate mapping. This immediate update only works once.
630 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
631 for (auto &uniformBlock : mDefaultUniformBlocks)
632 {
633 if (uniformBlock.uniformsDirty)
634 {
635 ANGLE_TRY(SyncDefaultUniformBlock(device, &uniformBlock.storage.memory,
636 uniformBlock.uniformData));
637 uniformBlock.uniformsDirty = false;
638 }
639 }
640
641 return vk::NoError();
642}
643
644vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
645{
646 std::array<VkDescriptorBufferInfo, 2> descriptorBufferInfo;
647 std::array<VkWriteDescriptorSet, 2> writeDescriptorInfo;
648 uint32_t bufferCount = 0;
649
650 for (auto &uniformBlock : mDefaultUniformBlocks)
651 {
652 auto &bufferInfo = descriptorBufferInfo[bufferCount];
653
654 if (!uniformBlock.uniformData.empty())
655 {
656 bufferInfo.buffer = uniformBlock.storage.buffer.getHandle();
657 }
658 else
659 {
660 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
661 }
662
663 bufferInfo.offset = 0;
664 bufferInfo.range = VK_WHOLE_SIZE;
665
666 auto &writeInfo = writeDescriptorInfo[bufferCount];
667
668 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
669 writeInfo.pNext = nullptr;
Jamie Madill5547b382017-10-23 18:16:01 -0400670 writeInfo.dstSet = mDescriptorSets[0];
Jamie Madill76e471e2017-10-21 09:56:01 -0400671 writeInfo.dstBinding = bufferCount;
672 writeInfo.dstArrayElement = 0;
673 writeInfo.descriptorCount = 1;
674 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
675 writeInfo.pImageInfo = nullptr;
676 writeInfo.pBufferInfo = &bufferInfo;
677 writeInfo.pTexelBufferView = nullptr;
678
679 bufferCount++;
680 }
681
682 VkDevice device = contextVk->getDevice();
683
684 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
685
686 return vk::NoError();
687}
688
Jamie Madill5547b382017-10-23 18:16:01 -0400689const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
Jamie Madill76e471e2017-10-21 09:56:01 -0400690{
Jamie Madill5547b382017-10-23 18:16:01 -0400691 return mDescriptorSets;
692}
693
Jamie Madill8c3988c2017-12-21 14:44:56 -0500694const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
Jamie Madill5547b382017-10-23 18:16:01 -0400695{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500696 return mUsedDescriptorSetRange;
Jamie Madill5547b382017-10-23 18:16:01 -0400697}
698
699void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
700{
701 if (mState.getSamplerBindings().empty() || !mDirtyTextures)
702 {
703 return;
704 }
705
Jamie Madill8c3988c2017-12-21 14:44:56 -0500706 ASSERT(mUsedDescriptorSetRange.contains(1));
707 VkDescriptorSet descriptorSet = mDescriptorSets[1];
Jamie Madill5547b382017-10-23 18:16:01 -0400708
709 // TODO(jmadill): Don't hard-code the texture limit.
710 ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
711 ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
712 uint32_t imageCount = 0;
713
714 const gl::State &glState = contextVk->getGLState();
715 const auto &completeTextures = glState.getCompleteTextureCache();
716
717 for (const auto &samplerBinding : mState.getSamplerBindings())
718 {
719 ASSERT(!samplerBinding.unreferenced);
720
721 // TODO(jmadill): Sampler arrays
722 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
723
724 GLuint textureUnit = samplerBinding.boundTextureUnits[0];
725 const gl::Texture *texture = completeTextures[textureUnit];
726
727 // TODO(jmadill): Incomplete textures handling.
728 ASSERT(texture);
729
Jamie Madille1f3ad42017-10-28 23:00:42 -0400730 TextureVk *textureVk = vk::GetImpl(texture);
Jamie Madill5547b382017-10-23 18:16:01 -0400731 const vk::Image &image = textureVk->getImage();
732
733 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
734
735 imageInfo.sampler = textureVk->getSampler().getHandle();
736 imageInfo.imageView = textureVk->getImageView().getHandle();
737 imageInfo.imageLayout = image.getCurrentLayout();
738
739 auto &writeInfo = writeDescriptorInfo[imageCount];
740
741 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
742 writeInfo.pNext = nullptr;
743 writeInfo.dstSet = descriptorSet;
744 writeInfo.dstBinding = imageCount;
745 writeInfo.dstArrayElement = 0;
746 writeInfo.descriptorCount = 1;
747 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
748 writeInfo.pImageInfo = &imageInfo;
749 writeInfo.pBufferInfo = nullptr;
750 writeInfo.pTexelBufferView = nullptr;
751
752 imageCount++;
753 }
754
755 VkDevice device = contextVk->getDevice();
756
757 ASSERT(imageCount > 0);
758 vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
759
760 mDirtyTextures = false;
761}
762
763void ProgramVk::invalidateTextures()
764{
765 mDirtyTextures = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400766}
767
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400768} // namespace rx