Commit d50537a7 by Luc Ferron Committed by Commit Bot

Vulkan: Texture caps map

We are generating the caps map using various bits from the results of vkGetPhysicalDeviceFormatProperties. This contains all the information required to fill out "renderable", "texturable" and "filterable". Later we'll need to read from vkGetPhysicalDeviceImageFormatProperties as well to get the sampleCounts. The tests for now are not very meaningful since they use the same logic as the caps code to build the expected results, however as soon as we'll add the hard-coded list of mandatory texture caps, the test will be a good validator that we are not breaking anything. We only check the optimal set of flags since it is the most restrictive set. isTexturable = flags contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT isFilterable = flags contain VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT isRenderable = flags contain VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT OR VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT Bug: angleproject:2348 Change-Id: I9da0712190d2678d7e377d6fcd4ca83d23eefd38 Reviewed-on: https://chromium-review.googlesource.com/908712 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent defe3937
......@@ -392,7 +392,8 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
mGlslangWrapper = GlslangWrapper::GetReference();
// Initialize the format table.
mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps);
mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps,
&mNativeCaps.compressedTextureFormats);
// Initialize the pipeline layout for GL programs.
ANGLE_TRY(initGraphicsPipelineLayout());
......@@ -562,7 +563,7 @@ void RendererVk::ensureCapsInitialized() const
{
if (!mCapsInitialized)
{
vk::GenerateCaps(mPhysicalDeviceProperties, &mNativeCaps, &mNativeTextureCaps,
vk::GenerateCaps(mPhysicalDeviceProperties, mNativeTextureCaps, &mNativeCaps,
&mNativeExtensions, &mNativeLimitations);
mCapsInitialized = true;
}
......
......@@ -9,10 +9,16 @@
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
#include "libANGLE/Caps.h"
#include "vk_format_utils.h"
namespace
{
constexpr unsigned int kComponentsPerVector = 4;
bool HasFormatFeatureBits(const VkFormatFeatureFlags featureBits,
const VkFormatProperties &formatProperties)
{
return (formatProperties.optimalTilingFeatures & featureBits) == featureBits;
}
}
namespace rx
......@@ -21,11 +27,13 @@ namespace vk
{
void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
const gl::TextureCapsMap &textureCaps,
gl::Caps *outCaps,
gl::TextureCapsMap * /*outTextureCaps*/,
gl::Extensions *outExtensions,
gl::Limitations * /* outLimitations */)
{
outExtensions->setTextureExtensionSupport(textureCaps);
// Enable this for simple buffer readback testing, but some functionality is missing.
// TODO(jmadill): Support full mapBufferRange extension.
outExtensions->mapBuffer = true;
......@@ -119,5 +127,19 @@ void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
// TODO(jmadill): count reserved varyings
outCaps->maxVaryingVectors = physicalDeviceProperties.limits.maxVertexOutputComponents / 4;
}
gl::TextureCaps GenerateTextureFormatCaps(const VkFormatProperties &formatProperties)
{
gl::TextureCaps textureCaps;
textureCaps.texturable =
HasFormatFeatureBits(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, formatProperties);
textureCaps.filterable =
HasFormatFeatureBits(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT, formatProperties);
textureCaps.renderable =
HasFormatFeatureBits(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, formatProperties) ||
HasFormatFeatureBits(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT, formatProperties);
return textureCaps;
}
} // namespace vk
} // namespace rx
......@@ -18,6 +18,7 @@ struct Limitations;
struct Extensions;
class TextureCapsMap;
struct Caps;
struct TextureCaps;
}
namespace rx
......@@ -25,12 +26,15 @@ namespace rx
namespace vk
{
class FormatTable;
void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
const gl::TextureCapsMap &textureCaps,
gl::Caps *outCaps,
gl::TextureCapsMap * /*outTextureCaps*/,
gl::Extensions *outExtensions,
gl::Limitations * /* outLimitations */);
gl::TextureCaps GenerateTextureFormatCaps(const VkFormatProperties &formatProperties);
} // namespace vk
} // namespace rx
......
......@@ -10,6 +10,7 @@
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/load_functions_table.h"
#include "vk_caps_utils.h"
namespace rx
{
......@@ -46,16 +47,38 @@ FormatTable::~FormatTable()
{
}
void FormatTable::initialize(VkPhysicalDevice physicalDevice, gl::TextureCapsMap *textureCapsMap)
void FormatTable::initialize(VkPhysicalDevice physicalDevice,
gl::TextureCapsMap *outTextureCapsMap,
std::vector<GLenum> *outCompressedTextureFormats)
{
for (size_t formatIndex = 0; formatIndex < angle::kNumANGLEFormats; ++formatIndex)
{
angle::Format::ID formatID = static_cast<angle::Format::ID>(formatIndex);
const angle::Format::ID 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);
mFormatData[formatIndex].loadFunctions = GetLoadFunctionsMap(
mFormatData[formatIndex].internalFormat, mFormatData[formatIndex].textureFormatID);
if (!mFormatData[formatIndex].valid())
{
// TODO(lucferron): Implement support for more OpenGL Texture formats
// http://anglebug.com/2358
continue;
}
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(
physicalDevice, mFormatData[formatIndex].vkTextureFormat, &formatProperties);
const gl::TextureCaps textureCaps = GenerateTextureFormatCaps(formatProperties);
outTextureCapsMap->set(formatID, textureCaps);
// TODO(lucferron): Optimize this by including compressed bool in the FormatID
// http://anglebug.com/2358
if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
{
outCompressedTextureFormats->push_back(internalFormat);
}
}
}
......
......@@ -32,6 +32,8 @@ struct Format final : private angle::NonCopyable
{
Format();
bool valid() const { return internalFormat != 0; }
// This is an auto-generated method in vk_format_table_autogen.cpp.
void initialize(VkPhysicalDevice physicalDevice, const angle::Format &angleFormat);
......@@ -53,8 +55,10 @@ class FormatTable final : angle::NonCopyable
FormatTable();
~FormatTable();
// Also initializes the TextureCapsMap.
void initialize(VkPhysicalDevice physicalDevice, gl::TextureCapsMap *textureCapsMap);
// Also initializes the TextureCapsMap and the compressedTextureCaps in the Caps instance.
void initialize(VkPhysicalDevice physicalDevice,
gl::TextureCapsMap *outTextureCapsMap,
std::vector<GLenum> *outCompressedTextureFormats);
const Format &operator[](GLenum internalFormat) const;
......
......@@ -216,6 +216,10 @@ if (is_win || is_linux || is_mac || is_android) {
sources += [ "angle_end2end_tests_main.cpp" ]
}
if (angle_enable_vulkan) {
sources += [ "gl_tests/VulkanFormatTablesTest.cpp" ]
}
configs += [
angle_root + ":internal_config",
angle_root + ":libANGLE_config",
......
//
// Copyright 2018 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.
//
// VulkanFormatTablesTest:
// Tests to validate our Vulkan support tables match hardware support.
//
#include "libANGLE/Context.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "test_utils/ANGLETest.h"
#include "test_utils/angle_test_instantiate.h"
using namespace angle;
namespace
{
class VulkanFormatTablesTest : public ANGLETest
{
};
struct ParametersToTest
{
VkImageType imageType;
VkImageCreateFlags createFlags;
};
// This test enumerates all GL formats - for each, it queries the Vulkan support for
// using it as a texture, filterable, and a render target. It checks this against our
// speed-optimized baked tables, and validates they would give the same result.
TEST_P(VulkanFormatTablesTest, TestFormatSupport)
{
ASSERT_TRUE(IsVulkan());
// Hack the angle!
const gl::Context *context = reinterpret_cast<gl::Context *>(getEGLWindow()->getContext());
auto *contextVk = rx::GetImplAs<rx::ContextVk>(context);
rx::RendererVk *renderer = contextVk->getRenderer();
// We need to test normal 2D images as well as Cube images.
const std::vector<ParametersToTest> parametersToTest = {
{VK_IMAGE_TYPE_2D, 0}, {VK_IMAGE_TYPE_2D, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT}};
const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
for (GLenum internalFormat : allFormats)
{
const rx::vk::Format &vkFormat = renderer->getFormat(internalFormat);
// Similar loop as when we build caps in vk_caps_utils.cpp, but query using
// vkGetPhysicalDeviceImageFormatProperties instead of vkGetPhysicalDeviceFormatProperties
// and verify we have all the same caps.
if (!vkFormat.valid())
{
// TODO(jmadill): Every angle format should be mapped to a vkFormat.
// This hasn't been defined in our vk_format_map.json yet so the caps won't be filled.
continue;
}
const gl::TextureCaps &textureCaps = renderer->getNativeTextureCaps().get(internalFormat);
for (const ParametersToTest params : parametersToTest)
{
// Now lets verify that that agaisnt vulkan.
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(renderer->getPhysicalDevice(),
vkFormat.vkTextureFormat, &formatProperties);
VkImageFormatProperties imageProperties;
// isTexturable?
bool isTexturable =
vkGetPhysicalDeviceImageFormatProperties(
renderer->getPhysicalDevice(), vkFormat.vkTextureFormat, params.imageType,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, params.createFlags,
&imageProperties) == VK_SUCCESS;
EXPECT_EQ(isTexturable, textureCaps.texturable) << vkFormat.vkTextureFormat;
// TODO(jmadill): Support ES3 textures.
// isFilterable?
bool isFilterable = (formatProperties.optimalTilingFeatures &
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ==
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
EXPECT_EQ(isFilterable, textureCaps.filterable) << vkFormat.vkTextureFormat;
// isRenderable?
const bool isRenderableColor =
(vkGetPhysicalDeviceImageFormatProperties(
renderer->getPhysicalDevice(), vkFormat.vkTextureFormat, params.imageType,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
params.createFlags, &imageProperties)) == VK_SUCCESS;
const bool isRenderableDepthStencil =
(vkGetPhysicalDeviceImageFormatProperties(
renderer->getPhysicalDevice(), vkFormat.vkTextureFormat, params.imageType,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
params.createFlags, &imageProperties)) == VK_SUCCESS;
bool isRenderable = isRenderableColor || isRenderableDepthStencil;
EXPECT_EQ(isRenderable, textureCaps.renderable) << vkFormat.vkTextureFormat;
}
}
}
ANGLE_INSTANTIATE_TEST(VulkanFormatTablesTest, ES2_VULKAN());
} // anonymous namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment