blob: cf27865af812968f2ee6a34c579591349ca38f7d [file] [log] [blame]
/*
* Copyright 2023 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/graphite/vk/VulkanYcbcrConversion.h"
#include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
#include "src/gpu/graphite/vk/VulkanCaps.h"
#include "src/gpu/graphite/vk/VulkanGraphiteUtils.h"
#include "src/gpu/graphite/vk/VulkanSharedContext.h"
namespace skgpu::graphite {
namespace {
static constexpr int kUsesExternalFormatBits = 1;
static constexpr int kYcbcrModelBits = 3;
static constexpr int kYcbcrRangeBits = 1;
static constexpr int kXChromaOffsetBits = 1;
static constexpr int kYChromaOffsetBits = 1;
static constexpr int kChromaFilterBits = 1;
static constexpr int kForceExplicitReconBits = 1;
static constexpr int kComponentBits = 3;
static constexpr int kUsesExternalFormatShift = 0;
static constexpr int kYcbcrModelShift = kUsesExternalFormatShift +
kUsesExternalFormatBits;
static constexpr int kYcbcrRangeShift = kYcbcrModelShift + kYcbcrModelBits;
static constexpr int kXChromaOffsetShift = kYcbcrRangeShift + kYcbcrRangeBits;
static constexpr int kYChromaOffsetShift = kXChromaOffsetShift + kXChromaOffsetBits;
static constexpr int kChromaFilterShift = kYChromaOffsetShift + kYChromaOffsetBits;
static constexpr int kForceExplicitReconShift = kChromaFilterShift + kChromaFilterBits;
static constexpr int kComponentRShift = kForceExplicitReconShift + kComponentBits;
static constexpr int kComponentGShift = kComponentRShift + kComponentBits;
static constexpr int kComponentBShift = kComponentGShift + kComponentBits;
static constexpr int kComponentAShift = kComponentBShift + kComponentBits;
static constexpr uint32_t kUseExternalFormatMask =
((1 << kUsesExternalFormatBits) - 1) << kUsesExternalFormatShift;
static constexpr uint32_t kYcbcrModelMask =
((1 << kYcbcrModelBits) - 1) << kYcbcrModelShift;
static constexpr uint32_t kYcbcrRangeMask =
((1 << kYcbcrRangeBits) - 1) << kYcbcrRangeShift;
static constexpr uint32_t kXChromaOffsetMask =
((1 << kXChromaOffsetBits) - 1) << kXChromaOffsetShift;
static constexpr uint32_t kYChromaOffsetMask =
((1 << kYChromaOffsetBits) - 1) << kYChromaOffsetShift;
static constexpr uint32_t kChromaFilterMask =
((1 << kChromaFilterBits) - 1) << kChromaFilterShift;
static constexpr uint32_t kForceExplicitReconMask =
((1 << kForceExplicitReconBits) - 1) << kForceExplicitReconShift;
static constexpr uint32_t kComponentRMask = ((1 << kComponentBits) - 1) << kComponentRShift;
static constexpr uint32_t kComponentBMask = ((1 << kComponentBits) - 1) << kComponentGShift;
static constexpr uint32_t kComponentGMask = ((1 << kComponentBits) - 1) << kComponentBShift;
static constexpr uint32_t kComponentAMask = ((1 << kComponentBits) - 1) << kComponentAShift;
} // anonymous namespace
sk_sp<VulkanYcbcrConversion> VulkanYcbcrConversion::Make(
const VulkanSharedContext* context, const VulkanYcbcrConversionInfo& conversionInfo) {
if (!context->vulkanCaps().supportsYcbcrConversion()) {
return nullptr;
}
VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo;
skgpu::SetupSamplerYcbcrConversionInfo(&ycbcrCreateInfo, conversionInfo);
#ifdef SK_BUILD_FOR_ANDROID
VkExternalFormatANDROID externalFormat;
if (conversionInfo.fExternalFormat) {
// Format must not be specified for external images.
SkASSERT(conversionInfo.fFormat == VK_FORMAT_UNDEFINED);
externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
externalFormat.pNext = nullptr;
externalFormat.externalFormat = conversionInfo.fExternalFormat;
SkASSERT(ycbcrCreateInfo.pNext == nullptr);
ycbcrCreateInfo.pNext = &externalFormat;
}
#else
// External images are supported only on Android.
SkASSERT(!conversionInfo.fExternalFormat);
#endif
if (!conversionInfo.fExternalFormat) {
SkASSERT(conversionInfo.fFormat != VK_FORMAT_UNDEFINED);
}
VkSamplerYcbcrConversion conversion;
VkResult result;
VULKAN_CALL_RESULT(context,
result,
CreateSamplerYcbcrConversion(
context->device(), &ycbcrCreateInfo, nullptr, &conversion));
if (result != VK_SUCCESS) {
return nullptr;
}
return sk_sp<VulkanYcbcrConversion>(new VulkanYcbcrConversion(context, conversion));
}
ImmutableSamplerInfo VulkanYcbcrConversion::ToImmutableSamplerInfo(
const VulkanYcbcrConversionInfo& conversionInfo) {
SkASSERT(conversionInfo.isValid());
static_assert(kComponentAShift + kComponentBits <= 32);
SkASSERT(conversionInfo.fYcbcrModel < (1u << kYcbcrModelBits ));
SkASSERT(conversionInfo.fYcbcrRange < (1u << kYcbcrRangeBits ));
SkASSERT(conversionInfo.fXChromaOffset < (1u << kXChromaOffsetBits ));
SkASSERT(conversionInfo.fYChromaOffset < (1u << kYChromaOffsetBits ));
SkASSERT(conversionInfo.fChromaFilter < (1u << kChromaFilterBits ));
SkASSERT(conversionInfo.fForceExplicitReconstruction < (1u << kForceExplicitReconBits));
SkASSERT(conversionInfo.fComponents.r < (1u << kComponentBits ));
SkASSERT(conversionInfo.fComponents.g < (1u << kComponentBits ));
SkASSERT(conversionInfo.fComponents.b < (1u << kComponentBits ));
SkASSERT(conversionInfo.fComponents.a < (1u << kComponentBits ));
const bool usesExternalFormat = conversionInfo.fFormat == VK_FORMAT_UNDEFINED;
ImmutableSamplerInfo info;
info.fNonFormatYcbcrConversionInfo =
(((uint32_t)(usesExternalFormat ) << kUsesExternalFormatShift) |
((uint32_t)(conversionInfo.fYcbcrModel ) << kYcbcrModelShift ) |
((uint32_t)(conversionInfo.fYcbcrRange ) << kYcbcrRangeShift ) |
((uint32_t)(conversionInfo.fXChromaOffset ) << kXChromaOffsetShift ) |
((uint32_t)(conversionInfo.fYChromaOffset ) << kYChromaOffsetShift ) |
((uint32_t)(conversionInfo.fChromaFilter ) << kChromaFilterShift ) |
((uint32_t)(conversionInfo.fForceExplicitReconstruction) << kForceExplicitReconShift) |
((uint32_t)(conversionInfo.fComponents.r ) << kComponentRShift ) |
((uint32_t)(conversionInfo.fComponents.g ) << kComponentGShift ) |
((uint32_t)(conversionInfo.fComponents.b ) << kComponentBShift ) |
((uint32_t)(conversionInfo.fComponents.a ) << kComponentAShift ));
info.fFormat = usesExternalFormat ? conversionInfo.fExternalFormat : conversionInfo.fFormat;
return info;
}
VulkanYcbcrConversionInfo VulkanYcbcrConversion::FromImmutableSamplerInfo(
ImmutableSamplerInfo info) {
const uint32_t nonFormatInfo = info.fNonFormatYcbcrConversionInfo;
VulkanYcbcrConversionInfo vkInfo;
const bool usesExternalFormat =
(nonFormatInfo >> kUsesExternalFormatShift) & kUseExternalFormatMask;
if (usesExternalFormat) {
vkInfo.fFormat = VK_FORMAT_UNDEFINED;
vkInfo.fExternalFormat = info.fFormat;
} else {
vkInfo.fFormat = static_cast<VkFormat>(info.fFormat);
vkInfo.fExternalFormat = 0;
}
vkInfo.fYcbcrModel = static_cast<VkSamplerYcbcrModelConversion>(
(nonFormatInfo & kYcbcrModelMask) >> kYcbcrModelShift);
vkInfo.fYcbcrRange = static_cast<VkSamplerYcbcrRange>(
(nonFormatInfo & kYcbcrRangeMask) >> kYcbcrRangeShift);
vkInfo.fComponents = { static_cast<VkComponentSwizzle>(
(nonFormatInfo & kComponentRMask) >> kComponentRShift),
static_cast<VkComponentSwizzle>(
(nonFormatInfo & kComponentGMask) >> kComponentGShift),
static_cast<VkComponentSwizzle>(
(nonFormatInfo & kComponentBMask) >> kComponentBShift),
static_cast<VkComponentSwizzle>(
(nonFormatInfo & kComponentAMask) >> kComponentAShift) };
vkInfo.fXChromaOffset = static_cast<VkChromaLocation>(
(nonFormatInfo & kXChromaOffsetMask) >> kXChromaOffsetShift);
vkInfo.fYChromaOffset = static_cast<VkChromaLocation>(
(nonFormatInfo & kYChromaOffsetMask) >> kYChromaOffsetShift);
vkInfo.fChromaFilter = static_cast<VkFilter>(
(nonFormatInfo & kChromaFilterMask) >> kChromaFilterShift);
vkInfo.fForceExplicitReconstruction = static_cast<VkBool32>(
(nonFormatInfo & kForceExplicitReconMask) >> kForceExplicitReconShift);
return vkInfo;
}
VulkanYcbcrConversion::VulkanYcbcrConversion(const VulkanSharedContext* context,
VkSamplerYcbcrConversion ycbcrConversion)
: Resource(context,
Ownership::kOwned,
/*gpuMemorySize=*/0)
, fYcbcrConversion (ycbcrConversion) {}
void VulkanYcbcrConversion::freeGpuData() {
auto sharedContext = static_cast<const VulkanSharedContext*>(this->sharedContext());
SkASSERT(fYcbcrConversion != VK_NULL_HANDLE);
VULKAN_CALL(sharedContext->interface(),
DestroySamplerYcbcrConversion(sharedContext->device(), fYcbcrConversion, nullptr));
}
} // namespace skgpu::graphite