blob: eb19bfeb9a45c11d4419d85723a7ae9f6ba7c68c [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"
Luc Ferrondaedf4d2018-03-16 09:28:53 -040016#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
Jamie Madill8ecf7f92017-01-13 17:29:52 -050017#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
18#include "libANGLE/renderer/vulkan/RendererVk.h"
Jamie Madill5547b382017-10-23 18:16:01 -040019#include "libANGLE/renderer/vulkan/TextureVk.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040020
21namespace rx
22{
23
Jamie Madill76e471e2017-10-21 09:56:01 -040024namespace
25{
26
27gl::Error InitDefaultUniformBlock(const gl::Context *context,
28 VkDevice device,
29 gl::Shader *shader,
30 vk::BufferAndMemory *storageOut,
31 sh::BlockLayoutMap *blockLayoutMapOut,
32 size_t *requiredSizeOut)
33{
34 const auto &uniforms = shader->getUniforms(context);
35
36 if (uniforms.empty())
37 {
38 *requiredSizeOut = 0;
39 return gl::NoError();
40 }
41
42 sh::Std140BlockEncoder blockEncoder;
Olli Etuaho3de27032017-11-30 12:16:47 +020043 sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
Jamie Madill76e471e2017-10-21 09:56:01 -040044
45 size_t blockSize = blockEncoder.getBlockSize();
46
47 // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
48 if (blockSize == 0)
49 {
50 *requiredSizeOut = 0;
51 return gl::NoError();
52 }
53
54 VkBufferCreateInfo uniformBufferInfo;
55 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
56 uniformBufferInfo.pNext = nullptr;
57 uniformBufferInfo.flags = 0;
58 uniformBufferInfo.size = blockSize;
59 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
60 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
61 uniformBufferInfo.queueFamilyIndexCount = 0;
62 uniformBufferInfo.pQueueFamilyIndices = nullptr;
63
64 ANGLE_TRY(storageOut->buffer.init(device, uniformBufferInfo));
65
Jamie Madill57dd97a2018-02-06 17:10:49 -050066 // Assume host vislble/coherent memory available.
67 VkMemoryPropertyFlags flags =
68 (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Jamie Madill57fbfd82018-02-14 12:45:34 -050069
70 ContextVk *contextVk = vk::GetImpl(context);
71
72 ANGLE_TRY(AllocateBufferMemory(contextVk->getRenderer(), flags, &storageOut->buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -040073 &storageOut->memory, requiredSizeOut));
74
75 return gl::NoError();
76}
77
78template <typename T>
79void UpdateDefaultUniformBlock(GLsizei count,
80 int componentCount,
81 const T *v,
82 const sh::BlockMemberInfo &layoutInfo,
83 angle::MemoryBuffer *uniformData)
84{
Jamie Madill76e471e2017-10-21 09:56:01 -040085 int elementSize = sizeof(T) * componentCount;
86 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
87 {
88 uint8_t *writePtr = uniformData->data() + layoutInfo.offset;
89 memcpy(writePtr, v, elementSize * count);
90 }
91 else
92 {
93 UNIMPLEMENTED();
94 }
95}
96
Luc Ferron7cec3352018-03-13 13:29:34 -040097template <typename T>
98void ReadFromDefaultUniformBlock(int componentCount,
99 T *dst,
100 const sh::BlockMemberInfo &layoutInfo,
101 const angle::MemoryBuffer *uniformData)
102{
103 ASSERT(layoutInfo.offset != -1);
104
105 int elementSize = sizeof(T) * componentCount;
106 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
107 {
108 const uint8_t *readPtr = uniformData->data() + layoutInfo.offset;
109 memcpy(dst, readPtr, elementSize);
110 }
111 else
112 {
113 UNIMPLEMENTED();
114 }
115}
116
Jamie Madill76e471e2017-10-21 09:56:01 -0400117vk::Error SyncDefaultUniformBlock(VkDevice device,
118 vk::DeviceMemory *bufferMemory,
119 const angle::MemoryBuffer &bufferData)
120{
121 ASSERT(bufferMemory->valid() && !bufferData.empty());
122 uint8_t *mapPointer = nullptr;
123 ANGLE_TRY(bufferMemory->map(device, 0, bufferData.size(), 0, &mapPointer));
124 memcpy(mapPointer, bufferData.data(), bufferData.size());
125 bufferMemory->unmap(device);
126 return vk::NoError();
127}
128
Jiawei Shao385b3e02018-03-21 09:43:28 +0800129// TODO(jiawei.shao@intel.com): Fully remove this enum by gl::ShaderType. (BUG=angleproject:2169)
Jamie Madill76e471e2017-10-21 09:56:01 -0400130enum ShaderIndex : uint32_t
131{
132 MinShaderIndex = 0,
133 VertexShader = MinShaderIndex,
134 FragmentShader = 1,
135 MaxShaderIndex = 2,
136};
137
138gl::Shader *GetShader(const gl::ProgramState &programState, uint32_t shaderIndex)
139{
140 switch (shaderIndex)
141 {
142 case VertexShader:
Jiawei Shao385b3e02018-03-21 09:43:28 +0800143 return programState.getAttachedShader(gl::ShaderType::Vertex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400144 case FragmentShader:
Jiawei Shao385b3e02018-03-21 09:43:28 +0800145 return programState.getAttachedShader(gl::ShaderType::Fragment);
Jamie Madill76e471e2017-10-21 09:56:01 -0400146 default:
147 UNREACHABLE();
148 return nullptr;
149 }
150}
151
152} // anonymous namespace
153
154ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
155 : storage(), uniformData(), uniformsDirty(false), uniformLayout()
156{
157}
158
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500159ProgramVk::DefaultUniformBlock::~DefaultUniformBlock()
160{
161}
162
Jamie Madill76e471e2017-10-21 09:56:01 -0400163ProgramVk::ProgramVk(const gl::ProgramState &state)
Jamie Madill8c3988c2017-12-21 14:44:56 -0500164 : ProgramImpl(state), mDefaultUniformBlocks(), mUsedDescriptorSetRange(), mDirtyTextures(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400165{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500166 mUsedDescriptorSetRange.invalidate();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400167}
168
169ProgramVk::~ProgramVk()
170{
171}
172
Jamie Madillb7d924a2018-03-10 11:16:54 -0500173gl::Error ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500174{
Jamie Madill67ae6c52018-03-09 11:49:01 -0500175 ContextVk *contextVk = vk::GetImpl(contextImpl);
Jamie Madillb7d924a2018-03-10 11:16:54 -0500176 return reset(contextVk);
Jamie Madillc5143482017-10-15 20:20:06 -0400177}
Jamie Madill5deea722017-02-16 10:44:46 -0500178
Jamie Madillb7d924a2018-03-10 11:16:54 -0500179vk::Error ProgramVk::reset(ContextVk *contextVk)
Jamie Madillc5143482017-10-15 20:20:06 -0400180{
Jamie Madill67ae6c52018-03-09 11:49:01 -0500181 // TODO(jmadill): Handle re-linking a program that is in-use. http://anglebug.com/2397
182
183 VkDevice device = contextVk->getDevice();
184
Jamie Madill76e471e2017-10-21 09:56:01 -0400185 for (auto &uniformBlock : mDefaultUniformBlocks)
186 {
187 uniformBlock.storage.memory.destroy(device);
188 uniformBlock.storage.buffer.destroy(device);
189 }
190
191 mEmptyUniformBlockStorage.memory.destroy(device);
192 mEmptyUniformBlockStorage.buffer.destroy(device);
193
Jamie Madill5deea722017-02-16 10:44:46 -0500194 mLinkedFragmentModule.destroy(device);
195 mLinkedVertexModule.destroy(device);
Jamie Madillf2f6d372018-01-10 21:37:23 -0500196 mVertexModuleSerial = Serial();
197 mFragmentModuleSerial = Serial();
Jamie Madill76e471e2017-10-21 09:56:01 -0400198
Jamie Madill5547b382017-10-23 18:16:01 -0400199 mDescriptorSets.clear();
Jamie Madill8c3988c2017-12-21 14:44:56 -0500200 mUsedDescriptorSetRange.invalidate();
Jamie Madill5547b382017-10-23 18:16:01 -0400201 mDirtyTextures = false;
Jamie Madillb7d924a2018-03-10 11:16:54 -0500202
203 return vk::NoError();
Jamie Madill5deea722017-02-16 10:44:46 -0500204}
205
Jamie Madill9cf9e872017-06-05 12:59:25 -0400206gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
207 gl::InfoLog &infoLog,
208 gl::BinaryInputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400209{
210 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500211 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400212}
213
Jamie Madill27a60632017-06-30 15:12:01 -0400214void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400215{
216 UNIMPLEMENTED();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400217}
218
219void ProgramVk::setBinaryRetrievableHint(bool retrievable)
220{
221 UNIMPLEMENTED();
222}
223
Yunchao He61afff12017-03-14 15:34:03 +0800224void ProgramVk::setSeparable(bool separable)
225{
226 UNIMPLEMENTED();
227}
228
Jamie Madill9cf9e872017-06-05 12:59:25 -0400229gl::LinkResult ProgramVk::link(const gl::Context *glContext,
Jamie Madillc9727f32017-11-07 12:37:07 -0500230 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400231 gl::InfoLog &infoLog)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400232{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400233 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madillc5143482017-10-15 20:20:06 -0400234 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500235 GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
Jamie Madillc5143482017-10-15 20:20:06 -0400236 VkDevice device = renderer->getDevice();
237
Jamie Madillb7d924a2018-03-10 11:16:54 -0500238 ANGLE_TRY(reset(contextVk));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500239
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500240 std::vector<uint32_t> vertexCode;
241 std::vector<uint32_t> fragmentCode;
242 bool linkSuccess = false;
Jamie Madill4dd167f2017-11-09 13:08:31 -0500243 ANGLE_TRY_RESULT(
244 glslangWrapper->linkProgram(glContext, mState, resources, &vertexCode, &fragmentCode),
245 linkSuccess);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500246 if (!linkSuccess)
247 {
248 return false;
249 }
250
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500251 {
252 VkShaderModuleCreateInfo vertexShaderInfo;
253 vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
254 vertexShaderInfo.pNext = nullptr;
255 vertexShaderInfo.flags = 0;
256 vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
257 vertexShaderInfo.pCode = vertexCode.data();
Jamie Madillc5143482017-10-15 20:20:06 -0400258
259 ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
Jamie Madillf2f6d372018-01-10 21:37:23 -0500260 mVertexModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500261 }
262
263 {
264 VkShaderModuleCreateInfo fragmentShaderInfo;
265 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
266 fragmentShaderInfo.pNext = nullptr;
267 fragmentShaderInfo.flags = 0;
268 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
269 fragmentShaderInfo.pCode = fragmentCode.data();
270
Jamie Madillc5143482017-10-15 20:20:06 -0400271 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madillf2f6d372018-01-10 21:37:23 -0500272 mFragmentModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500273 }
274
Jamie Madill76e471e2017-10-21 09:56:01 -0400275 ANGLE_TRY(initDescriptorSets(contextVk));
276 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500277
Jamie Madill8c3988c2017-12-21 14:44:56 -0500278 if (!mState.getSamplerUniformRange().empty())
279 {
280 // Ensure the descriptor set range includes the textures at position 1.
281 mUsedDescriptorSetRange.extend(1);
282 mDirtyTextures = true;
283 }
284
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500285 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400286}
287
Jamie Madill76e471e2017-10-21 09:56:01 -0400288gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
289{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400290 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madill57fbfd82018-02-14 12:45:34 -0500291 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400292 VkDevice device = contextVk->getDevice();
293
294 // Process vertex and fragment uniforms into std140 packing.
295 std::array<sh::BlockLayoutMap, 2> layoutMap;
296 std::array<size_t, 2> requiredBufferSize = {{0, 0}};
297
298 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
299 {
300 ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex),
301 &mDefaultUniformBlocks[shaderIndex].storage,
302 &layoutMap[shaderIndex],
303 &requiredBufferSize[shaderIndex]));
304 }
305
306 // Init the default block layout info.
307 const auto &locations = mState.getUniformLocations();
308 const auto &uniforms = mState.getUniforms();
309 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
310 {
311 std::array<sh::BlockMemberInfo, 2> layoutInfo;
312
313 const auto &location = locations[locationIndex];
314 if (location.used() && !location.ignored)
315 {
Jamie Madillde03e002017-10-21 14:04:20 -0400316 const auto &uniform = uniforms[location.index];
317
318 if (uniform.isSampler())
319 continue;
320
Jamie Madill76e471e2017-10-21 09:56:01 -0400321 std::string uniformName = uniform.name;
322 if (uniform.isArray())
323 {
Olli Etuaho1734e172017-10-27 15:30:27 +0300324 uniformName += ArrayString(location.arrayIndex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400325 }
326
327 bool found = false;
328
329 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
330 {
331 auto it = layoutMap[shaderIndex].find(uniformName);
332 if (it != layoutMap[shaderIndex].end())
333 {
334 found = true;
335 layoutInfo[shaderIndex] = it->second;
336 }
337 }
338
339 ASSERT(found);
340 }
341
342 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
343 {
344 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
345 }
346 }
347
348 bool anyDirty = false;
349 bool allDirty = true;
350
351 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
352 {
353 if (requiredBufferSize[shaderIndex] > 0)
354 {
355 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
356 requiredBufferSize[shaderIndex]))
357 {
358 return gl::OutOfMemory() << "Memory allocation failure.";
359 }
360 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
361 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
362
363 anyDirty = true;
364 }
365 else
366 {
367 allDirty = false;
368 }
369 }
370
371 if (anyDirty)
372 {
373 // Initialize the "empty" uniform block if necessary.
374 if (!allDirty)
375 {
376 VkBufferCreateInfo uniformBufferInfo;
377 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
378 uniformBufferInfo.pNext = nullptr;
379 uniformBufferInfo.flags = 0;
380 uniformBufferInfo.size = 1;
381 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
382 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
383 uniformBufferInfo.queueFamilyIndexCount = 0;
384 uniformBufferInfo.pQueueFamilyIndices = nullptr;
385
386 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
387
Jamie Madill57dd97a2018-02-06 17:10:49 -0500388 // Assume host vislble/coherent memory available.
389 VkMemoryPropertyFlags flags =
390 (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Jamie Madill76e471e2017-10-21 09:56:01 -0400391 size_t requiredSize = 0;
Jamie Madill57fbfd82018-02-14 12:45:34 -0500392 ANGLE_TRY(AllocateBufferMemory(renderer, flags, &mEmptyUniformBlockStorage.buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -0400393 &mEmptyUniformBlockStorage.memory, &requiredSize));
394 }
395
396 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
Jamie Madill8c3988c2017-12-21 14:44:56 -0500397
398 // Ensure the descriptor set range includes the uniform buffers at position 0.
399 mUsedDescriptorSetRange.extend(0);
Jamie Madill5547b382017-10-23 18:16:01 -0400400 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400401
402 return gl::NoError();
403}
404
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400405GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
406{
407 UNIMPLEMENTED();
408 return GLboolean();
409}
410
Jamie Madill76e471e2017-10-21 09:56:01 -0400411template <typename T>
412void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
413{
414 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
415 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
416
Luc Ferron7cec3352018-03-13 13:29:34 -0400417 if (linkedUniform.isSampler())
418 {
419 UNIMPLEMENTED();
420 return;
421 }
422
Jamie Madill76e471e2017-10-21 09:56:01 -0400423 if (linkedUniform.type == entryPointType)
424 {
425 for (auto &uniformBlock : mDefaultUniformBlocks)
426 {
427 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
Jamie Madill5eaddbd2018-03-14 16:16:03 -0400428
429 // Assume an offset of -1 means the block is unused.
430 if (layoutInfo.offset == -1)
431 {
432 continue;
433 }
434
Jamie Madill76e471e2017-10-21 09:56:01 -0400435 UpdateDefaultUniformBlock(count, linkedUniform.typeInfo->componentCount, v, layoutInfo,
436 &uniformBlock.uniformData);
Jamie Madill5eaddbd2018-03-14 16:16:03 -0400437
438 uniformBlock.uniformsDirty = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400439 }
440 }
441 else
442 {
443 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
444 UNIMPLEMENTED();
445 }
446}
447
Luc Ferron7cec3352018-03-13 13:29:34 -0400448template <typename T>
449void ProgramVk::getUniformImpl(GLint location, T *v, GLenum entryPointType) const
450{
451 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
452 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
453
454 if (linkedUniform.isSampler())
455 {
456 UNIMPLEMENTED();
457 return;
458 }
459
460 ASSERT(linkedUniform.typeInfo->componentType == entryPointType);
Olli Etuaho107c7242018-03-20 15:45:35 +0200461 const gl::ShaderType shaderType = linkedUniform.getFirstShaderTypeWhereActive();
Jiawei Shao385b3e02018-03-21 09:43:28 +0800462 ASSERT(shaderType != gl::ShaderType::InvalidEnum);
Luc Ferron7cec3352018-03-13 13:29:34 -0400463
Jiawei Shao385b3e02018-03-21 09:43:28 +0800464 const DefaultUniformBlock &uniformBlock =
465 mDefaultUniformBlocks[static_cast<GLuint>(shaderType)];
Luc Ferron7cec3352018-03-13 13:29:34 -0400466 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
467 ReadFromDefaultUniformBlock(linkedUniform.typeInfo->componentCount, v, layoutInfo,
468 &uniformBlock.uniformData);
469}
470
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400471void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
472{
Jamie Madill76e471e2017-10-21 09:56:01 -0400473 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400474}
475
476void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
477{
Jamie Madill76e471e2017-10-21 09:56:01 -0400478 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400479}
480
481void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
482{
Jamie Madill76e471e2017-10-21 09:56:01 -0400483 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400484}
485
486void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
487{
Jamie Madill76e471e2017-10-21 09:56:01 -0400488 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400489}
490
491void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
492{
Luc Ferron7cec3352018-03-13 13:29:34 -0400493 setUniformImpl(location, count, v, GL_INT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400494}
495
496void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
497{
498 UNIMPLEMENTED();
499}
500
501void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
502{
503 UNIMPLEMENTED();
504}
505
506void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
507{
508 UNIMPLEMENTED();
509}
510
511void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
512{
513 UNIMPLEMENTED();
514}
515
516void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
517{
518 UNIMPLEMENTED();
519}
520
521void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
522{
523 UNIMPLEMENTED();
524}
525
526void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
527{
528 UNIMPLEMENTED();
529}
530
531void ProgramVk::setUniformMatrix2fv(GLint location,
532 GLsizei count,
533 GLboolean transpose,
534 const GLfloat *value)
535{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400536 if (transpose == GL_TRUE)
537 {
538 UNIMPLEMENTED();
539 return;
540 }
541
542 setUniformImpl(location, count, value, GL_FLOAT_MAT2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400543}
544
545void ProgramVk::setUniformMatrix3fv(GLint location,
546 GLsizei count,
547 GLboolean transpose,
548 const GLfloat *value)
549{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400550 if (transpose == GL_TRUE)
551 {
552 UNIMPLEMENTED();
553 return;
554 }
555 setUniformImpl(location, count, value, GL_FLOAT_MAT3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400556}
557
558void ProgramVk::setUniformMatrix4fv(GLint location,
559 GLsizei count,
560 GLboolean transpose,
561 const GLfloat *value)
562{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400563 if (transpose == GL_TRUE)
564 {
565 UNIMPLEMENTED();
566 return;
567 }
568
569 setUniformImpl(location, count, value, GL_FLOAT_MAT4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400570}
571
572void ProgramVk::setUniformMatrix2x3fv(GLint location,
573 GLsizei count,
574 GLboolean transpose,
575 const GLfloat *value)
576{
577 UNIMPLEMENTED();
578}
579
580void ProgramVk::setUniformMatrix3x2fv(GLint location,
581 GLsizei count,
582 GLboolean transpose,
583 const GLfloat *value)
584{
585 UNIMPLEMENTED();
586}
587
588void ProgramVk::setUniformMatrix2x4fv(GLint location,
589 GLsizei count,
590 GLboolean transpose,
591 const GLfloat *value)
592{
593 UNIMPLEMENTED();
594}
595
596void ProgramVk::setUniformMatrix4x2fv(GLint location,
597 GLsizei count,
598 GLboolean transpose,
599 const GLfloat *value)
600{
601 UNIMPLEMENTED();
602}
603
604void ProgramVk::setUniformMatrix3x4fv(GLint location,
605 GLsizei count,
606 GLboolean transpose,
607 const GLfloat *value)
608{
609 UNIMPLEMENTED();
610}
611
612void ProgramVk::setUniformMatrix4x3fv(GLint location,
613 GLsizei count,
614 GLboolean transpose,
615 const GLfloat *value)
616{
617 UNIMPLEMENTED();
618}
619
620void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
621{
622 UNIMPLEMENTED();
623}
624
Sami Väisänen46eaa942016-06-29 10:26:37 +0300625void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
626 GLenum genMode,
627 GLint components,
628 const GLfloat *coeffs)
629{
630 UNIMPLEMENTED();
631}
632
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500633const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
634{
635 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
636 return mLinkedVertexModule;
637}
638
Jamie Madillf2f6d372018-01-10 21:37:23 -0500639Serial ProgramVk::getVertexModuleSerial() const
640{
641 return mVertexModuleSerial;
642}
643
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500644const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
645{
646 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
647 return mLinkedFragmentModule;
648}
649
Jamie Madillf2f6d372018-01-10 21:37:23 -0500650Serial ProgramVk::getFragmentModuleSerial() const
651{
652 return mFragmentModuleSerial;
653}
654
Jamie Madill76e471e2017-10-21 09:56:01 -0400655vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
656{
Jamie Madill5547b382017-10-23 18:16:01 -0400657 ASSERT(mDescriptorSets.empty());
Jamie Madill76e471e2017-10-21 09:56:01 -0400658
Jamie Madill8c3988c2017-12-21 14:44:56 -0500659 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400660
661 // Write out to a new a descriptor set.
Luc Ferrondaedf4d2018-03-16 09:28:53 -0400662 DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool();
Jamie Madill76e471e2017-10-21 09:56:01 -0400663
Jamie Madill8c3988c2017-12-21 14:44:56 -0500664 const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
665
666 uint32_t descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
Jamie Madill76e471e2017-10-21 09:56:01 -0400667
Jamie Madill5547b382017-10-23 18:16:01 -0400668 mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
Luc Ferrondaedf4d2018-03-16 09:28:53 -0400669 ANGLE_TRY(dynamicDescriptorPool->allocateDescriptorSets(
670 contextVk, descriptorSetLayouts[0].ptr(), descriptorSetCount, &mDescriptorSets[0]));
Jamie Madill76e471e2017-10-21 09:56:01 -0400671 return vk::NoError();
672}
673
Jamie Madill54164b02017-08-28 15:17:37 -0400674void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
675{
Luc Ferron7cec3352018-03-13 13:29:34 -0400676 getUniformImpl(location, params, GL_FLOAT);
Jamie Madill54164b02017-08-28 15:17:37 -0400677}
678
679void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
680{
Luc Ferron7cec3352018-03-13 13:29:34 -0400681 getUniformImpl(location, params, GL_INT);
Jamie Madill54164b02017-08-28 15:17:37 -0400682}
683
684void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
685{
686 UNIMPLEMENTED();
687}
688
Jamie Madill76e471e2017-10-21 09:56:01 -0400689vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
690{
691 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
692 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
693 {
694 return vk::NoError();
695 }
696
Jamie Madill8c3988c2017-12-21 14:44:56 -0500697 ASSERT(mUsedDescriptorSetRange.contains(0));
Jamie Madill5547b382017-10-23 18:16:01 -0400698
Jamie Madill76e471e2017-10-21 09:56:01 -0400699 VkDevice device = contextVk->getDevice();
700
701 // Update buffer memory by immediate mapping. This immediate update only works once.
702 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
703 for (auto &uniformBlock : mDefaultUniformBlocks)
704 {
705 if (uniformBlock.uniformsDirty)
706 {
707 ANGLE_TRY(SyncDefaultUniformBlock(device, &uniformBlock.storage.memory,
708 uniformBlock.uniformData));
709 uniformBlock.uniformsDirty = false;
710 }
711 }
712
713 return vk::NoError();
714}
715
716vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
717{
718 std::array<VkDescriptorBufferInfo, 2> descriptorBufferInfo;
719 std::array<VkWriteDescriptorSet, 2> writeDescriptorInfo;
720 uint32_t bufferCount = 0;
721
722 for (auto &uniformBlock : mDefaultUniformBlocks)
723 {
724 auto &bufferInfo = descriptorBufferInfo[bufferCount];
725
726 if (!uniformBlock.uniformData.empty())
727 {
728 bufferInfo.buffer = uniformBlock.storage.buffer.getHandle();
729 }
730 else
731 {
732 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
733 }
734
735 bufferInfo.offset = 0;
736 bufferInfo.range = VK_WHOLE_SIZE;
737
738 auto &writeInfo = writeDescriptorInfo[bufferCount];
739
740 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
741 writeInfo.pNext = nullptr;
Jamie Madill5547b382017-10-23 18:16:01 -0400742 writeInfo.dstSet = mDescriptorSets[0];
Jamie Madill76e471e2017-10-21 09:56:01 -0400743 writeInfo.dstBinding = bufferCount;
744 writeInfo.dstArrayElement = 0;
745 writeInfo.descriptorCount = 1;
746 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
747 writeInfo.pImageInfo = nullptr;
748 writeInfo.pBufferInfo = &bufferInfo;
749 writeInfo.pTexelBufferView = nullptr;
750
751 bufferCount++;
752 }
753
754 VkDevice device = contextVk->getDevice();
755
756 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
757
758 return vk::NoError();
759}
760
Jamie Madill5547b382017-10-23 18:16:01 -0400761const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
Jamie Madill76e471e2017-10-21 09:56:01 -0400762{
Jamie Madill5547b382017-10-23 18:16:01 -0400763 return mDescriptorSets;
764}
765
Jamie Madill8c3988c2017-12-21 14:44:56 -0500766const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
Jamie Madill5547b382017-10-23 18:16:01 -0400767{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500768 return mUsedDescriptorSetRange;
Jamie Madill5547b382017-10-23 18:16:01 -0400769}
770
771void ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
772{
773 if (mState.getSamplerBindings().empty() || !mDirtyTextures)
774 {
775 return;
776 }
777
Jamie Madill8c3988c2017-12-21 14:44:56 -0500778 ASSERT(mUsedDescriptorSetRange.contains(1));
779 VkDescriptorSet descriptorSet = mDescriptorSets[1];
Jamie Madill5547b382017-10-23 18:16:01 -0400780
781 // TODO(jmadill): Don't hard-code the texture limit.
782 ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
783 ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
784 uint32_t imageCount = 0;
785
786 const gl::State &glState = contextVk->getGLState();
787 const auto &completeTextures = glState.getCompleteTextureCache();
788
789 for (const auto &samplerBinding : mState.getSamplerBindings())
790 {
791 ASSERT(!samplerBinding.unreferenced);
792
793 // TODO(jmadill): Sampler arrays
794 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
795
796 GLuint textureUnit = samplerBinding.boundTextureUnits[0];
797 const gl::Texture *texture = completeTextures[textureUnit];
798
799 // TODO(jmadill): Incomplete textures handling.
800 ASSERT(texture);
801
Jamie Madille1f3ad42017-10-28 23:00:42 -0400802 TextureVk *textureVk = vk::GetImpl(texture);
Jamie Madill5547b382017-10-23 18:16:01 -0400803 const vk::Image &image = textureVk->getImage();
804
805 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
806
807 imageInfo.sampler = textureVk->getSampler().getHandle();
808 imageInfo.imageView = textureVk->getImageView().getHandle();
809 imageInfo.imageLayout = image.getCurrentLayout();
810
811 auto &writeInfo = writeDescriptorInfo[imageCount];
812
813 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
814 writeInfo.pNext = nullptr;
815 writeInfo.dstSet = descriptorSet;
816 writeInfo.dstBinding = imageCount;
817 writeInfo.dstArrayElement = 0;
818 writeInfo.descriptorCount = 1;
819 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
820 writeInfo.pImageInfo = &imageInfo;
821 writeInfo.pBufferInfo = nullptr;
822 writeInfo.pTexelBufferView = nullptr;
823
824 imageCount++;
825 }
826
827 VkDevice device = contextVk->getDevice();
828
829 ASSERT(imageCount > 0);
830 vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
831
832 mDirtyTextures = false;
833}
834
835void ProgramVk::invalidateTextures()
836{
837 mDirtyTextures = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400838}
839
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400840} // namespace rx