Пример #1
0
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();
}