gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext) { ContextVk *contextVk = vk::GetImpl(glContext); VkDevice device = contextVk->getDevice(); // Process vertex and fragment uniforms into std140 packing. std::array<sh::BlockLayoutMap, 2> layoutMap; std::array<size_t, 2> requiredBufferSize = {{0, 0}}; for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex) { ANGLE_TRY(InitDefaultUniformBlock(glContext, device, GetShader(mState, shaderIndex), &mDefaultUniformBlocks[shaderIndex].storage, &layoutMap[shaderIndex], &requiredBufferSize[shaderIndex])); } // Init the default block layout info. const auto &locations = mState.getUniformLocations(); const auto &uniforms = mState.getUniforms(); for (size_t locationIndex = 0; locationIndex < locations.size(); ++locationIndex) { std::array<sh::BlockMemberInfo, 2> layoutInfo; const auto &location = locations[locationIndex]; if (location.used() && !location.ignored) { const auto &uniform = uniforms[location.index]; if (uniform.isSampler()) continue; std::string uniformName = uniform.name; if (uniform.isArray()) { uniformName += ArrayString(location.arrayIndex); } bool found = false; for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex) { auto it = layoutMap[shaderIndex].find(uniformName); if (it != layoutMap[shaderIndex].end()) { found = true; layoutInfo[shaderIndex] = it->second; } } ASSERT(found); } for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex) { mDefaultUniformBlocks[shaderIndex].uniformLayout.push_back(layoutInfo[shaderIndex]); } } bool anyDirty = false; bool allDirty = true; for (uint32_t shaderIndex = MinShaderIndex; shaderIndex < MaxShaderIndex; ++shaderIndex) { if (requiredBufferSize[shaderIndex] > 0) { if (!mDefaultUniformBlocks[shaderIndex].uniformData.resize( requiredBufferSize[shaderIndex])) { return gl::OutOfMemory() << "Memory allocation failure."; } mDefaultUniformBlocks[shaderIndex].uniformData.fill(0); mDefaultUniformBlocks[shaderIndex].uniformsDirty = true; anyDirty = true; } else { allDirty = false; } } if (anyDirty) { // Initialize the "empty" uniform block if necessary. if (!allDirty) { VkBufferCreateInfo uniformBufferInfo; uniformBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; uniformBufferInfo.pNext = nullptr; uniformBufferInfo.flags = 0; uniformBufferInfo.size = 1; uniformBufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; uniformBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; uniformBufferInfo.queueFamilyIndexCount = 0; uniformBufferInfo.pQueueFamilyIndices = nullptr; ANGLE_TRY(mEmptyUniformBlockStorage.buffer.init(device, uniformBufferInfo)); size_t requiredSize = 0; ANGLE_TRY(AllocateBufferMemory(contextVk, 1, &mEmptyUniformBlockStorage.buffer, &mEmptyUniformBlockStorage.memory, &requiredSize)); } ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk)); } else { // If the program has no uniforms, note this in the offset. mDescriptorSetOffset = 1; } return gl::NoError(); }