Repository: google/filament
File: filament/backend/src/vulkan/VulkanDescriptorSetLayoutCache.cpp (C++)

Code before:
                stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
                alreadySeen.set(fragIndex);
            }
        } else if (!alreadySeen.test(index)) {
            // We are in fragment stage bits
            binding = (uint32_t) (index - fvkutils::getFragmentStageShift<Bitmask>());
            stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
        }

        if (stages) {
            toBind[count++] = {
                .binding = binding,
                .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                .descriptorCount = 1,
                .stageFlags = stages,
                .pImmutableSamplers = external[index] && immutableSamplerCount > immutableIndex
                                              ? &(immutableSamplers[immutableIndex++].second)
                                              : nullptr,
            };
        }
    });
    return count;
}

uint64_t computeImmutableSamplerHash(
        utils::FixedCapacityVector<std::pair<uint8_t, VkSampler>> const& samplers) {
    size_t const size = samplers.size();
    if (size == 0) {
        return 0;
    }
    return utils::hash::murmur3((uint32_t*) samplers.data(), samplers.size() * 2, 0);
}

} // anonymous namespace

VulkanDescriptorSetLayoutCache::VulkanDescriptorSetLayoutCache(VkDevice device,
        fvkmemory::ResourceManager* resourceManager)
    : mDevice(device),
      mResourceManager(resourceManager) {}

VulkanDescriptorSetLayoutCache::~VulkanDescriptorSetLayoutCache() = default;

void VulkanDescriptorSetLayoutCache::terminate() noexcept {
    for (auto& itr: mVkLayouts) {
        vkDestroyDescriptorSetLayout(mDevice, itr.second, VKALLOC);
    }
}

VkDescriptorSetLayout VulkanDescriptorSetLayoutCache::getVkLayout(
        VulkanDescriptorSetLayout::Bitmask const& bitmasks,
        fvkutils::SamplerBitmask externalSamplers,

Review comment (suggestion):
there's a potential packing issue here.  To be safe, you could probably just make this `std::pair<uint64_t, VkSampler>`

Code after:
                stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
                alreadySeen.set(fragIndex);
            }
        } else if (!alreadySeen.test(index)) {
            // We are in fragment stage bits
            binding = (uint32_t) (index - fvkutils::getFragmentStageShift<Bitmask>());
            stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
        }

        if (stages) {
            toBind[count++] = {
                .binding = binding,
                .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                .descriptorCount = 1,
                .stageFlags = stages,
                .pImmutableSamplers = external[index] && immutableSamplerCount > immutableIndex
                                              ? &(immutableSamplers[immutableIndex++].second)
                                              : nullptr,
            };
        }
    });
    return count;
}

uint64_t computeImmutableSamplerHash(
        utils::FixedCapacityVector<std::pair<uint64_t, VkSampler>> const& samplers) {
    size_t const size = samplers.size();
    if (size == 0) {
        return 0;
    }
    //64bit + 64bit per element = 4 words
    return utils::hash::murmur3((uint32_t*) samplers.data(), samplers.size() * 4, 0);
}

} // anonymous namespace

VulkanDescriptorSetLayoutCache::VulkanDescriptorSetLayoutCache(VkDevice device,
        fvkmemory::ResourceManager* resourceManager)
    : mDevice(device),
      mResourceManager(resourceManager) {}

VulkanDescriptorSetLayoutCache::~VulkanDescriptorSetLayoutCache() = default;

void VulkanDescriptorSetLayoutCache::terminate() noexcept {
    for (auto& itr: mVkLayouts) {
        vkDestroyDescriptorSetLayout(mDevice, itr.second, VKALLOC);
    }
}

VkDescriptorSetLayout VulkanDescriptorSetLayoutCache::getVkLayout(
        VulkanDescriptorSetLayout::Bitmask const& bitmasks,