Commit 6a89d227 by Jamie Madill Committed by Commit Bot

Vulkan: Refactor format table.

This moves the Vulkan format table to dynamically generated, but keeps it easily indexed. Because Vulkan format support is not able to be fully determined until runtime, we'll need a dynamic way to build the table. The most straight-forward way seems to be to keep a copy of the full table in the Renderer. Initializing it once at startup makes it a bit slower to init, but saves us from any threading shenanigans with lazy init when (and if) we ever support multi- threaded Contexts. BUG=angleproject:2207 Change-Id: Ib1ac879daa562c7ad1a965390be401fa2314e42c Reviewed-on: https://chromium-review.googlesource.com/742374 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent d10cf69e
......@@ -139,4 +139,6 @@ enum class Format::ID
S8_UINT
};
constexpr uint32_t kNumANGLEFormats = 125;
} // namespace angle
......@@ -32,6 +32,8 @@ enum class Format::ID
{angle_format_enum}
}};
constexpr uint32_t kNumANGLEFormats = {num_angle_formats};
}} // namespace angle
"""
......@@ -254,11 +256,13 @@ with open('Format_table_autogen.cpp', 'wt') as out_file:
out_file.close()
enum_data = gen_enum_string(all_angle)
num_angle_formats = len(all_angle)
output_h = template_autogen_h.format(
script_name = sys.argv[0],
copyright_year = date.today().year,
angle_format_enum = enum_data,
data_source_name = data_source_name)
data_source_name = data_source_name,
num_angle_formats = num_angle_formats)
with open('Format_ID_autogen.inl', 'wt') as out_file:
out_file.write(output_h)
out_file.close()
......@@ -343,6 +343,9 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
mGlslangWrapper = GlslangWrapper::GetReference();
// Initialize the format table.
mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps);
return vk::NoError();
}
......
......@@ -15,6 +15,7 @@
#include "common/angleutils.h"
#include "libANGLE/Caps.h"
#include "libANGLE/renderer/vulkan/formatutilsvk.h"
#include "libANGLE/renderer/vulkan/renderervk_utils.h"
namespace egl
......@@ -105,6 +106,12 @@ class RendererVk : angle::NonCopyable
// This is necessary to update the cached current RenderPass Framebuffer.
void onReleaseRenderPass(const FramebufferVk *framebufferVk);
// TODO(jmadill): We could pass angle::Format::ID here.
const vk::Format &getFormat(GLenum internalFormat) const
{
return mFormatTable[internalFormat];
}
private:
void ensureCapsInitialized() const;
void generateCaps(gl::Caps *outCaps,
......@@ -143,6 +150,7 @@ class RendererVk : angle::NonCopyable
std::vector<vk::FenceAndSerial> mInFlightFences;
std::vector<vk::GarbageObject> mGarbage;
vk::MemoryProperties mMemoryProperties;
vk::FormatTable mFormatTable;
// TODO(jmadill): Don't keep a single renderpass in the Renderer.
FramebufferVk *mCurrentRenderPassFramebuffer;
......
......@@ -24,10 +24,10 @@ namespace rx
namespace
{
const vk::Format &GetVkFormatFromConfig(const egl::Config &config)
const vk::Format &GetVkFormatFromConfig(RendererVk *renderer, const egl::Config &config)
{
// TODO(jmadill): Properly handle format interpretation.
return vk::Format::Get(GL_BGRA8_EXT);
return renderer->getFormat(GL_BGRA8_EXT);
}
VkPresentModeKHR GetDesiredPresentMode(const std::vector<VkPresentModeKHR> &presentModes,
......@@ -301,7 +301,7 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &surfaceFormatCount,
surfaceFormats.data()));
mRenderTarget.format = &GetVkFormatFromConfig(*mState.config);
mRenderTarget.format = &GetVkFormatFromConfig(renderer, *mState.config);
auto nativeFormat = mRenderTarget.format->native;
if (surfaceFormatCount == 1u && surfaceFormats[0].format == VK_FORMAT_UNDEFINED)
......@@ -345,7 +345,7 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
swapchainInfo.clipped = VK_TRUE;
swapchainInfo.oldSwapchain = VK_NULL_HANDLE;
const auto &device = renderer->getDevice();
VkDevice device = renderer->getDevice();
ANGLE_VK_TRY(vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &mSwapchain));
// Intialize the swapchain image views.
......
......@@ -51,6 +51,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
{
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
VkDevice device = contextVk->getDevice();
// TODO(jmadill): support multi-level textures.
ASSERT(level == 0);
......@@ -74,9 +75,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
// Convert internalFormat to sized internal format.
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
const vk::Format &vkFormat = vk::Format::Get(formatInfo.sizedInternalFormat);
VkDevice device = contextVk->getDevice();
const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
if (!mImage.valid())
{
......@@ -203,7 +202,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
inputSkipBytes);
auto loadFunction = vkFormat.getLoadFunctions()(type);
auto loadFunction = vkFormat.loadFunctions(type);
uint8_t *mapPointer = nullptr;
ANGLE_TRY(stagingImage.getDeviceMemory().map(device, 0, VK_WHOLE_SIZE, 0, &mapPointer));
......
......@@ -16,14 +16,45 @@ namespace rx
namespace vk
{
Format::Format()
: internalFormat(GL_NONE),
formatID(angle::Format::ID::NONE),
native(VK_FORMAT_UNDEFINED),
dataInitializerFunction(nullptr),
loadFunctions()
{
}
const angle::Format &Format::format() const
{
return angle::Format::Get(formatID);
}
LoadFunctionMap Format::getLoadFunctions() const
FormatTable::FormatTable()
{
}
FormatTable::~FormatTable()
{
}
void FormatTable::initialize(VkPhysicalDevice physicalDevice, gl::TextureCapsMap *textureCapsMap)
{
for (size_t formatIndex = 0; formatIndex < angle::kNumANGLEFormats; ++formatIndex)
{
angle::Format::ID formatID = static_cast<angle::Format::ID>(formatIndex);
const angle::Format &angleFormat = angle::Format::Get(formatID);
mFormatData[formatIndex].initialize(physicalDevice, angleFormat);
mFormatData[formatIndex].loadFunctions =
GetLoadFunctionsMap(mFormatData[formatIndex].internalFormat, formatID);
}
}
const Format &FormatTable::operator[](GLenum internalFormat) const
{
return GetLoadFunctionsMap(internalFormat, formatID);
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.
......
......@@ -11,9 +11,17 @@
#include <vulkan/vulkan.h>
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/Format.h"
#include "libANGLE/renderer/renderer_utils.h"
#include <array>
namespace gl
{
class TextureCapsMap;
} // namespace gl
namespace rx
{
......@@ -22,32 +30,35 @@ namespace vk
struct Format final : private angle::NonCopyable
{
constexpr Format(GLenum internalFormat,
angle::Format::ID formatID,
VkFormat native,
InitializeTextureDataFunction initFunction);
Format();
static const Format &Get(GLenum internalFormat);
// This is an auto-generated method in vk_format_table_autogen.cpp.
void initialize(VkPhysicalDevice physicalDevice, const angle::Format &angleFormat);
const angle::Format &format() const;
LoadFunctionMap getLoadFunctions() const;
GLenum internalFormat;
angle::Format::ID formatID;
VkFormat native;
InitializeTextureDataFunction dataInitializerFunction;
LoadFunctionMap loadFunctions;
};
constexpr Format::Format(GLenum internalFormat,
angle::Format::ID formatID,
VkFormat native,
InitializeTextureDataFunction initFunction)
: internalFormat(internalFormat),
formatID(formatID),
native(native),
dataInitializerFunction(initFunction)
class FormatTable final : angle::NonCopyable
{
}
public:
FormatTable();
~FormatTable();
// Also initializes the TextureCapsMap.
void initialize(VkPhysicalDevice physicalDevice, gl::TextureCapsMap *textureCapsMap);
const Format &operator[](GLenum internalFormat) const;
private:
// The table data is indexed by angle::Format::ID.
std::array<Format, angle::kNumANGLEFormats> mFormatData;
};
// TODO(jmadill): This is temporary. Figure out how to handle format conversions.
VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat);
......
......@@ -41,21 +41,15 @@ namespace rx
namespace vk
{{
// static
const Format &Format::Get(GLenum internalFormat)
void Format::initialize(VkPhysicalDevice physicalDevice, const angle::Format &angleFormat)
{{
// clang-format off
switch (internalFormat)
switch (angleFormat.id)
{{
{format_case_data}
default:
UNREACHABLE();
break;
}}
// clang-format on
UNREACHABLE();
static const Format noInfo(GL_NONE, angle::Format::ID::NONE, VK_FORMAT_UNDEFINED, nullptr);
return noInfo;
}}
}} // namespace vk
......@@ -63,57 +57,49 @@ const Format &Format::Get(GLenum internalFormat)
}} // namespace rx
"""
format_entry_template = """{space}{{
{space} static constexpr Format info({internalFormat},
{space} angle::Format::ID::{formatName},
{space} {vkFormat},
{space} {initializer});
{space} return info;
{space}}}
empty_format_entry_template = """{space}case angle::Format::ID::{formatName}:
{space} // This format is not implemented in Vulkan.
{space} break;
"""
def parse_format_case(internal_format, format_name, native_format):
table_data = ""
parsed = {
"space": " ",
"internalFormat": internal_format,
"formatName": format_name,
"vkFormat": native_format,
}
# Derived values.
parsed["initializer"] = angle_format.get_internal_format_initializer(
internal_format, format_name)
return format_entry_template.format(**parsed)
def parse_json_into_cases(json_map, vk_map):
table_data = ''
for internal_format, format_name in sorted(json_map.iteritems()):
format_entry_template = """{space}case angle::Format::ID::{formatName}:
{space}{{
{space} internalFormat = {internalFormat};
{space} formatID = angle::Format::ID::{formatName};
{space} native = {vkFormat};
{space} dataInitializerFunction = {initializer};
{space} break;
{space}}}
"""
if format_name not in vk_map:
continue
def gen_format_case(angle, internal_format, vk_map):
native_format = vk_map[format_name]
if angle not in vk_map or angle == 'NONE':
return empty_format_entry_template.format(
space = ' ',
formatName = angle)
table_data += ' case ' + internal_format + ':\n'
table_data += parse_format_case(internal_format, format_name, native_format)
vk_format_name = vk_map[angle]
initializer = angle_format.get_internal_format_initializer(
internal_format, vk_format_name)
return table_data
return format_entry_template.format(
space = ' ',
internalFormat = internal_format,
formatName = angle,
vkFormat = vk_format_name,
initializer = initializer)
input_file_name = 'vk_format_map.json'
out_file_name = 'vk_format_table'
json_map = angle_format.load_without_override()
angle_to_gl = angle_format.load_inverse_table(os.path.join('..', 'angle_format_map.json'))
vk_map = angle_format.load_json(input_file_name)
vk_cases = [gen_format_case(angle, gl, vk_map) for angle, gl in sorted(angle_to_gl.iteritems())]
format_case_data = parse_json_into_cases(json_map, vk_map)
output_cpp = template_table_autogen_cpp.format(
copyright_year = date.today().year,
format_case_data = format_case_data,
format_case_data = "\n".join(vk_cases),
script_name = __file__,
out_file_name = out_file_name,
input_file_name = input_file_name)
......
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