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 ...@@ -139,4 +139,6 @@ enum class Format::ID
S8_UINT S8_UINT
}; };
constexpr uint32_t kNumANGLEFormats = 125;
} // namespace angle } // namespace angle
...@@ -32,6 +32,8 @@ enum class Format::ID ...@@ -32,6 +32,8 @@ enum class Format::ID
{angle_format_enum} {angle_format_enum}
}}; }};
constexpr uint32_t kNumANGLEFormats = {num_angle_formats};
}} // namespace angle }} // namespace angle
""" """
...@@ -254,11 +256,13 @@ with open('Format_table_autogen.cpp', 'wt') as out_file: ...@@ -254,11 +256,13 @@ with open('Format_table_autogen.cpp', 'wt') as out_file:
out_file.close() out_file.close()
enum_data = gen_enum_string(all_angle) enum_data = gen_enum_string(all_angle)
num_angle_formats = len(all_angle)
output_h = template_autogen_h.format( output_h = template_autogen_h.format(
script_name = sys.argv[0], script_name = sys.argv[0],
copyright_year = date.today().year, copyright_year = date.today().year,
angle_format_enum = enum_data, 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: with open('Format_ID_autogen.inl', 'wt') as out_file:
out_file.write(output_h) out_file.write(output_h)
out_file.close() out_file.close()
...@@ -343,6 +343,9 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w ...@@ -343,6 +343,9 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
mGlslangWrapper = GlslangWrapper::GetReference(); mGlslangWrapper = GlslangWrapper::GetReference();
// Initialize the format table.
mFormatTable.initialize(mPhysicalDevice, &mNativeTextureCaps);
return vk::NoError(); return vk::NoError();
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/Caps.h" #include "libANGLE/Caps.h"
#include "libANGLE/renderer/vulkan/formatutilsvk.h"
#include "libANGLE/renderer/vulkan/renderervk_utils.h" #include "libANGLE/renderer/vulkan/renderervk_utils.h"
namespace egl namespace egl
...@@ -105,6 +106,12 @@ class RendererVk : angle::NonCopyable ...@@ -105,6 +106,12 @@ class RendererVk : angle::NonCopyable
// This is necessary to update the cached current RenderPass Framebuffer. // This is necessary to update the cached current RenderPass Framebuffer.
void onReleaseRenderPass(const FramebufferVk *framebufferVk); 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: private:
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
void generateCaps(gl::Caps *outCaps, void generateCaps(gl::Caps *outCaps,
...@@ -143,6 +150,7 @@ class RendererVk : angle::NonCopyable ...@@ -143,6 +150,7 @@ class RendererVk : angle::NonCopyable
std::vector<vk::FenceAndSerial> mInFlightFences; std::vector<vk::FenceAndSerial> mInFlightFences;
std::vector<vk::GarbageObject> mGarbage; std::vector<vk::GarbageObject> mGarbage;
vk::MemoryProperties mMemoryProperties; vk::MemoryProperties mMemoryProperties;
vk::FormatTable mFormatTable;
// TODO(jmadill): Don't keep a single renderpass in the Renderer. // TODO(jmadill): Don't keep a single renderpass in the Renderer.
FramebufferVk *mCurrentRenderPassFramebuffer; FramebufferVk *mCurrentRenderPassFramebuffer;
......
...@@ -24,10 +24,10 @@ namespace rx ...@@ -24,10 +24,10 @@ namespace rx
namespace 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. // 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, VkPresentModeKHR GetDesiredPresentMode(const std::vector<VkPresentModeKHR> &presentModes,
...@@ -301,7 +301,7 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer) ...@@ -301,7 +301,7 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &surfaceFormatCount, ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &surfaceFormatCount,
surfaceFormats.data())); surfaceFormats.data()));
mRenderTarget.format = &GetVkFormatFromConfig(*mState.config); mRenderTarget.format = &GetVkFormatFromConfig(renderer, *mState.config);
auto nativeFormat = mRenderTarget.format->native; auto nativeFormat = mRenderTarget.format->native;
if (surfaceFormatCount == 1u && surfaceFormats[0].format == VK_FORMAT_UNDEFINED) if (surfaceFormatCount == 1u && surfaceFormats[0].format == VK_FORMAT_UNDEFINED)
...@@ -345,7 +345,7 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer) ...@@ -345,7 +345,7 @@ vk::Error WindowSurfaceVk::initializeImpl(RendererVk *renderer)
swapchainInfo.clipped = VK_TRUE; swapchainInfo.clipped = VK_TRUE;
swapchainInfo.oldSwapchain = VK_NULL_HANDLE; swapchainInfo.oldSwapchain = VK_NULL_HANDLE;
const auto &device = renderer->getDevice(); VkDevice device = renderer->getDevice();
ANGLE_VK_TRY(vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &mSwapchain)); ANGLE_VK_TRY(vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &mSwapchain));
// Intialize the swapchain image views. // Intialize the swapchain image views.
......
...@@ -51,6 +51,7 @@ gl::Error TextureVk::setImage(const gl::Context *context, ...@@ -51,6 +51,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
VkDevice device = contextVk->getDevice();
// TODO(jmadill): support multi-level textures. // TODO(jmadill): support multi-level textures.
ASSERT(level == 0); ASSERT(level == 0);
...@@ -74,9 +75,7 @@ gl::Error TextureVk::setImage(const gl::Context *context, ...@@ -74,9 +75,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
// Convert internalFormat to sized internal format. // Convert internalFormat to sized internal format.
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
const vk::Format &vkFormat = vk::Format::Get(formatInfo.sizedInternalFormat); const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
VkDevice device = contextVk->getDevice();
if (!mImage.valid()) if (!mImage.valid())
{ {
...@@ -203,7 +202,7 @@ gl::Error TextureVk::setImage(const gl::Context *context, ...@@ -203,7 +202,7 @@ gl::Error TextureVk::setImage(const gl::Context *context,
formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages), formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
inputSkipBytes); inputSkipBytes);
auto loadFunction = vkFormat.getLoadFunctions()(type); auto loadFunction = vkFormat.loadFunctions(type);
uint8_t *mapPointer = nullptr; uint8_t *mapPointer = nullptr;
ANGLE_TRY(stagingImage.getDeviceMemory().map(device, 0, VK_WHOLE_SIZE, 0, &mapPointer)); ANGLE_TRY(stagingImage.getDeviceMemory().map(device, 0, VK_WHOLE_SIZE, 0, &mapPointer));
......
...@@ -16,14 +16,45 @@ namespace rx ...@@ -16,14 +16,45 @@ namespace rx
namespace vk 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 const angle::Format &Format::format() const
{ {
return angle::Format::Get(formatID); 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. // TODO(jmadill): This is temporary. Figure out how to handle format conversions.
......
...@@ -11,9 +11,17 @@ ...@@ -11,9 +11,17 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/Format.h" #include "libANGLE/renderer/Format.h"
#include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/renderer_utils.h"
#include <array>
namespace gl
{
class TextureCapsMap;
} // namespace gl
namespace rx namespace rx
{ {
...@@ -22,32 +30,35 @@ namespace vk ...@@ -22,32 +30,35 @@ namespace vk
struct Format final : private angle::NonCopyable struct Format final : private angle::NonCopyable
{ {
constexpr Format(GLenum internalFormat, Format();
angle::Format::ID formatID,
VkFormat native,
InitializeTextureDataFunction initFunction);
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; const angle::Format &format() const;
LoadFunctionMap getLoadFunctions() const;
GLenum internalFormat; GLenum internalFormat;
angle::Format::ID formatID; angle::Format::ID formatID;
VkFormat native; VkFormat native;
InitializeTextureDataFunction dataInitializerFunction; InitializeTextureDataFunction dataInitializerFunction;
LoadFunctionMap loadFunctions;
}; };
constexpr Format::Format(GLenum internalFormat, class FormatTable final : angle::NonCopyable
angle::Format::ID formatID,
VkFormat native,
InitializeTextureDataFunction initFunction)
: internalFormat(internalFormat),
formatID(formatID),
native(native),
dataInitializerFunction(initFunction)
{ {
} 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. // TODO(jmadill): This is temporary. Figure out how to handle format conversions.
VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat); VkFormat GetNativeVertexFormat(gl::VertexFormatType vertexFormat);
......
...@@ -41,21 +41,15 @@ namespace rx ...@@ -41,21 +41,15 @@ namespace rx
namespace vk namespace vk
{{ {{
// static void Format::initialize(VkPhysicalDevice physicalDevice, const angle::Format &angleFormat)
const Format &Format::Get(GLenum internalFormat)
{{ {{
// clang-format off switch (angleFormat.id)
switch (internalFormat)
{{ {{
{format_case_data} {format_case_data}
default: default:
UNREACHABLE();
break; break;
}} }}
// clang-format on
UNREACHABLE();
static const Format noInfo(GL_NONE, angle::Format::ID::NONE, VK_FORMAT_UNDEFINED, nullptr);
return noInfo;
}} }}
}} // namespace vk }} // namespace vk
...@@ -63,57 +57,49 @@ const Format &Format::Get(GLenum internalFormat) ...@@ -63,57 +57,49 @@ const Format &Format::Get(GLenum internalFormat)
}} // namespace rx }} // namespace rx
""" """
format_entry_template = """{space}{{ empty_format_entry_template = """{space}case angle::Format::ID::{formatName}:
{space} static constexpr Format info({internalFormat}, {space} // This format is not implemented in Vulkan.
{space} angle::Format::ID::{formatName}, {space} break;
{space} {vkFormat},
{space} {initializer});
{space} return info;
{space}}}
""" """
def parse_format_case(internal_format, format_name, native_format): format_entry_template = """{space}case angle::Format::ID::{formatName}:
{space}{{
table_data = "" {space} internalFormat = {internalFormat};
{space} formatID = angle::Format::ID::{formatName};
parsed = { {space} native = {vkFormat};
"space": " ", {space} dataInitializerFunction = {initializer};
"internalFormat": internal_format, {space} break;
"formatName": format_name, {space}}}
"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()):
if format_name not in vk_map: def gen_format_case(angle, internal_format, vk_map):
continue
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' vk_format_name = vk_map[angle]
table_data += parse_format_case(internal_format, format_name, native_format) 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' input_file_name = 'vk_format_map.json'
out_file_name = 'vk_format_table' 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_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( output_cpp = template_table_autogen_cpp.format(
copyright_year = date.today().year, copyright_year = date.today().year,
format_case_data = format_case_data, format_case_data = "\n".join(vk_cases),
script_name = __file__, script_name = __file__,
out_file_name = out_file_name, out_file_name = out_file_name,
input_file_name = input_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