Commit f0b02054 by Geoff Lang Committed by Commit Bot

Add a Vulkan feature to compress float32 vertex formats.

Use the vertex conversion pipeline in VertexArrayVk to detect static vertex data and convert float32 vertices to float16. This feature is useful for determining if an allication is vertex bandwidth bound and seeing what gains could be had by using smaller attributes. This feature could be implemented in ANGLE's frontend but new infrastructure for converting and storing the converted attributes would need to be added to gl::VertexArray. Our backends already have the functionality needed to handle unsupported attribute formats and this can be repurposed for compressing vertex formats. Bug: b/167404532 Bug: b/161716126 Change-Id: I9a09656a72e8499faa4124adf876d7261c8341c9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2342285 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 4d779fb3
......@@ -408,6 +408,14 @@ struct FeaturesVk : FeatureSetBase
Feature forceNearestMipFiltering = {"force_nearest_mip_filtering",
FeatureCategory::VulkanWorkarounds,
"Force nearest mip filtering when sampling.", &members};
// Compress float32 vertices in static buffers to float16 at draw time. ANGLE is non-conformant
// if this feature is enabled.
angle::Feature compressVertexData = {"compress_vertex_data",
angle::FeatureCategory::VulkanWorkarounds,
"Compress vertex data to smaller data types when "
"possible. Using this feature makes ANGLE non-conformant.",
&members};
};
inline FeaturesVk::FeaturesVk() = default;
......
......@@ -2,7 +2,7 @@
"src/libANGLE/es3_copy_conversion_formats.json":
"54608f6f7d9aa7c59a8458ccf3ab9935",
"src/libANGLE/es3_copy_conversion_table_autogen.cpp":
"b20d198cf5e292c43170d4873b381b34",
"773a77dd24084a9071431e9df1c097e3",
"src/libANGLE/gen_copy_conversion_table.py":
"18e0d2ff461f730a9efb0dcdfa3f058a",
"src/libANGLE/renderer/angle_format.py":
......
......@@ -4,9 +4,9 @@
"src/libANGLE/renderer/angle_format_map.json":
"aa4a0d3463b76858a75787b9cdec8e98",
"src/libANGLE/renderer/vulkan/gen_vk_format_table.py":
"54a7374f93f17da1386600027acca7a3",
"b4d38f08a354849dcba2a8f9f2569069",
"src/libANGLE/renderer/vulkan/vk_format_map.json":
"5dc3cfb41778806e379876ce9fa427f3",
"b62588b1e9f6d9fa98aeea886d8ed2bd",
"src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp":
"7882959fda2dbda451164f2afd2e35be"
"dfb656a573582202fe813eb23d5052dc"
}
\ No newline at end of file
......@@ -89,6 +89,8 @@
"df913989b39699e549ba9089190d358c",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000007.inc":
"c9e0fad17170e97662b0fa0d37919ea3",
"src/libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000008.inc":
"680d2865d4350c8f36fbbdaec1b43682",
"src/libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.00000000.inc":
"3a4ab796f02d3f1c306c92f7da2c68ee",
"src/libANGLE/renderer/vulkan/shaders/gen/GenerateMipmap.comp.00000000.inc":
......@@ -250,9 +252,9 @@
"src/libANGLE/renderer/vulkan/shaders/src/ConvertIndirectLineLoop.comp.json":
"c2c79c40b0fbcb4876637aa06e8aa919",
"src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp":
"f63e7c4f738c11f1a1b19023d4515dc4",
"537e6cff8f9a0b6acdf1c9be5fdcef7c",
"src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp.json":
"e4a95aae7f216780946e7332d22aa74e",
"f2abd98463e46c0af45e8a1a5e5af88f",
"src/libANGLE/renderer/vulkan/shaders/src/FullScreenQuad.vert":
"805ec8b2f87d4bd4242dc5b1c58ba3b4",
"src/libANGLE/renderer/vulkan/shaders/src/GenerateMipmap.comp":
......@@ -276,9 +278,9 @@
"src/libANGLE/renderer/vulkan/shaders/src/OverlayDraw.comp.json":
"af79e5153c99cdb1e6b551b11bbf7f6b",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp":
"df9efda2dee207bea8e346f2c9fa824f",
"a62caa10b2ec5dc17cc8cbf9094d38f4",
"src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h":
"96c6f4b7a06a3b21f3b0ceea661014ef",
"a18cac1ffca9735480a2b9dea67b73c0",
"tools/glslang/glslang_validator.exe.sha1":
"17e862cc6f462fecbf50b24ed6544a27",
"tools/glslang/glslang_validator.sha1":
......
......@@ -200,6 +200,19 @@ bool IsArrayTextureType(TextureType type)
}
}
bool IsStaticBufferUsage(BufferUsage useage)
{
switch (useage)
{
case BufferUsage::StaticCopy:
case BufferUsage::StaticDraw:
case BufferUsage::StaticRead:
return true;
default:
return false;
}
}
std::ostream &operator<<(std::ostream &os, PrimitiveMode value)
{
switch (value)
......
......@@ -223,6 +223,8 @@ TextureType SamplerTypeToTextureType(GLenum samplerType);
bool IsMultisampled(gl::TextureType type);
bool IsArrayTextureType(gl::TextureType type);
bool IsStaticBufferUsage(BufferUsage useage);
enum class PrimitiveMode : uint8_t
{
Points = 0x0,
......
// GENERATED FILE - DO NOT EDIT.
// Generated by gen_copy_conversion_table.py using data from es3_copy_conversion_formats.json.
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Copyright 2020 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.
//
......
......@@ -44,6 +44,13 @@ void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t coun
template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized>
void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
template <size_t inputComponentCount, size_t outputComponentCount>
void Copy32FTo16FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
void CopyXYZ32FToXYZ9E5(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
void CopyXYZ32FToX11Y11B10F(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
template <bool isSigned, bool normalized, bool toFloat>
void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input,
size_t stride,
......
......@@ -219,6 +219,57 @@ inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t coun
}
}
template <size_t inputComponentCount, size_t outputComponentCount>
void Copy32FTo16FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
{
const unsigned short kZero = gl::float32ToFloat16(0.0f);
const unsigned short kOne = gl::float32ToFloat16(1.0f);
for (size_t i = 0; i < count; i++)
{
const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
unsigned short *offsetOutput =
reinterpret_cast<unsigned short *>(output) + i * outputComponentCount;
for (size_t j = 0; j < inputComponentCount; j++)
{
offsetOutput[j] = gl::float32ToFloat16(offsetInput[j]);
}
for (size_t j = inputComponentCount; j < outputComponentCount; j++)
{
offsetOutput[j] = (j == 3) ? kOne : kZero;
}
}
}
inline void CopyXYZ32FToXYZ9E5(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
{
for (size_t i = 0; i < count; i++)
{
const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
unsigned int *offsetOutput = reinterpret_cast<unsigned int *>(output) + i;
*offsetOutput = gl::convertRGBFloatsTo999E5(offsetInput[0], offsetInput[1], offsetInput[2]);
}
}
inline void CopyXYZ32FToX11Y11B10F(const uint8_t *input,
size_t stride,
size_t count,
uint8_t *output)
{
for (size_t i = 0; i < count; i++)
{
const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
unsigned int *offsetOutput = reinterpret_cast<unsigned int *>(output) + i;
*offsetOutput = gl::float32ToFloat11(offsetInput[0]) << 0 |
gl::float32ToFloat11(offsetInput[1]) << 11 |
gl::float32ToFloat10(offsetInput[2]) << 22;
}
}
namespace priv
{
......
......@@ -352,6 +352,7 @@ class ContextVk : public ContextImpl, public vk::Context
GLuint stride,
GLuint divisor,
angle::FormatID format,
bool compressed,
GLuint relativeOffset,
const vk::BufferHelper *vertexBuffer);
......@@ -1167,6 +1168,7 @@ ANGLE_INLINE angle::Result ContextVk::onVertexAttributeChange(size_t attribIndex
GLuint stride,
GLuint divisor,
angle::FormatID format,
bool compressed,
GLuint relativeOffset,
const vk::BufferHelper *vertexBuffer)
{
......@@ -1174,7 +1176,8 @@ ANGLE_INLINE angle::Result ContextVk::onVertexAttributeChange(size_t attribIndex
// Set divisor to 1 for attribs with emulated divisor
mGraphicsPipelineDesc->updateVertexInput(
&mGraphicsPipelineTransition, static_cast<uint32_t>(attribIndex), stride,
divisor > mRenderer->getMaxVertexAttribDivisor() ? 1 : divisor, format, relativeOffset);
divisor > mRenderer->getMaxVertexAttribDivisor() ? 1 : divisor, format, compressed,
relativeOffset);
return onVertexBufferChange(vertexBuffer);
}
} // namespace rx
......
......@@ -1895,6 +1895,8 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ANGLE_FEATURE_CONDITION(&mFeatures, forceNearestFiltering, false);
ANGLE_FEATURE_CONDITION(&mFeatures, forceNearestMipFiltering, false);
ANGLE_FEATURE_CONDITION(&mFeatures, compressVertexData, false);
angle::PlatformMethods *platform = ANGLEPlatformCurrent();
platform->overrideFeaturesVk(platform, &mFeatures);
......
......@@ -67,14 +67,13 @@ uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params)
// Assert on the types to make sure the shader supports its. These are based on
// ConvertVertex_comp::Conversion values.
ASSERT(!destIsSint || srcIsSint); // If destination is sint, src must be sint too
ASSERT(!destIsUint || srcIsUint); // If destination is uint, src must be uint too
ASSERT(!srcIsFixed || destIsFloat); // If source is fixed, dest must be float
ASSERT(srcIsHalfFloat == destIsHalfFloat); // Both src and dest are half float or neither
ASSERT(!destIsSint || srcIsSint); // If destination is sint, src must be sint too
ASSERT(!destIsUint || srcIsUint); // If destination is uint, src must be uint too
ASSERT(!srcIsFixed || destIsFloat); // If source is fixed, dest must be float
// One of each bool set must be true
ASSERT(srcIsSint || srcIsUint || srcIsSnorm || srcIsUnorm || srcIsFixed || srcIsFloat);
ASSERT(destIsSint || destIsUint || destIsFloat);
ASSERT(destIsSint || destIsUint || destIsFloat || destIsHalfFloat);
// We currently don't have any big-endian devices in the list of supported platforms. The
// shader is capable of supporting big-endian architectures, but the relevant flag (IsBigEndian)
......@@ -90,6 +89,10 @@ uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params)
// Note that HalfFloat conversion uses the same shader as Uint.
flags |= ConvertVertex_comp::kUintToUint;
}
else if (srcIsFloat && destIsHalfFloat)
{
flags |= ConvertVertex_comp::kFloatToHalf;
}
else if (srcIsSint && destIsSint)
{
flags |= ConvertVertex_comp::kSintToSint;
......
......@@ -123,14 +123,16 @@ class VertexArrayVk : public VertexArrayImpl
size_t attribIndex,
const vk::Format &vertexFormat,
ConversionBuffer *conversion,
GLuint relativeOffset);
GLuint relativeOffset,
bool compressed);
angle::Result convertVertexBufferCPU(ContextVk *contextVk,
BufferVk *srcBuffer,
const gl::VertexBinding &binding,
size_t attribIndex,
const vk::Format &vertexFormat,
ConversionBuffer *conversion,
GLuint relativeOffset);
GLuint relativeOffset,
bool compress);
angle::Result syncDirtyAttrib(ContextVk *contextVk,
const gl::VertexAttribute &attrib,
......@@ -145,6 +147,7 @@ class VertexArrayVk : public VertexArrayImpl
gl::AttribArray<vk::BufferHelper *> mCurrentArrayBuffers;
// Cache strides of attributes for a fast pipeline cache update when VAOs are changed
gl::AttribArray<GLuint> mCurrentArrayBufferStrides;
gl::AttributesMask mCurrentArrayBufferCompressed;
VkDeviceSize mCurrentElementArrayBufferOffset;
vk::BufferHelper *mCurrentElementArrayBuffer;
......
......@@ -93,7 +93,7 @@ buffer_struct_template = """{{{buffer}, {vk_buffer_format}, {vk_buffer_format_is
buffer_fallback_template = """{{
static constexpr BufferFormatInitInfo kInfo[] = {{{buffer_list}}};
initBufferFallback(renderer, kInfo, ArraySize(kInfo));
initBufferFallback(renderer, kInfo, ArraySize(kInfo), {buffer_compressed_offset});
}}"""
......@@ -155,9 +155,17 @@ def gen_format_case(angle, internal_format, vk_json_data):
fallbacks = vk_fallbacks.get(format, {}).get(type, [])
if not isinstance(fallbacks, list):
fallbacks = [fallbacks]
if format not in vk_map:
return fallbacks
return [format] + fallbacks
compressed = vk_fallbacks.get(format, {}).get(type + "_compressed", [])
if not isinstance(compressed, list):
compressed = [compressed]
fallbacks += compressed
if format in vk_map:
fallbacks = [format] + fallbacks
return (fallbacks, len(fallbacks) - len(compressed))
def image_args(format):
return dict(
......@@ -176,7 +184,7 @@ def gen_format_case(angle, internal_format, vk_json_data):
vertex_load_converts='false' if angle == format else 'true',
)
images = get_formats(angle, "image")
images, images_compressed_offset = get_formats(angle, "image")
if len(images) == 1:
args.update(image_template=image_basic_template)
args.update(image_args(images[0]))
......@@ -185,7 +193,7 @@ def gen_format_case(angle, internal_format, vk_json_data):
image_template=image_fallback_template,
image_list=", ".join(image_struct_template.format(**image_args(i)) for i in images))
buffers = get_formats(angle, "buffer")
buffers, buffers_compressed_offset = get_formats(angle, "buffer")
if len(buffers) == 1:
args.update(buffer_template=buffer_basic_template)
args.update(buffer_args(buffers[0]))
......@@ -193,7 +201,8 @@ def gen_format_case(angle, internal_format, vk_json_data):
args.update(
buffer_template=buffer_fallback_template,
buffer_list=", ".join(
buffer_struct_template.format(**buffer_args(i)) for i in buffers))
buffer_struct_template.format(**buffer_args(i)) for i in buffers),
buffer_compressed_offset=buffers_compressed_offset)
return format_entry_template.format(**args).format(**args)
......
......@@ -46,6 +46,7 @@
// * UnormToFloat: Similar to UintToFloat, but normalized.
// * FixedToFloat: 16.16 signed fixed-point to floating point.
// * FloatToFloat: float.
// * FloatToHalf: float to half-float
//
// SintToSint, UintToUint and FloatToFloat correspond to CopyNativeVertexData() and
// Copy8SintTo16SintVertexData() in renderer/copyvertex.inc.
......@@ -67,7 +68,7 @@
#define SrcType int
#elif UintToUint || UintToFloat
#define SrcType uint
#elif SnormToFloat || UnormToFloat || FixedToFloat || FloatToFloat
#elif SnormToFloat || UnormToFloat || FixedToFloat || FloatToFloat || FloatToHalf
#define SrcType float
#else
#error "Not all conversions are accounted for"
......@@ -83,6 +84,9 @@
#elif SintToFloat || UintToFloat || SnormToFloat || UnormToFloat || FixedToFloat || FloatToFloat
#define DestType float
#define IsDestFloat 1
#elif FloatToHalf
#define DestType float
#define IsDestFloat 0
#else
#error "Not all conversions are accounted for"
#endif
......@@ -254,7 +258,7 @@ SrcType loadSourceComponent(uint cd)
#elif FixedToFloat
// 1.0 in fixed point is 0x10000
valueAsUint = 0x10000;
#elif FloatToFloat
#elif FloatToFloat || FloatToHalf
valueAsUint = floatBitsToUint(1.0);
#else
#error "Not all conversions are accounted for"
......@@ -296,7 +300,7 @@ SrcType loadSourceComponent(uint cd)
#elif FixedToFloat
float divisor = 1.0f / 65536.0f;
SrcType value = int(valueAsUint) * divisor;
#elif FloatToFloat
#elif FloatToFloat || FloatToHalf
SrcType value = uintBitsToFloat(valueAsUint);
#else
#error "Not all conversions are accounted for"
......@@ -328,6 +332,10 @@ uint makeDestinationComponent(uint cd, DestType value)
uint valueMask = valueBits == 32 ? -1 : (1 << valueBits) - 1;
uint valueAsUint = (uint(value) & valueMask) << shiftBits;
#elif FloatToHalf
uint shift = ((cd & 1) == 0) ? 0 : 16;
uint valueAsUint = packHalf2x16(vec2(value, 0.0)) << shift;
#elif IsDestFloat
// If the destination is float, it will occupy the whole result.
uint valueAsUint = floatBitsToInt(value);
......
......@@ -18,6 +18,7 @@
[ "SnormToFloat", "-Od" ],
[ "UnormToFloat", "-Od" ],
[ "FixedToFloat", "-Od" ],
[ "FloatToFloat", "-Od" ]
[ "FloatToFloat", "-Od" ],
[ "FloatToHalf", "-Od" ]
]
}
......@@ -910,6 +910,7 @@ void GraphicsPipelineDesc::initDefaults()
SetBitField(packedAttrib.stride, 0);
SetBitField(packedAttrib.divisor, 0);
SetBitField(packedAttrib.format, defaultFormat);
SetBitField(packedAttrib.compressed, 0);
SetBitField(packedAttrib.offset, 0);
}
......@@ -1107,7 +1108,8 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
angle::FormatID formatID = static_cast<angle::FormatID>(packedAttrib.format);
const vk::Format &format = contextVk->getRenderer()->getFormat(formatID);
const angle::Format &angleFormat = format.intendedFormat();
VkFormat vkFormat = format.vkBufferFormat;
VkFormat vkFormat =
packedAttrib.compressed ? format.vkCompressedBufferFormat : format.vkBufferFormat;
gl::ComponentType attribType =
GetVertexAttributeComponentType(angleFormat.isPureInt(), angleFormat.vertexAttribType);
......@@ -1343,6 +1345,7 @@ void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *tra
GLuint stride,
GLuint divisor,
angle::FormatID format,
bool compressed,
GLuint relativeOffset)
{
vk::PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
......@@ -1356,6 +1359,7 @@ void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *tra
}
SetBitField(packedAttrib.format, format);
SetBitField(packedAttrib.compressed, compressed);
SetBitField(packedAttrib.offset, relativeOffset);
constexpr size_t kAttribBits = kPackedAttribDescSize * kBitsPerByte;
......
......@@ -310,8 +310,10 @@ struct PackedAttribDesc final
uint8_t format;
uint8_t divisor;
// Can only take 11 bits on NV.
uint16_t offset;
// Desktop drivers support
uint16_t offset : kAttributeOffsetMaxBits;
uint16_t compressed : 1;
// Although technically stride can be any value in ES 2.0, in practice supporting stride
// greater than MAX_USHORT should not be that helpful. Note that stride limits are
......@@ -519,6 +521,7 @@ class GraphicsPipelineDesc final
GLuint stride,
GLuint divisor,
angle::FormatID format,
bool compressed,
GLuint relativeOffset);
// Input assembly info
......
......@@ -238,8 +238,7 @@ void RendererVk::ensureCapsInitialized() const
mNativeCaps.maxVertexAttribBindings = LimitToInt(limitsVk.maxVertexInputBindings);
// Offset and stride are stored as uint16_t in PackedAttribDesc.
mNativeCaps.maxVertexAttribRelativeOffset =
std::min(static_cast<uint32_t>(std::numeric_limits<uint16_t>::max()),
limitsVk.maxVertexInputAttributeOffset);
std::min((1u << kAttributeOffsetMaxBits) - 1, limitsVk.maxVertexInputAttributeOffset);
mNativeCaps.maxVertexAttribStride =
std::min(static_cast<uint32_t>(std::numeric_limits<uint16_t>::max()),
limitsVk.maxVertexInputBindingStride);
......
......@@ -258,6 +258,15 @@
"R32G32B32A32_SNORM": {
"buffer": "R32G32B32A32_FLOAT"
},
"R32G32B32A32_FLOAT": {
"buffer_compressed": "R16G16B16A16_FLOAT"
},
"R32G32_FLOAT": {
"buffer_compressed": "R16G16_FLOAT"
},
"R32_FLOAT": {
"buffer_compressed": "R16_FLOAT"
},
"R32_USCALED": {
"buffer": "R32_FLOAT"
},
......@@ -466,7 +475,8 @@
"buffer": "R16G16B16A16_FLOAT"
},
"R32G32B32_FLOAT": {
"image": "R32G32B32A32_FLOAT"
"image": "R32G32B32A32_FLOAT",
"buffer_compressed": "R16G16B16A16_FLOAT"
},
"ETC2_R8G8B8_UNORM_BLOCK": {
"image": "R8G8B8A8_UNORM"
......
......@@ -110,9 +110,14 @@ Format::Format()
vkImageFormat(VK_FORMAT_UNDEFINED),
actualBufferFormatID(angle::FormatID::NONE),
vkBufferFormat(VK_FORMAT_UNDEFINED),
actualCompressedBufferFormatID(angle::FormatID::NONE),
vkCompressedBufferFormat(VK_FORMAT_UNDEFINED),
imageInitializerFunction(nullptr),
textureLoadFunctions(),
vertexLoadFunction(nullptr),
compressedVertexLoadFunction(nullptr),
vertexLoadRequiresConversion(false),
compressedVertexLoadRequiresConversion(false),
vkBufferFormatIsPacked(false),
vkFormatIsInt(false),
vkFormatIsUnsigned(false)
......@@ -145,17 +150,34 @@ void Format::initImageFallback(RendererVk *renderer, const ImageFormatInitInfo *
imageInitializerFunction = info[i].initializer;
}
void Format::initBufferFallback(RendererVk *renderer, const BufferFormatInitInfo *info, int numInfo)
void Format::initBufferFallback(RendererVk *renderer,
const BufferFormatInitInfo *info,
int numInfo,
int compressedStartIndex)
{
size_t skip = renderer->getFeatures().forceFallbackFormat.enabled ? 1 : 0;
int i = FindSupportedFormat(renderer, info, skip, static_cast<uint32_t>(numInfo),
HasFullBufferFormatSupport);
actualBufferFormatID = info[i].format;
vkBufferFormat = info[i].vkFormat;
vkBufferFormatIsPacked = info[i].vkFormatIsPacked;
vertexLoadFunction = info[i].vertexLoadFunction;
vertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion;
{
size_t skip = renderer->getFeatures().forceFallbackFormat.enabled ? 1 : 0;
int i = FindSupportedFormat(renderer, info, skip, compressedStartIndex,
HasFullBufferFormatSupport);
actualBufferFormatID = info[i].format;
vkBufferFormat = info[i].vkFormat;
vkBufferFormatIsPacked = info[i].vkFormatIsPacked;
vertexLoadFunction = info[i].vertexLoadFunction;
vertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion;
}
if (renderer->getFeatures().compressVertexData.enabled && compressedStartIndex < numInfo)
{
int i = FindSupportedFormat(renderer, info, compressedStartIndex, numInfo,
HasFullBufferFormatSupport);
actualCompressedBufferFormatID = info[i].format;
vkCompressedBufferFormat = info[i].vkFormat;
vkCompressedBufferFormatIsPacked = info[i].vkFormatIsPacked;
compressedVertexLoadFunction = info[i].vertexLoadFunction;
compressedVertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion;
}
}
size_t Format::getImageCopyBufferAlignment() const
......@@ -332,9 +354,9 @@ bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, VkFormat vkForma
renderer->hasImageFormatFeatureBits(vkFormat, kBitsDepth);
}
size_t GetVertexInputAlignment(const vk::Format &format)
size_t GetVertexInputAlignment(const vk::Format &format, bool compressed)
{
const angle::Format &bufferFormat = format.actualBufferFormat();
const angle::Format &bufferFormat = format.actualBufferFormat(compressed);
size_t pixelBytes = bufferFormat.pixelBytes;
return format.vkBufferFormatIsPacked ? pixelBytes : (pixelBytes / bufferFormat.channelCount);
}
......
......@@ -70,9 +70,20 @@ struct Format final : private angle::NonCopyable
}
// The actual Buffer format is used to implement the front-end format for Buffers.
const angle::Format &actualBufferFormat() const
const angle::Format &actualBufferFormat(bool compressed) const
{
return angle::Format::Get(actualBufferFormatID);
return angle::Format::Get(compressed ? actualCompressedBufferFormatID
: actualBufferFormatID);
}
VertexCopyFunction getVertexLoadFunction(bool compressed) const
{
return compressed ? compressedVertexLoadFunction : vertexLoadFunction;
}
bool getVertexLoadRequiresConversion(bool compressed) const
{
return compressed ? compressedVertexLoadRequiresConversion : vertexLoadRequiresConversion;
}
// The |internalFormat| always correponds to a valid GLenum type. For types that don't have a
......@@ -94,7 +105,10 @@ struct Format final : private angle::NonCopyable
// These are used in the format table init.
void initImageFallback(RendererVk *renderer, const ImageFormatInitInfo *info, int numInfo);
void initBufferFallback(RendererVk *renderer, const BufferFormatInitInfo *info, int numInfo);
void initBufferFallback(RendererVk *renderer,
const BufferFormatInitInfo *fallbackInfo,
int numInfo,
int compressedStartIndex);
angle::FormatID intendedFormatID;
GLenum internalFormat;
......@@ -102,13 +116,18 @@ struct Format final : private angle::NonCopyable
VkFormat vkImageFormat;
angle::FormatID actualBufferFormatID;
VkFormat vkBufferFormat;
angle::FormatID actualCompressedBufferFormatID;
VkFormat vkCompressedBufferFormat;
InitializeTextureDataFunction imageInitializerFunction;
LoadFunctionMap textureLoadFunctions;
VertexCopyFunction vertexLoadFunction;
VertexCopyFunction compressedVertexLoadFunction;
bool vertexLoadRequiresConversion;
bool compressedVertexLoadRequiresConversion;
bool vkBufferFormatIsPacked;
bool vkCompressedBufferFormatIsPacked;
bool vkFormatIsInt;
bool vkFormatIsUnsigned;
};
......@@ -162,7 +181,7 @@ bool HasNonRenderableTextureFormatSupport(RendererVk *renderer, VkFormat vkForma
// Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This
// calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'.
size_t GetVertexInputAlignment(const vk::Format &format);
size_t GetVertexInputAlignment(const vk::Format &format, bool compressed);
// Get the swizzle state based on format's requirements and emulations.
gl::SwizzleState GetFormatSwizzle(const ContextVk *contextVk,
......
......@@ -63,6 +63,7 @@ namespace
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000005.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000006.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000007.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ConvertVertex.comp.00000008.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/FullScreenQuad.vert.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/GenerateMipmap.comp.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/GenerateMipmap.comp.00000001.inc"
......@@ -199,6 +200,7 @@ constexpr CompressedShaderBlob kConvertVertex_comp_shaders[] = {
{kConvertVertex_comp_00000005, sizeof(kConvertVertex_comp_00000005)},
{kConvertVertex_comp_00000006, sizeof(kConvertVertex_comp_00000006)},
{kConvertVertex_comp_00000007, sizeof(kConvertVertex_comp_00000007)},
{kConvertVertex_comp_00000008, sizeof(kConvertVertex_comp_00000008)},
};
constexpr CompressedShaderBlob kFullScreenQuad_vert_shaders[] = {
{kFullScreenQuad_vert_00000000, sizeof(kFullScreenQuad_vert_00000000)},
......
......@@ -53,6 +53,7 @@ angle_vulkan_internal_shaders = [
"shaders/gen/ConvertVertex.comp.00000005.inc",
"shaders/gen/ConvertVertex.comp.00000006.inc",
"shaders/gen/ConvertVertex.comp.00000007.inc",
"shaders/gen/ConvertVertex.comp.00000008.inc",
"shaders/gen/FullScreenQuad.vert.00000000.inc",
"shaders/gen/GenerateMipmap.comp.00000000.inc",
"shaders/gen/GenerateMipmap.comp.00000001.inc",
......
......@@ -86,8 +86,9 @@ enum Conversion
kUnormToFloat = 0x00000005,
kFixedToFloat = 0x00000006,
kFloatToFloat = 0x00000007,
kFloatToHalf = 0x00000008,
};
constexpr size_t kArrayLen = 0x00000008;
constexpr size_t kArrayLen = 0x00000009;
} // namespace ConvertVertex_comp
namespace FullScreenQuad_vert
......
......@@ -103,6 +103,10 @@ enum class TextureDimension
TEX_2D_ARRAY,
};
// A maximum offset of 4096 covers almost every Vulkan driver on desktop (80%) and mobile (99%). The
// next highest values to meet native drivers are 16 bits or 32 bits.
constexpr uint32_t kAttributeOffsetMaxBits = 15;
namespace vk
{
struct Format;
......
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