blob: 9c3aa6ed72c3f7b0f4973fbcbdc4eedbdb779fb7 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/renderer/backend/vulkan/yuv_conversion_vk.h"
#include "flutter/fml/hash_combine.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/vulkan/device_holder_vk.h"
#include "impeller/renderer/backend/vulkan/sampler_vk.h"
namespace impeller {
YUVConversionVK::YUVConversionVK(const vk::Device& device,
const YUVConversionDescriptorVK& chain)
: chain_(chain) {
auto conversion = device.createSamplerYcbcrConversionUnique(chain_.get());
if (conversion.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Could not create YUV conversion: "
<< vk::to_string(conversion.result);
return;
}
conversion_ = std::move(conversion.value);
}
YUVConversionVK::~YUVConversionVK() = default;
bool YUVConversionVK::IsValid() const {
return conversion_ && !!conversion_.get();
}
vk::SamplerYcbcrConversion YUVConversionVK::GetConversion() const {
return conversion_ ? conversion_.get()
: static_cast<vk::SamplerYcbcrConversion>(VK_NULL_HANDLE);
}
const YUVConversionDescriptorVK& YUVConversionVK::GetDescriptor() const {
return chain_;
}
std::size_t YUVConversionDescriptorVKHash::operator()(
const YUVConversionDescriptorVK& desc) const {
// Hashers in Vulkan HPP hash the pNext member which isn't what we want for
// these to be stable.
const auto& conv = desc.get();
std::size_t hash = fml::HashCombine(conv.format, //
conv.ycbcrModel, //
conv.ycbcrRange, //
conv.components.r, //
conv.components.g, //
conv.components.b, //
conv.components.a, //
conv.xChromaOffset, //
conv.yChromaOffset, //
conv.chromaFilter, //
conv.forceExplicitReconstruction //
);
#if FML_OS_ANDROID
const auto external_format = desc.get<vk::ExternalFormatANDROID>();
fml::HashCombineSeed(hash, external_format.externalFormat);
#endif // FML_OS_ANDROID
return hash;
};
bool YUVConversionDescriptorVKEqual::operator()(
const YUVConversionDescriptorVK& lhs_desc,
const YUVConversionDescriptorVK& rhs_desc) const {
// Default equality checks in Vulkan HPP checks pNext member members by
// pointer which isn't what we want.
{
const auto& lhs = lhs_desc.get();
const auto& rhs = rhs_desc.get();
if (lhs.format != rhs.format || //
lhs.ycbcrModel != rhs.ycbcrModel || //
lhs.ycbcrRange != rhs.ycbcrRange || //
lhs.components.r != rhs.components.r || //
lhs.components.g != rhs.components.g || //
lhs.components.b != rhs.components.b || //
lhs.components.a != rhs.components.a || //
lhs.xChromaOffset != rhs.xChromaOffset || //
lhs.yChromaOffset != rhs.yChromaOffset || //
lhs.chromaFilter != rhs.chromaFilter || //
lhs.forceExplicitReconstruction != rhs.forceExplicitReconstruction //
) {
return false;
}
}
#if FML_OS_ANDROID
{
const auto lhs = lhs_desc.get<vk::ExternalFormatANDROID>();
const auto rhs = rhs_desc.get<vk::ExternalFormatANDROID>();
return lhs.externalFormat == rhs.externalFormat;
}
#else // FML_OS_ANDROID
return true;
#endif // FML_OS_ANDROID
}
ImmutableSamplerKeyVK::ImmutableSamplerKeyVK(const SamplerVK& sampler)
: sampler(sampler.GetDescriptor()) {
if (const auto& conversion = sampler.GetYUVConversion()) {
yuv_conversion = conversion->GetDescriptor();
}
}
bool ImmutableSamplerKeyVK::IsEqual(const ImmutableSamplerKeyVK& other) const {
return sampler.IsEqual(other.sampler) &&
YUVConversionDescriptorVKEqual{}(yuv_conversion, other.yuv_conversion);
}
std::size_t ImmutableSamplerKeyVK::GetHash() const {
return fml::HashCombine(sampler.GetHash(),
YUVConversionDescriptorVKHash{}(yuv_conversion));
}
} // namespace impeller