blob: d6fecd7bf4b441f018f70395de9b7209e950a93b [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"
Luc Ferron7a06ac12018-03-15 10:17:04 -040019#include "libANGLE/renderer/vulkan/StreamingBuffer.h"
Jamie Madill5547b382017-10-23 18:16:01 -040020#include "libANGLE/renderer/vulkan/TextureVk.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040021
22namespace rx
23{
24
Jamie Madill76e471e2017-10-21 09:56:01 -040025namespace
26{
27
Luc Ferron7a06ac12018-03-15 10:17:04 -040028constexpr size_t kUniformBlockStreamingBufferMinSize = 256 * 128;
29
Jamie Madill76e471e2017-10-21 09:56:01 -040030gl::Error InitDefaultUniformBlock(const gl::Context *context,
Jamie Madill76e471e2017-10-21 09:56:01 -040031 gl::Shader *shader,
Jamie Madill76e471e2017-10-21 09:56:01 -040032 sh::BlockLayoutMap *blockLayoutMapOut,
Luc Ferron7a06ac12018-03-15 10:17:04 -040033 size_t *blockSizeOut)
Jamie Madill76e471e2017-10-21 09:56:01 -040034{
35 const auto &uniforms = shader->getUniforms(context);
36
37 if (uniforms.empty())
38 {
Luc Ferron7a06ac12018-03-15 10:17:04 -040039 *blockSizeOut = 0;
Jamie Madill76e471e2017-10-21 09:56:01 -040040 return gl::NoError();
41 }
42
43 sh::Std140BlockEncoder blockEncoder;
Olli Etuaho3de27032017-11-30 12:16:47 +020044 sh::GetUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
Jamie Madill76e471e2017-10-21 09:56:01 -040045
46 size_t blockSize = blockEncoder.getBlockSize();
47
48 // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
49 if (blockSize == 0)
50 {
Luc Ferron7a06ac12018-03-15 10:17:04 -040051 *blockSizeOut = 0;
Jamie Madill76e471e2017-10-21 09:56:01 -040052 return gl::NoError();
53 }
54
Luc Ferron7a06ac12018-03-15 10:17:04 -040055 *blockSizeOut = blockSize;
Jamie Madill76e471e2017-10-21 09:56:01 -040056 return gl::NoError();
57}
58
59template <typename T>
60void UpdateDefaultUniformBlock(GLsizei count,
Luc Ferron2371aca2018-03-27 16:03:03 -040061 uint32_t arrayIndex,
Jamie Madill76e471e2017-10-21 09:56:01 -040062 int componentCount,
63 const T *v,
64 const sh::BlockMemberInfo &layoutInfo,
65 angle::MemoryBuffer *uniformData)
66{
Luc Ferron2371aca2018-03-27 16:03:03 -040067 const int elementSize = sizeof(T) * componentCount;
68
69 uint8_t *dst = uniformData->data() + layoutInfo.offset;
Jamie Madill76e471e2017-10-21 09:56:01 -040070 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
71 {
Luc Ferron2371aca2018-03-27 16:03:03 -040072 uint32_t arrayOffset = arrayIndex * layoutInfo.arrayStride;
73 uint8_t *writePtr = dst + arrayOffset;
Jamie Madill76e471e2017-10-21 09:56:01 -040074 memcpy(writePtr, v, elementSize * count);
75 }
76 else
77 {
Luc Ferron2371aca2018-03-27 16:03:03 -040078 // Have to respect the arrayStride between each element of the array.
79 int maxIndex = arrayIndex + count;
80 for (int writeIndex = arrayIndex, readIndex = 0; writeIndex < maxIndex;
81 writeIndex++, readIndex++)
82 {
83 const int arrayOffset = writeIndex * layoutInfo.arrayStride;
84 uint8_t *writePtr = dst + arrayOffset;
85 const T *readPtr = v + readIndex;
86 memcpy(writePtr, readPtr, elementSize);
87 }
Jamie Madill76e471e2017-10-21 09:56:01 -040088 }
89}
90
Luc Ferron7cec3352018-03-13 13:29:34 -040091template <typename T>
92void ReadFromDefaultUniformBlock(int componentCount,
Luc Ferron2371aca2018-03-27 16:03:03 -040093 uint32_t arrayIndex,
Luc Ferron7cec3352018-03-13 13:29:34 -040094 T *dst,
95 const sh::BlockMemberInfo &layoutInfo,
96 const angle::MemoryBuffer *uniformData)
97{
98 ASSERT(layoutInfo.offset != -1);
99
Luc Ferron2371aca2018-03-27 16:03:03 -0400100 const int elementSize = sizeof(T) * componentCount;
101 const uint8_t *source = uniformData->data() + layoutInfo.offset;
102
Luc Ferron7cec3352018-03-13 13:29:34 -0400103 if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
104 {
Luc Ferron2371aca2018-03-27 16:03:03 -0400105 const uint8_t *readPtr = source + arrayIndex * layoutInfo.arrayStride;
Luc Ferron7cec3352018-03-13 13:29:34 -0400106 memcpy(dst, readPtr, elementSize);
107 }
108 else
109 {
Luc Ferron2371aca2018-03-27 16:03:03 -0400110 // Have to respect the arrayStride between each element of the array.
111 const int arrayOffset = arrayIndex * layoutInfo.arrayStride;
112 const uint8_t *readPtr = source + arrayOffset;
113 memcpy(dst, readPtr, elementSize);
Luc Ferron7cec3352018-03-13 13:29:34 -0400114 }
115}
116
Luc Ferron7a06ac12018-03-15 10:17:04 -0400117vk::Error SyncDefaultUniformBlock(ContextVk *contextVk,
118 StreamingBuffer &streamingBuffer,
119 const angle::MemoryBuffer &bufferData,
120 uint32_t *outOffset,
121 bool *outBufferModified)
Jamie Madill76e471e2017-10-21 09:56:01 -0400122{
Luc Ferron7a06ac12018-03-15 10:17:04 -0400123 ASSERT(!bufferData.empty());
124 uint8_t *data = nullptr;
125 VkBuffer *outBuffer = nullptr;
126 uint32_t offset;
127 ANGLE_TRY(streamingBuffer.allocate(contextVk, bufferData.size(), &data, outBuffer, &offset,
128 outBufferModified));
129 *outOffset = offset;
130 memcpy(data, bufferData.data(), bufferData.size());
131 ANGLE_TRY(streamingBuffer.flush(contextVk));
Jamie Madill76e471e2017-10-21 09:56:01 -0400132 return vk::NoError();
133}
134
Jiawei Shao385b3e02018-03-21 09:43:28 +0800135// TODO(jiawei.shao@intel.com): Fully remove this enum by gl::ShaderType. (BUG=angleproject:2169)
Jamie Madill76e471e2017-10-21 09:56:01 -0400136enum ShaderIndex : uint32_t
137{
138 MinShaderIndex = 0,
139 VertexShader = MinShaderIndex,
140 FragmentShader = 1,
Luc Ferron7a06ac12018-03-15 10:17:04 -0400141 MaxShaderIndex = kShaderTypeCount,
Jamie Madill76e471e2017-10-21 09:56:01 -0400142};
143
144gl::Shader *GetShader(const gl::ProgramState &programState, uint32_t shaderIndex)
145{
146 switch (shaderIndex)
147 {
148 case VertexShader:
Jiawei Shao385b3e02018-03-21 09:43:28 +0800149 return programState.getAttachedShader(gl::ShaderType::Vertex);
Jamie Madill76e471e2017-10-21 09:56:01 -0400150 case FragmentShader:
Jiawei Shao385b3e02018-03-21 09:43:28 +0800151 return programState.getAttachedShader(gl::ShaderType::Fragment);
Jamie Madill76e471e2017-10-21 09:56:01 -0400152 default:
153 UNREACHABLE();
154 return nullptr;
155 }
156}
157
158} // anonymous namespace
159
160ProgramVk::DefaultUniformBlock::DefaultUniformBlock()
Luc Ferron7a06ac12018-03-15 10:17:04 -0400161 : storage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
162 kUniformBlockStreamingBufferMinSize),
163 uniformData(),
164 uniformsDirty(false),
165 uniformLayout()
Jamie Madill76e471e2017-10-21 09:56:01 -0400166{
167}
168
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500169ProgramVk::DefaultUniformBlock::~DefaultUniformBlock()
170{
171}
172
Jamie Madill76e471e2017-10-21 09:56:01 -0400173ProgramVk::ProgramVk(const gl::ProgramState &state)
Luc Ferron7a06ac12018-03-15 10:17:04 -0400174 : ProgramImpl(state),
175 mDefaultUniformBlocks(),
176 mUniformBlocksOffsets(),
177 mUsedDescriptorSetRange(),
178 mDirtyTextures(true)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400179{
Luc Ferron7a06ac12018-03-15 10:17:04 -0400180 mUniformBlocksOffsets.fill(0);
Jamie Madill8c3988c2017-12-21 14:44:56 -0500181 mUsedDescriptorSetRange.invalidate();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400182}
183
184ProgramVk::~ProgramVk()
185{
186}
187
Jamie Madillb7d924a2018-03-10 11:16:54 -0500188gl::Error ProgramVk::destroy(const gl::Context *contextImpl)
Jamie Madill5deea722017-02-16 10:44:46 -0500189{
Jamie Madill67ae6c52018-03-09 11:49:01 -0500190 ContextVk *contextVk = vk::GetImpl(contextImpl);
Jamie Madillb7d924a2018-03-10 11:16:54 -0500191 return reset(contextVk);
Jamie Madillc5143482017-10-15 20:20:06 -0400192}
Jamie Madill5deea722017-02-16 10:44:46 -0500193
Jamie Madillb7d924a2018-03-10 11:16:54 -0500194vk::Error ProgramVk::reset(ContextVk *contextVk)
Jamie Madillc5143482017-10-15 20:20:06 -0400195{
Jamie Madill67ae6c52018-03-09 11:49:01 -0500196 // TODO(jmadill): Handle re-linking a program that is in-use. http://anglebug.com/2397
197
198 VkDevice device = contextVk->getDevice();
199
Jamie Madill76e471e2017-10-21 09:56:01 -0400200 for (auto &uniformBlock : mDefaultUniformBlocks)
201 {
Luc Ferron7a06ac12018-03-15 10:17:04 -0400202 uniformBlock.storage.destroy(device);
Jamie Madill76e471e2017-10-21 09:56:01 -0400203 }
204
205 mEmptyUniformBlockStorage.memory.destroy(device);
206 mEmptyUniformBlockStorage.buffer.destroy(device);
207
Jamie Madill5deea722017-02-16 10:44:46 -0500208 mLinkedFragmentModule.destroy(device);
209 mLinkedVertexModule.destroy(device);
Jamie Madillf2f6d372018-01-10 21:37:23 -0500210 mVertexModuleSerial = Serial();
211 mFragmentModuleSerial = Serial();
Jamie Madill76e471e2017-10-21 09:56:01 -0400212
Jamie Madill5547b382017-10-23 18:16:01 -0400213 mDescriptorSets.clear();
Jamie Madill8c3988c2017-12-21 14:44:56 -0500214 mUsedDescriptorSetRange.invalidate();
Jamie Madill5547b382017-10-23 18:16:01 -0400215 mDirtyTextures = false;
Jamie Madillb7d924a2018-03-10 11:16:54 -0500216
217 return vk::NoError();
Jamie Madill5deea722017-02-16 10:44:46 -0500218}
219
Jamie Madill9cf9e872017-06-05 12:59:25 -0400220gl::LinkResult ProgramVk::load(const gl::Context *contextImpl,
221 gl::InfoLog &infoLog,
222 gl::BinaryInputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400223{
224 UNIMPLEMENTED();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500225 return gl::InternalError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400226}
227
Jamie Madill27a60632017-06-30 15:12:01 -0400228void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400229{
230 UNIMPLEMENTED();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400231}
232
233void ProgramVk::setBinaryRetrievableHint(bool retrievable)
234{
235 UNIMPLEMENTED();
236}
237
Yunchao He61afff12017-03-14 15:34:03 +0800238void ProgramVk::setSeparable(bool separable)
239{
240 UNIMPLEMENTED();
241}
242
Jamie Madill9cf9e872017-06-05 12:59:25 -0400243gl::LinkResult ProgramVk::link(const gl::Context *glContext,
Jamie Madillc9727f32017-11-07 12:37:07 -0500244 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400245 gl::InfoLog &infoLog)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400246{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400247 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madillc5143482017-10-15 20:20:06 -0400248 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500249 GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
Jamie Madillc5143482017-10-15 20:20:06 -0400250 VkDevice device = renderer->getDevice();
251
Jamie Madillb7d924a2018-03-10 11:16:54 -0500252 ANGLE_TRY(reset(contextVk));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500253
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500254 std::vector<uint32_t> vertexCode;
255 std::vector<uint32_t> fragmentCode;
256 bool linkSuccess = false;
Jamie Madill4dd167f2017-11-09 13:08:31 -0500257 ANGLE_TRY_RESULT(
258 glslangWrapper->linkProgram(glContext, mState, resources, &vertexCode, &fragmentCode),
259 linkSuccess);
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500260 if (!linkSuccess)
261 {
262 return false;
263 }
264
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500265 {
266 VkShaderModuleCreateInfo vertexShaderInfo;
267 vertexShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
268 vertexShaderInfo.pNext = nullptr;
269 vertexShaderInfo.flags = 0;
270 vertexShaderInfo.codeSize = vertexCode.size() * sizeof(uint32_t);
271 vertexShaderInfo.pCode = vertexCode.data();
Jamie Madillc5143482017-10-15 20:20:06 -0400272
273 ANGLE_TRY(mLinkedVertexModule.init(device, vertexShaderInfo));
Jamie Madillf2f6d372018-01-10 21:37:23 -0500274 mVertexModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500275 }
276
277 {
278 VkShaderModuleCreateInfo fragmentShaderInfo;
279 fragmentShaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
280 fragmentShaderInfo.pNext = nullptr;
281 fragmentShaderInfo.flags = 0;
282 fragmentShaderInfo.codeSize = fragmentCode.size() * sizeof(uint32_t);
283 fragmentShaderInfo.pCode = fragmentCode.data();
284
Jamie Madillc5143482017-10-15 20:20:06 -0400285 ANGLE_TRY(mLinkedFragmentModule.init(device, fragmentShaderInfo));
Jamie Madillf2f6d372018-01-10 21:37:23 -0500286 mFragmentModuleSerial = renderer->issueProgramSerial();
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500287 }
288
Jamie Madill76e471e2017-10-21 09:56:01 -0400289 ANGLE_TRY(initDefaultUniformBlocks(glContext));
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500290
Jamie Madill8c3988c2017-12-21 14:44:56 -0500291 if (!mState.getSamplerUniformRange().empty())
292 {
293 // Ensure the descriptor set range includes the textures at position 1.
294 mUsedDescriptorSetRange.extend(1);
295 mDirtyTextures = true;
296 }
297
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500298 return true;
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400299}
300
Jamie Madill76e471e2017-10-21 09:56:01 -0400301gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
302{
Jamie Madille1f3ad42017-10-28 23:00:42 -0400303 ContextVk *contextVk = vk::GetImpl(glContext);
Jamie Madill57fbfd82018-02-14 12:45:34 -0500304 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400305 VkDevice device = contextVk->getDevice();
306
307 // Process vertex and fragment uniforms into std140 packing.
Luc Ferron7a06ac12018-03-15 10:17:04 -0400308 std::array<sh::BlockLayoutMap, MaxShaderIndex> layoutMap;
309 std::array<size_t, MaxShaderIndex> requiredBufferSize = {{0, 0}};
Jamie Madill76e471e2017-10-21 09:56:01 -0400310
311 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
312 {
Luc Ferron7a06ac12018-03-15 10:17:04 -0400313 ANGLE_TRY(InitDefaultUniformBlock(glContext, GetShader(mState, shaderIndex),
Jamie Madill76e471e2017-10-21 09:56:01 -0400314 &layoutMap[shaderIndex],
315 &requiredBufferSize[shaderIndex]));
316 }
317
318 // Init the default block layout info.
319 const auto &locations = mState.getUniformLocations();
320 const auto &uniforms = mState.getUniforms();
321 for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex)
322 {
Luc Ferron7a06ac12018-03-15 10:17:04 -0400323 std::array<sh::BlockMemberInfo, MaxShaderIndex> layoutInfo;
Jamie Madill76e471e2017-10-21 09:56:01 -0400324
325 const auto &location = locations[locationIndex];
326 if (location.used() && !location.ignored)
327 {
Jamie Madillde03e002017-10-21 14:04:20 -0400328 const auto &uniform = uniforms[location.index];
329
330 if (uniform.isSampler())
331 continue;
332
Jamie Madill76e471e2017-10-21 09:56:01 -0400333 std::string uniformName = uniform.name;
334 if (uniform.isArray())
335 {
Luc Ferron2371aca2018-03-27 16:03:03 -0400336 // Gets the uniform name without the [0] at the end.
337 uniformName = gl::ParseResourceName(uniformName, nullptr);
Jamie Madill76e471e2017-10-21 09:56:01 -0400338 }
339
340 bool found = false;
341
342 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
343 {
344 auto it = layoutMap[shaderIndex].find(uniformName);
345 if (it != layoutMap[shaderIndex].end())
346 {
347 found = true;
348 layoutInfo[shaderIndex] = it->second;
349 }
350 }
351
352 ASSERT(found);
353 }
354
355 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
356 {
357 mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]);
358 }
359 }
360
361 bool anyDirty = false;
362 bool allDirty = true;
363
364 for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex)
365 {
366 if (requiredBufferSize[shaderIndex] > 0)
367 {
368 if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize(
369 requiredBufferSize[shaderIndex]))
370 {
371 return gl::OutOfMemory() << "Memory allocation failure.";
372 }
Luc Ferron7a06ac12018-03-15 10:17:04 -0400373 size_t minAlignment = static_cast<size_t>(
374 renderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
375
376 mDefaultUniformBlocks[shaderIndex].storage.init(minAlignment);
377
378 // Initialize uniform buffer memory to zero by default.
Jamie Madill76e471e2017-10-21 09:56:01 -0400379 mDefaultUniformBlocks[shaderIndex].uniformData.fill(0);
380 mDefaultUniformBlocks[shaderIndex].uniformsDirty = true;
381
382 anyDirty = true;
383 }
384 else
385 {
386 allDirty = false;
387 }
388 }
389
390 if (anyDirty)
391 {
392 // Initialize the "empty" uniform block if necessary.
393 if (!allDirty)
394 {
395 VkBufferCreateInfo uniformBufferInfo;
396 uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
397 uniformBufferInfo.pNext = nullptr;
398 uniformBufferInfo.flags = 0;
399 uniformBufferInfo.size = 1;
400 uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
401 uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
402 uniformBufferInfo.queueFamilyIndexCount = 0;
403 uniformBufferInfo.pQueueFamilyIndices = nullptr;
404
405 ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo));
406
Luc Ferron7a06ac12018-03-15 10:17:04 -0400407 // Assume host visible/coherent memory available.
Jamie Madill57dd97a2018-02-06 17:10:49 -0500408 VkMemoryPropertyFlags flags =
409 (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Jamie Madill76e471e2017-10-21 09:56:01 -0400410 size_t requiredSize = 0;
Jamie Madill57fbfd82018-02-14 12:45:34 -0500411 ANGLE_TRY(AllocateBufferMemory(renderer, flags, &mEmptyUniformBlockStorage.buffer,
Jamie Madill76e471e2017-10-21 09:56:01 -0400412 &mEmptyUniformBlockStorage.memory, &requiredSize));
413 }
414
Jamie Madill8c3988c2017-12-21 14:44:56 -0500415 // Ensure the descriptor set range includes the uniform buffers at position 0.
416 mUsedDescriptorSetRange.extend(0);
Jamie Madill5547b382017-10-23 18:16:01 -0400417 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400418
419 return gl::NoError();
420}
421
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400422GLboolean ProgramVk::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
423{
424 UNIMPLEMENTED();
425 return GLboolean();
426}
427
Jamie Madill76e471e2017-10-21 09:56:01 -0400428template <typename T>
429void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
430{
431 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
432 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
433
Luc Ferron7cec3352018-03-13 13:29:34 -0400434 if (linkedUniform.isSampler())
435 {
436 UNIMPLEMENTED();
437 return;
438 }
439
Jamie Madill76e471e2017-10-21 09:56:01 -0400440 if (linkedUniform.type == entryPointType)
441 {
442 for (auto &uniformBlock : mDefaultUniformBlocks)
443 {
444 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
Jamie Madill5eaddbd2018-03-14 16:16:03 -0400445
446 // Assume an offset of -1 means the block is unused.
447 if (layoutInfo.offset == -1)
448 {
449 continue;
450 }
451
Luc Ferron2371aca2018-03-27 16:03:03 -0400452 UpdateDefaultUniformBlock(count, locationInfo.arrayIndex,
453 linkedUniform.typeInfo->componentCount, v, layoutInfo,
Jamie Madill76e471e2017-10-21 09:56:01 -0400454 &uniformBlock.uniformData);
Jamie Madill5eaddbd2018-03-14 16:16:03 -0400455
456 uniformBlock.uniformsDirty = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400457 }
458 }
459 else
460 {
461 ASSERT(linkedUniform.type == gl::VariableBoolVectorType(entryPointType));
462 UNIMPLEMENTED();
463 }
464}
465
Luc Ferron7cec3352018-03-13 13:29:34 -0400466template <typename T>
467void ProgramVk::getUniformImpl(GLint location, T *v, GLenum entryPointType) const
468{
469 const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
470 const gl::LinkedUniform &linkedUniform = mState.getUniforms()[locationInfo.index];
471
472 if (linkedUniform.isSampler())
473 {
474 UNIMPLEMENTED();
475 return;
476 }
477
478 ASSERT(linkedUniform.typeInfo->componentType == entryPointType);
Olli Etuaho107c7242018-03-20 15:45:35 +0200479 const gl::ShaderType shaderType = linkedUniform.getFirstShaderTypeWhereActive();
Jiawei Shao385b3e02018-03-21 09:43:28 +0800480 ASSERT(shaderType != gl::ShaderType::InvalidEnum);
Luc Ferron7cec3352018-03-13 13:29:34 -0400481
Jiawei Shao385b3e02018-03-21 09:43:28 +0800482 const DefaultUniformBlock &uniformBlock =
483 mDefaultUniformBlocks[static_cast<GLuint>(shaderType)];
Luc Ferron7cec3352018-03-13 13:29:34 -0400484 const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
Luc Ferron2371aca2018-03-27 16:03:03 -0400485 ReadFromDefaultUniformBlock(linkedUniform.typeInfo->componentCount, locationInfo.arrayIndex, v,
486 layoutInfo, &uniformBlock.uniformData);
Luc Ferron7cec3352018-03-13 13:29:34 -0400487}
488
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400489void ProgramVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
490{
Jamie Madill76e471e2017-10-21 09:56:01 -0400491 setUniformImpl(location, count, v, GL_FLOAT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400492}
493
494void ProgramVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
495{
Jamie Madill76e471e2017-10-21 09:56:01 -0400496 setUniformImpl(location, count, v, GL_FLOAT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400497}
498
499void ProgramVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
500{
Jamie Madill76e471e2017-10-21 09:56:01 -0400501 setUniformImpl(location, count, v, GL_FLOAT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400502}
503
504void ProgramVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
505{
Jamie Madill76e471e2017-10-21 09:56:01 -0400506 setUniformImpl(location, count, v, GL_FLOAT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400507}
508
509void ProgramVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
510{
Luc Ferron7cec3352018-03-13 13:29:34 -0400511 setUniformImpl(location, count, v, GL_INT);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400512}
513
514void ProgramVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
515{
Luc Ferron489243f2018-03-28 16:55:28 -0400516 setUniformImpl(location, count, v, GL_INT_VEC2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400517}
518
519void ProgramVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
520{
Luc Ferron489243f2018-03-28 16:55:28 -0400521 setUniformImpl(location, count, v, GL_INT_VEC3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400522}
523
524void ProgramVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
525{
Luc Ferron489243f2018-03-28 16:55:28 -0400526 setUniformImpl(location, count, v, GL_INT_VEC4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400527}
528
529void ProgramVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
530{
531 UNIMPLEMENTED();
532}
533
534void ProgramVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
535{
536 UNIMPLEMENTED();
537}
538
539void ProgramVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
540{
541 UNIMPLEMENTED();
542}
543
544void ProgramVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
545{
546 UNIMPLEMENTED();
547}
548
549void ProgramVk::setUniformMatrix2fv(GLint location,
550 GLsizei count,
551 GLboolean transpose,
552 const GLfloat *value)
553{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400554 if (transpose == GL_TRUE)
555 {
556 UNIMPLEMENTED();
557 return;
558 }
559
560 setUniformImpl(location, count, value, GL_FLOAT_MAT2);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400561}
562
563void ProgramVk::setUniformMatrix3fv(GLint location,
564 GLsizei count,
565 GLboolean transpose,
566 const GLfloat *value)
567{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400568 if (transpose == GL_TRUE)
569 {
570 UNIMPLEMENTED();
571 return;
572 }
573 setUniformImpl(location, count, value, GL_FLOAT_MAT3);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400574}
575
576void ProgramVk::setUniformMatrix4fv(GLint location,
577 GLsizei count,
578 GLboolean transpose,
579 const GLfloat *value)
580{
Luc Ferron5b64aca2018-03-14 14:55:58 -0400581 if (transpose == GL_TRUE)
582 {
583 UNIMPLEMENTED();
584 return;
585 }
586
587 setUniformImpl(location, count, value, GL_FLOAT_MAT4);
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400588}
589
590void ProgramVk::setUniformMatrix2x3fv(GLint location,
591 GLsizei count,
592 GLboolean transpose,
593 const GLfloat *value)
594{
595 UNIMPLEMENTED();
596}
597
598void ProgramVk::setUniformMatrix3x2fv(GLint location,
599 GLsizei count,
600 GLboolean transpose,
601 const GLfloat *value)
602{
603 UNIMPLEMENTED();
604}
605
606void ProgramVk::setUniformMatrix2x4fv(GLint location,
607 GLsizei count,
608 GLboolean transpose,
609 const GLfloat *value)
610{
611 UNIMPLEMENTED();
612}
613
614void ProgramVk::setUniformMatrix4x2fv(GLint location,
615 GLsizei count,
616 GLboolean transpose,
617 const GLfloat *value)
618{
619 UNIMPLEMENTED();
620}
621
622void ProgramVk::setUniformMatrix3x4fv(GLint location,
623 GLsizei count,
624 GLboolean transpose,
625 const GLfloat *value)
626{
627 UNIMPLEMENTED();
628}
629
630void ProgramVk::setUniformMatrix4x3fv(GLint location,
631 GLsizei count,
632 GLboolean transpose,
633 const GLfloat *value)
634{
635 UNIMPLEMENTED();
636}
637
638void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
639{
640 UNIMPLEMENTED();
641}
642
Sami Väisänen46eaa942016-06-29 10:26:37 +0300643void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
644 GLenum genMode,
645 GLint components,
646 const GLfloat *coeffs)
647{
648 UNIMPLEMENTED();
649}
650
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500651const vk::ShaderModule &ProgramVk::getLinkedVertexModule() const
652{
653 ASSERT(mLinkedVertexModule.getHandle() != VK_NULL_HANDLE);
654 return mLinkedVertexModule;
655}
656
Jamie Madillf2f6d372018-01-10 21:37:23 -0500657Serial ProgramVk::getVertexModuleSerial() const
658{
659 return mVertexModuleSerial;
660}
661
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500662const vk::ShaderModule &ProgramVk::getLinkedFragmentModule() const
663{
664 ASSERT(mLinkedFragmentModule.getHandle() != VK_NULL_HANDLE);
665 return mLinkedFragmentModule;
666}
667
Jamie Madillf2f6d372018-01-10 21:37:23 -0500668Serial ProgramVk::getFragmentModuleSerial() const
669{
670 return mFragmentModuleSerial;
671}
672
Luc Ferron6ea1b412018-03-21 16:13:01 -0400673vk::Error ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex)
Jamie Madill76e471e2017-10-21 09:56:01 -0400674{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500675 RendererVk *renderer = contextVk->getRenderer();
Jamie Madill76e471e2017-10-21 09:56:01 -0400676
677 // Write out to a new a descriptor set.
Luc Ferrondaedf4d2018-03-16 09:28:53 -0400678 DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool();
Jamie Madill8c3988c2017-12-21 14:44:56 -0500679 const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
Jamie Madill76e471e2017-10-21 09:56:01 -0400680
Luc Ferron6ea1b412018-03-21 16:13:01 -0400681 uint32_t potentialNewCount = descriptorSetIndex + 1;
682 if (potentialNewCount > mDescriptorSets.size())
683 {
684 mDescriptorSets.resize(potentialNewCount, VK_NULL_HANDLE);
685 }
Luc Ferron7a06ac12018-03-15 10:17:04 -0400686
Luc Ferron6ea1b412018-03-21 16:13:01 -0400687 const VkDescriptorSetLayout *descriptorSetLayout =
688 descriptorSetLayouts[descriptorSetIndex].ptr();
689
690 ANGLE_TRY(dynamicDescriptorPool->allocateDescriptorSets(contextVk, descriptorSetLayout, 1,
691 &mDescriptorSets[descriptorSetIndex]));
Jamie Madill76e471e2017-10-21 09:56:01 -0400692 return vk::NoError();
693}
694
Jamie Madill54164b02017-08-28 15:17:37 -0400695void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
696{
Luc Ferron7cec3352018-03-13 13:29:34 -0400697 getUniformImpl(location, params, GL_FLOAT);
Jamie Madill54164b02017-08-28 15:17:37 -0400698}
699
700void ProgramVk::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
701{
Luc Ferron7cec3352018-03-13 13:29:34 -0400702 getUniformImpl(location, params, GL_INT);
Jamie Madill54164b02017-08-28 15:17:37 -0400703}
704
705void ProgramVk::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
706{
707 UNIMPLEMENTED();
708}
709
Jamie Madill76e471e2017-10-21 09:56:01 -0400710vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
711{
712 if (!mDefaultUniformBlocks[VertexShader].uniformsDirty &&
713 !mDefaultUniformBlocks[FragmentShader].uniformsDirty)
714 {
715 return vk::NoError();
716 }
717
Jamie Madill8c3988c2017-12-21 14:44:56 -0500718 ASSERT(mUsedDescriptorSetRange.contains(0));
Jamie Madill5547b382017-10-23 18:16:01 -0400719
Jamie Madill76e471e2017-10-21 09:56:01 -0400720 // Update buffer memory by immediate mapping. This immediate update only works once.
721 // TODO(jmadill): Handle inserting updates into the command stream, or use dynamic buffers.
Luc Ferron7a06ac12018-03-15 10:17:04 -0400722 bool anyNewBufferAllocated = false;
723 for (size_t index = 0; index < mDefaultUniformBlocks.size(); index++)
Jamie Madill76e471e2017-10-21 09:56:01 -0400724 {
Luc Ferron7a06ac12018-03-15 10:17:04 -0400725 DefaultUniformBlock &uniformBlock = mDefaultUniformBlocks[index];
726
Jamie Madill76e471e2017-10-21 09:56:01 -0400727 if (uniformBlock.uniformsDirty)
728 {
Luc Ferron7a06ac12018-03-15 10:17:04 -0400729 bool bufferModified = false;
730 ANGLE_TRY(SyncDefaultUniformBlock(contextVk, uniformBlock.storage,
731 uniformBlock.uniformData,
732 &mUniformBlocksOffsets[index], &bufferModified));
Jamie Madill76e471e2017-10-21 09:56:01 -0400733 uniformBlock.uniformsDirty = false;
Luc Ferron7a06ac12018-03-15 10:17:04 -0400734
735 if (bufferModified)
736 {
737 anyNewBufferAllocated = true;
738 }
Jamie Madill76e471e2017-10-21 09:56:01 -0400739 }
740 }
741
Luc Ferron7a06ac12018-03-15 10:17:04 -0400742 if (anyNewBufferAllocated)
743 {
744 // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
745 // modify the descriptor sets once initialized.
Luc Ferron6ea1b412018-03-21 16:13:01 -0400746 ANGLE_TRY(allocateDescriptorSet(contextVk, UniformBufferIndex));
Luc Ferron7a06ac12018-03-15 10:17:04 -0400747 ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
748 }
749
Jamie Madill76e471e2017-10-21 09:56:01 -0400750 return vk::NoError();
751}
752
753vk::Error ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
754{
Luc Ferron7a06ac12018-03-15 10:17:04 -0400755 std::array<VkDescriptorBufferInfo, MaxShaderIndex> descriptorBufferInfo;
756 std::array<VkWriteDescriptorSet, MaxShaderIndex> writeDescriptorInfo;
Jamie Madill76e471e2017-10-21 09:56:01 -0400757 uint32_t bufferCount = 0;
758
759 for (auto &uniformBlock : mDefaultUniformBlocks)
760 {
761 auto &bufferInfo = descriptorBufferInfo[bufferCount];
Luc Ferron7a06ac12018-03-15 10:17:04 -0400762 auto &writeInfo = writeDescriptorInfo[bufferCount];
Jamie Madill76e471e2017-10-21 09:56:01 -0400763
764 if (!uniformBlock.uniformData.empty())
765 {
Luc Ferron7a06ac12018-03-15 10:17:04 -0400766 bufferInfo.buffer = uniformBlock.storage.getCurrentBufferHandle();
Jamie Madill76e471e2017-10-21 09:56:01 -0400767 }
768 else
769 {
770 bufferInfo.buffer = mEmptyUniformBlockStorage.buffer.getHandle();
771 }
772
773 bufferInfo.offset = 0;
774 bufferInfo.range = VK_WHOLE_SIZE;
775
Jamie Madill76e471e2017-10-21 09:56:01 -0400776 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
777 writeInfo.pNext = nullptr;
Jamie Madill5547b382017-10-23 18:16:01 -0400778 writeInfo.dstSet = mDescriptorSets[0];
Jamie Madill76e471e2017-10-21 09:56:01 -0400779 writeInfo.dstBinding = bufferCount;
780 writeInfo.dstArrayElement = 0;
781 writeInfo.descriptorCount = 1;
Luc Ferron7a06ac12018-03-15 10:17:04 -0400782 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
Jamie Madill76e471e2017-10-21 09:56:01 -0400783 writeInfo.pImageInfo = nullptr;
784 writeInfo.pBufferInfo = &bufferInfo;
785 writeInfo.pTexelBufferView = nullptr;
786
787 bufferCount++;
788 }
789
790 VkDevice device = contextVk->getDevice();
791
792 vkUpdateDescriptorSets(device, bufferCount, writeDescriptorInfo.data(), 0, nullptr);
793
794 return vk::NoError();
795}
796
Jamie Madill5547b382017-10-23 18:16:01 -0400797const std::vector<VkDescriptorSet> &ProgramVk::getDescriptorSets() const
Jamie Madill76e471e2017-10-21 09:56:01 -0400798{
Jamie Madill5547b382017-10-23 18:16:01 -0400799 return mDescriptorSets;
800}
801
Luc Ferron7a06ac12018-03-15 10:17:04 -0400802const uint32_t *ProgramVk::getDynamicOffsets()
803{
804 // If we have no descriptor set being used, we do not need to specify any offsets when binding
805 // the descriptor sets.
806 if (!mUsedDescriptorSetRange.contains(0))
807 return nullptr;
808
809 return mUniformBlocksOffsets.data();
810}
811
812uint32_t ProgramVk::getDynamicOffsetsCount()
813{
814 if (!mUsedDescriptorSetRange.contains(0))
815 return 0;
816
817 return static_cast<uint32_t>(mUniformBlocksOffsets.size());
818}
819
Jamie Madill8c3988c2017-12-21 14:44:56 -0500820const gl::RangeUI &ProgramVk::getUsedDescriptorSetRange() const
Jamie Madill5547b382017-10-23 18:16:01 -0400821{
Jamie Madill8c3988c2017-12-21 14:44:56 -0500822 return mUsedDescriptorSetRange;
Jamie Madill5547b382017-10-23 18:16:01 -0400823}
824
Luc Ferron6ea1b412018-03-21 16:13:01 -0400825vk::Error ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
Jamie Madill5547b382017-10-23 18:16:01 -0400826{
827 if (mState.getSamplerBindings().empty() || !mDirtyTextures)
828 {
Luc Ferron6ea1b412018-03-21 16:13:01 -0400829 return vk::NoError();
Jamie Madill5547b382017-10-23 18:16:01 -0400830 }
831
Luc Ferron6ea1b412018-03-21 16:13:01 -0400832 ANGLE_TRY(allocateDescriptorSet(contextVk, TextureIndex));
833
Jamie Madill8c3988c2017-12-21 14:44:56 -0500834 ASSERT(mUsedDescriptorSetRange.contains(1));
835 VkDescriptorSet descriptorSet = mDescriptorSets[1];
Jamie Madill5547b382017-10-23 18:16:01 -0400836
837 // TODO(jmadill): Don't hard-code the texture limit.
838 ShaderTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
839 ShaderTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
840 uint32_t imageCount = 0;
841
842 const gl::State &glState = contextVk->getGLState();
843 const auto &completeTextures = glState.getCompleteTextureCache();
844
845 for (const auto &samplerBinding : mState.getSamplerBindings())
846 {
847 ASSERT(!samplerBinding.unreferenced);
848
849 // TODO(jmadill): Sampler arrays
850 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
851
852 GLuint textureUnit = samplerBinding.boundTextureUnits[0];
853 const gl::Texture *texture = completeTextures[textureUnit];
854
855 // TODO(jmadill): Incomplete textures handling.
856 ASSERT(texture);
857
Jamie Madille1f3ad42017-10-28 23:00:42 -0400858 TextureVk *textureVk = vk::GetImpl(texture);
Jamie Madill5547b382017-10-23 18:16:01 -0400859 const vk::Image &image = textureVk->getImage();
860
861 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
862
863 imageInfo.sampler = textureVk->getSampler().getHandle();
864 imageInfo.imageView = textureVk->getImageView().getHandle();
865 imageInfo.imageLayout = image.getCurrentLayout();
866
867 auto &writeInfo = writeDescriptorInfo[imageCount];
868
869 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
870 writeInfo.pNext = nullptr;
871 writeInfo.dstSet = descriptorSet;
872 writeInfo.dstBinding = imageCount;
873 writeInfo.dstArrayElement = 0;
874 writeInfo.descriptorCount = 1;
875 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
876 writeInfo.pImageInfo = &imageInfo;
877 writeInfo.pBufferInfo = nullptr;
878 writeInfo.pTexelBufferView = nullptr;
879
880 imageCount++;
881 }
882
883 VkDevice device = contextVk->getDevice();
884
885 ASSERT(imageCount > 0);
886 vkUpdateDescriptorSets(device, imageCount, writeDescriptorInfo.data(), 0, nullptr);
887
888 mDirtyTextures = false;
Luc Ferron6ea1b412018-03-21 16:13:01 -0400889 return vk::NoError();
Jamie Madill5547b382017-10-23 18:16:01 -0400890}
891
892void ProgramVk::invalidateTextures()
893{
894 mDirtyTextures = true;
Jamie Madill76e471e2017-10-21 09:56:01 -0400895}
896
Luc Ferron7a06ac12018-03-15 10:17:04 -0400897void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
898{
899 for (DefaultUniformBlock &block : mDefaultUniformBlocks)
900 {
901 block.storage.setMinimumSize(minSize);
902 }
903}
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400904} // namespace rx