blob: 1f1fa0a075c51cab772128bde91bdb2d30a8c3dd [file] [log] [blame]
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// vk_format_utils:
// Helper for Vulkan format code.
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/load_functions_table.h"
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
namespace rx
{
namespace
{
constexpr VkFormatFeatureFlags kNecessaryBitsFullSupportDepthStencil =
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
constexpr VkFormatFeatureFlags kNecessaryBitsFullSupportColor =
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
bool HasFormatFeatureBits(const VkFormatFeatureFlags featureBits,
const VkFormatProperties &formatProperties)
{
return IsMaskFlagSet(formatProperties.optimalTilingFeatures, featureBits);
}
void FillTextureFormatCaps(const VkFormatProperties &formatProperties,
gl::TextureCaps *outTextureCaps)
{
outTextureCaps->texturable =
HasFormatFeatureBits(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, formatProperties);
outTextureCaps->filterable =
HasFormatFeatureBits(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT, formatProperties);
outTextureCaps->renderable =
HasFormatFeatureBits(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, formatProperties) ||
HasFormatFeatureBits(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT, formatProperties);
}
} // anonymous namespace
namespace vk
{
void GetFormatProperties(VkPhysicalDevice physicalDevice,
VkFormat vkFormat,
VkFormatProperties *propertiesOut)
{
// Try filling out the info from our hard coded format data, if we can't find the
// information we need, we'll make the call to Vulkan.
const VkFormatProperties &formatProperties = vk::GetMandatoryFormatSupport(vkFormat);
// Once we filled what we could with the mandatory texture caps, we verify if
// all the bits we need to satify all our checks are present, and if so we can
// skip the device call.
if (!IsMaskFlagSet(formatProperties.optimalTilingFeatures, kNecessaryBitsFullSupportColor) &&
!IsMaskFlagSet(formatProperties.optimalTilingFeatures,
kNecessaryBitsFullSupportDepthStencil))
{
vkGetPhysicalDeviceFormatProperties(physicalDevice, vkFormat, propertiesOut);
}
else
{
*propertiesOut = formatProperties;
}
}
bool HasFullFormatSupport(VkPhysicalDevice physicalDevice, VkFormat vkFormat)
{
VkFormatProperties formatProperties;
GetFormatProperties(physicalDevice, vkFormat, &formatProperties);
constexpr uint32_t kBitsColor =
(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
constexpr uint32_t kBitsDepth = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
return HasFormatFeatureBits(kBitsColor, formatProperties) ||
HasFormatFeatureBits(kBitsDepth, formatProperties);
}
// Format implementation.
Format::Format()
: internalFormat(GL_NONE),
textureFormatID(angle::Format::ID::NONE),
vkTextureFormat(VK_FORMAT_UNDEFINED),
bufferFormatID(angle::Format::ID::NONE),
vkBufferFormat(VK_FORMAT_UNDEFINED),
dataInitializerFunction(nullptr),
loadFunctions()
{
}
const angle::Format &Format::textureFormat() const
{
return angle::Format::Get(textureFormatID);
}
const angle::Format &Format::bufferFormat() const
{
return angle::Format::Get(bufferFormatID);
}
bool operator==(const Format &lhs, const Format &rhs)
{
return &lhs == &rhs;
}
bool operator!=(const Format &lhs, const Format &rhs)
{
return &lhs != &rhs;
}
// FormatTable implementation.
FormatTable::FormatTable()
{
}
FormatTable::~FormatTable()
{
}
void FormatTable::initialize(VkPhysicalDevice physicalDevice,
gl::TextureCapsMap *outTextureCapsMap,
std::vector<GLenum> *outCompressedTextureFormats)
{
for (size_t formatIndex = 0; formatIndex < angle::kNumANGLEFormats; ++formatIndex)
{
const auto formatID = static_cast<angle::Format::ID>(formatIndex);
const angle::Format &angleFormat = angle::Format::Get(formatID);
mFormatData[formatIndex].initialize(physicalDevice, angleFormat);
const GLenum internalFormat = mFormatData[formatIndex].internalFormat;
mFormatData[formatIndex].loadFunctions =
GetLoadFunctionsMap(internalFormat, mFormatData[formatIndex].textureFormatID);
if (!mFormatData[formatIndex].valid())
{
continue;
}
const VkFormat vkFormat = mFormatData[formatIndex].vkTextureFormat;
// Try filling out the info from our hard coded format data, if we can't find the
// information we need, we'll make the call to Vulkan.
VkFormatProperties formatProperties;
GetFormatProperties(physicalDevice, vkFormat, &formatProperties);
gl::TextureCaps textureCaps;
FillTextureFormatCaps(formatProperties, &textureCaps);
outTextureCapsMap->set(formatID, textureCaps);
if (angleFormat.isBlock)
{
outCompressedTextureFormats->push_back(internalFormat);
}
}
}
const Format &FormatTable::operator[](GLenum internalFormat) const
{
angle::Format::ID formatID = angle::Format::InternalFormatToID(internalFormat);
return mFormatData[static_cast<size_t>(formatID)];
}
// TODO(jmadill): This is temporary. Figure out how to handle format conversions.
VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat)
{
switch (vertexFormat)
{
case gl::VERTEX_FORMAT_INVALID:
UNREACHABLE();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE1:
return VK_FORMAT_R8_SINT;
case gl::VERTEX_FORMAT_SBYTE1_NORM:
return VK_FORMAT_R8_SNORM;
case gl::VERTEX_FORMAT_SBYTE2:
return VK_FORMAT_R8G8_SINT;
case gl::VERTEX_FORMAT_SBYTE2_NORM:
return VK_FORMAT_R8G8_SNORM;
case gl::VERTEX_FORMAT_SBYTE3:
return VK_FORMAT_R8G8B8_SINT;
case gl::VERTEX_FORMAT_SBYTE3_NORM:
return VK_FORMAT_R8G8B8_SNORM;
case gl::VERTEX_FORMAT_SBYTE4:
return VK_FORMAT_R8G8B8A8_SINT;
case gl::VERTEX_FORMAT_SBYTE4_NORM:
return VK_FORMAT_R8G8B8A8_SNORM;
case gl::VERTEX_FORMAT_UBYTE1:
return VK_FORMAT_R8_UINT;
case gl::VERTEX_FORMAT_UBYTE1_NORM:
return VK_FORMAT_R8_UNORM;
case gl::VERTEX_FORMAT_UBYTE2:
return VK_FORMAT_R8G8_UINT;
case gl::VERTEX_FORMAT_UBYTE2_NORM:
return VK_FORMAT_R8G8_UNORM;
case gl::VERTEX_FORMAT_UBYTE3:
return VK_FORMAT_R8G8B8_UINT;
case gl::VERTEX_FORMAT_UBYTE3_NORM:
return VK_FORMAT_R8G8B8_UNORM;
case gl::VERTEX_FORMAT_UBYTE4:
return VK_FORMAT_R8G8B8A8_UINT;
case gl::VERTEX_FORMAT_UBYTE4_NORM:
return VK_FORMAT_R8G8B8A8_UNORM;
case gl::VERTEX_FORMAT_SSHORT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT1_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT2_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT3_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT4_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SBYTE4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UBYTE4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SSHORT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_USHORT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT1_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT2_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT3_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT4_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FIXED4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF1:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF2:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF3:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_HALF4:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_FLOAT1:
return VK_FORMAT_R32_SFLOAT;
case gl::VERTEX_FORMAT_FLOAT2:
return VK_FORMAT_R32G32_SFLOAT;
case gl::VERTEX_FORMAT_FLOAT3:
return VK_FORMAT_R32G32B32_SFLOAT;
case gl::VERTEX_FORMAT_FLOAT4:
return VK_FORMAT_R32G32B32A32_SFLOAT;
case gl::VERTEX_FORMAT_SINT210:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT210:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT210_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT210_NORM:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_SINT210_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
case gl::VERTEX_FORMAT_UINT210_INT:
UNIMPLEMENTED();
return VK_FORMAT_UNDEFINED;
default:
UNREACHABLE();
return VK_FORMAT_UNDEFINED;
}
}
} // namespace vk
} // namespace rx