Skip to content

Commit e697e37

Browse files
Mohan MaiyaAngle LUCI CQ
authored andcommitted
Vulkan: Allow certain usecases to have non-zero stride
When glVertexAttribPointer is called with a type parameter that doesn't match the vertex attribute binding's type in shader, the vulkan backend used to force the stride to 0. This is acceptable since this usecase is unspecified in spec. To allow for better app compatibility, introduce a new extension that requires normal glVertexAttribPointer functionality to be maintained if the mismatched vertex attribute type is a mismatched integer type sign. This change also modifies the VkFormat used when a mismatch in signedness occurs to use a VkFormat with the same component width as the type parameter. Bug: angleproject:5762 Test: VertexAttributeTestES3.DrawWithRelaxedVertexAttributeType* Test: VertexAttributeTestES3.DrawWithMismatchedComponentCount* Change-Id: I7e5281500afc3d77f0775821447cabfad3ff2d66 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2765012 Commit-Queue: Mohan Maiya <[email protected]> Reviewed-by: Shahbaz Youssefi <[email protected]> Reviewed-by: Jamie Madill <[email protected]>
1 parent 1f1e0e6 commit e697e37

File tree

8 files changed

+449
-3
lines changed

8 files changed

+449
-3
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
Name
2+
3+
ANGLE_relaxed_vertex_attribute_type
4+
5+
Name Strings
6+
7+
GL_ANGLE_relaxed_vertex_attribute_type
8+
9+
Contributors
10+
11+
Jamie Madill, Google
12+
Kevin Jung, Samsung
13+
14+
Contact
15+
16+
Jamie Madill (jmadill 'at' google.com)
17+
18+
Notice
19+
20+
Copyright (c) 2021 The Khronos Group Inc. Copyright terms at
21+
http://www.khronos.org/registry/speccopyright.html
22+
23+
Status
24+
25+
Draft
26+
27+
Version
28+
29+
Version 1, March 25, 2021
30+
31+
Number
32+
33+
OpenGL ES Extension #??
34+
35+
Dependencies
36+
37+
Requires OpenGL ES 3.0
38+
39+
Written against the OpenGL ES 3.0 specification.
40+
41+
Overview
42+
43+
This extension defines behavior when the type parameter of
44+
VertexAttribPointer has mismatched integer signedness with
45+
the shader's attribute.
46+
47+
New Procedures and Functions
48+
49+
None
50+
51+
New Tokens
52+
53+
None
54+
55+
Additions to the OpenGL ES Specification
56+
57+
Add after paragraph 6 of section 2.9 "Vertex Arrays" (beginning with
58+
"When values for a vertex shader attribute variable are sourced..."):
59+
60+
If the generic attribute is specified by VertexAttribIPointer with an
61+
unsigned type for base signed integer type attributes, or by a signed
62+
type for base unsigned integer type attributes, the values loaded
63+
into the shader attribute are reinterpreted as the corresponding
64+
signed/unsigned type.
65+
66+
New State
67+
68+
None
69+
70+
Conformance Tests
71+
72+
TBD
73+
74+
Issues
75+
76+
None
77+
78+
Revision History
79+
80+
Rev. Date Author Changes
81+
---- ------------- --------- ----------------------------------------
82+
1 Mar 25, 2021 jmadill Initial version

src/libANGLE/Caps.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
10831083
map["GL_EXT_clip_cull_distance"] = enableableExtension(&Extensions::clipCullDistanceEXT);
10841084
map["GL_ANGLE_get_serialized_context_string"] = esOnlyExtension(&Extensions::getSerializedContextStringANGLE);
10851085
map["GL_EXT_primitive_bounding_box"] = esOnlyExtension(&Extensions::primitiveBoundingBoxEXT);
1086+
map["GL_ANGLE_relaxed_vertex_attribute_type"] = esOnlyExtension(&Extensions::relaxedVertexAttributeTypeANGLE);
10861087
// GLES1 extensions
10871088
map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArrayOES);
10881089
map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMapOES);

src/libANGLE/Caps.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,9 @@ struct Extensions
737737

738738
// GL_EXT_primitive_bounding_box
739739
bool primitiveBoundingBoxEXT = false;
740+
741+
// GL_ANGLE_relaxed_vertex_attribute_type
742+
bool relaxedVertexAttributeTypeANGLE = false;
740743
};
741744

742745
// Pointer to a boolean memeber of the Extensions struct

src/libANGLE/formatutils.cpp

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,6 +2597,182 @@ size_t GetVertexFormatSize(angle::FormatID vertexFormatID)
25972597
}
25982598
}
25992599

2600+
angle::FormatID ConvertFormatSignedness(const angle::Format &format)
2601+
{
2602+
switch (format.id)
2603+
{
2604+
// 1 byte signed to unsigned
2605+
case angle::FormatID::R8_SINT:
2606+
return angle::FormatID::R8_UINT;
2607+
case angle::FormatID::R8_SNORM:
2608+
return angle::FormatID::R8_UNORM;
2609+
case angle::FormatID::R8_SSCALED:
2610+
return angle::FormatID::R8_USCALED;
2611+
case angle::FormatID::R8G8_SINT:
2612+
return angle::FormatID::R8G8_UINT;
2613+
case angle::FormatID::R8G8_SNORM:
2614+
return angle::FormatID::R8G8_UNORM;
2615+
case angle::FormatID::R8G8_SSCALED:
2616+
return angle::FormatID::R8G8_USCALED;
2617+
case angle::FormatID::R8G8B8_SINT:
2618+
return angle::FormatID::R8G8B8_UINT;
2619+
case angle::FormatID::R8G8B8_SNORM:
2620+
return angle::FormatID::R8G8B8_UNORM;
2621+
case angle::FormatID::R8G8B8_SSCALED:
2622+
return angle::FormatID::R8G8B8_USCALED;
2623+
case angle::FormatID::R8G8B8A8_SINT:
2624+
return angle::FormatID::R8G8B8A8_UINT;
2625+
case angle::FormatID::R8G8B8A8_SNORM:
2626+
return angle::FormatID::R8G8B8A8_UNORM;
2627+
case angle::FormatID::R8G8B8A8_SSCALED:
2628+
return angle::FormatID::R8G8B8A8_USCALED;
2629+
// 1 byte unsigned to signed
2630+
case angle::FormatID::R8_UINT:
2631+
return angle::FormatID::R8_SINT;
2632+
case angle::FormatID::R8_UNORM:
2633+
return angle::FormatID::R8_SNORM;
2634+
case angle::FormatID::R8_USCALED:
2635+
return angle::FormatID::R8_SSCALED;
2636+
case angle::FormatID::R8G8_UINT:
2637+
return angle::FormatID::R8G8_SINT;
2638+
case angle::FormatID::R8G8_UNORM:
2639+
return angle::FormatID::R8G8_SNORM;
2640+
case angle::FormatID::R8G8_USCALED:
2641+
return angle::FormatID::R8G8_SSCALED;
2642+
case angle::FormatID::R8G8B8_UINT:
2643+
return angle::FormatID::R8G8B8_SINT;
2644+
case angle::FormatID::R8G8B8_UNORM:
2645+
return angle::FormatID::R8G8B8_SNORM;
2646+
case angle::FormatID::R8G8B8_USCALED:
2647+
return angle::FormatID::R8G8B8_SSCALED;
2648+
case angle::FormatID::R8G8B8A8_UINT:
2649+
return angle::FormatID::R8G8B8A8_SINT;
2650+
case angle::FormatID::R8G8B8A8_UNORM:
2651+
return angle::FormatID::R8G8B8A8_SNORM;
2652+
case angle::FormatID::R8G8B8A8_USCALED:
2653+
return angle::FormatID::R8G8B8A8_SSCALED;
2654+
// 2 byte signed to unsigned
2655+
case angle::FormatID::R16_SINT:
2656+
return angle::FormatID::R16_UINT;
2657+
case angle::FormatID::R16_SNORM:
2658+
return angle::FormatID::R16_UNORM;
2659+
case angle::FormatID::R16_SSCALED:
2660+
return angle::FormatID::R16_USCALED;
2661+
case angle::FormatID::R16G16_SINT:
2662+
return angle::FormatID::R16G16_UINT;
2663+
case angle::FormatID::R16G16_SNORM:
2664+
return angle::FormatID::R16G16_UNORM;
2665+
case angle::FormatID::R16G16_SSCALED:
2666+
return angle::FormatID::R16G16_USCALED;
2667+
case angle::FormatID::R16G16B16_SINT:
2668+
return angle::FormatID::R16G16B16_UINT;
2669+
case angle::FormatID::R16G16B16_SNORM:
2670+
return angle::FormatID::R16G16B16_UNORM;
2671+
case angle::FormatID::R16G16B16_SSCALED:
2672+
return angle::FormatID::R16G16B16_USCALED;
2673+
case angle::FormatID::R16G16B16A16_SINT:
2674+
return angle::FormatID::R16G16B16A16_UINT;
2675+
case angle::FormatID::R16G16B16A16_SNORM:
2676+
return angle::FormatID::R16G16B16A16_UNORM;
2677+
case angle::FormatID::R16G16B16A16_SSCALED:
2678+
return angle::FormatID::R16G16B16A16_USCALED;
2679+
// 2 byte unsigned to signed
2680+
case angle::FormatID::R16_UINT:
2681+
return angle::FormatID::R16_SINT;
2682+
case angle::FormatID::R16_UNORM:
2683+
return angle::FormatID::R16_SNORM;
2684+
case angle::FormatID::R16_USCALED:
2685+
return angle::FormatID::R16_SSCALED;
2686+
case angle::FormatID::R16G16_UINT:
2687+
return angle::FormatID::R16G16_SINT;
2688+
case angle::FormatID::R16G16_UNORM:
2689+
return angle::FormatID::R16G16_SNORM;
2690+
case angle::FormatID::R16G16_USCALED:
2691+
return angle::FormatID::R16G16_SSCALED;
2692+
case angle::FormatID::R16G16B16_UINT:
2693+
return angle::FormatID::R16G16B16_SINT;
2694+
case angle::FormatID::R16G16B16_UNORM:
2695+
return angle::FormatID::R16G16B16_SNORM;
2696+
case angle::FormatID::R16G16B16_USCALED:
2697+
return angle::FormatID::R16G16B16_SSCALED;
2698+
case angle::FormatID::R16G16B16A16_UINT:
2699+
return angle::FormatID::R16G16B16A16_SINT;
2700+
case angle::FormatID::R16G16B16A16_UNORM:
2701+
return angle::FormatID::R16G16B16A16_SNORM;
2702+
case angle::FormatID::R16G16B16A16_USCALED:
2703+
return angle::FormatID::R16G16B16A16_SSCALED;
2704+
// 4 byte signed to unsigned
2705+
case angle::FormatID::R32_SINT:
2706+
return angle::FormatID::R32_UINT;
2707+
case angle::FormatID::R32_SNORM:
2708+
return angle::FormatID::R32_UNORM;
2709+
case angle::FormatID::R32_SSCALED:
2710+
return angle::FormatID::R32_USCALED;
2711+
case angle::FormatID::R32G32_SINT:
2712+
return angle::FormatID::R32G32_UINT;
2713+
case angle::FormatID::R32G32_SNORM:
2714+
return angle::FormatID::R32G32_UNORM;
2715+
case angle::FormatID::R32G32_SSCALED:
2716+
return angle::FormatID::R32G32_USCALED;
2717+
case angle::FormatID::R32G32B32_SINT:
2718+
return angle::FormatID::R32G32B32_UINT;
2719+
case angle::FormatID::R32G32B32_SNORM:
2720+
return angle::FormatID::R32G32B32_UNORM;
2721+
case angle::FormatID::R32G32B32_SSCALED:
2722+
return angle::FormatID::R32G32B32_USCALED;
2723+
case angle::FormatID::R32G32B32A32_SINT:
2724+
return angle::FormatID::R32G32B32A32_UINT;
2725+
case angle::FormatID::R32G32B32A32_SNORM:
2726+
return angle::FormatID::R32G32B32A32_UNORM;
2727+
case angle::FormatID::R32G32B32A32_SSCALED:
2728+
return angle::FormatID::R32G32B32A32_USCALED;
2729+
// 4 byte unsigned to signed
2730+
case angle::FormatID::R32_UINT:
2731+
return angle::FormatID::R32_SINT;
2732+
case angle::FormatID::R32_UNORM:
2733+
return angle::FormatID::R32_SNORM;
2734+
case angle::FormatID::R32_USCALED:
2735+
return angle::FormatID::R32_SSCALED;
2736+
case angle::FormatID::R32G32_UINT:
2737+
return angle::FormatID::R32G32_SINT;
2738+
case angle::FormatID::R32G32_UNORM:
2739+
return angle::FormatID::R32G32_SNORM;
2740+
case angle::FormatID::R32G32_USCALED:
2741+
return angle::FormatID::R32G32_SSCALED;
2742+
case angle::FormatID::R32G32B32_UINT:
2743+
return angle::FormatID::R32G32B32_SINT;
2744+
case angle::FormatID::R32G32B32_UNORM:
2745+
return angle::FormatID::R32G32B32_SNORM;
2746+
case angle::FormatID::R32G32B32_USCALED:
2747+
return angle::FormatID::R32G32B32_SSCALED;
2748+
case angle::FormatID::R32G32B32A32_UINT:
2749+
return angle::FormatID::R32G32B32A32_SINT;
2750+
case angle::FormatID::R32G32B32A32_UNORM:
2751+
return angle::FormatID::R32G32B32A32_SNORM;
2752+
case angle::FormatID::R32G32B32A32_USCALED:
2753+
return angle::FormatID::R32G32B32A32_SSCALED;
2754+
// 1010102 signed to unsigned
2755+
case angle::FormatID::R10G10B10A2_SINT:
2756+
return angle::FormatID::R10G10B10A2_UINT;
2757+
case angle::FormatID::R10G10B10A2_SSCALED:
2758+
return angle::FormatID::R10G10B10A2_USCALED;
2759+
case angle::FormatID::R10G10B10A2_SNORM:
2760+
return angle::FormatID::R10G10B10A2_UNORM;
2761+
// 1010102 unsigned to signed
2762+
case angle::FormatID::R10G10B10A2_UINT:
2763+
return angle::FormatID::R10G10B10A2_SINT;
2764+
case angle::FormatID::R10G10B10A2_USCALED:
2765+
return angle::FormatID::R10G10B10A2_SSCALED;
2766+
case angle::FormatID::R10G10B10A2_UNORM:
2767+
return angle::FormatID::R10G10B10A2_SNORM;
2768+
default:
2769+
UNREACHABLE();
2770+
}
2771+
#if !UNREACHABLE_IS_NORETURN
2772+
return angle::FormatID::NONE;
2773+
#endif
2774+
}
2775+
26002776
bool ValidES3InternalFormat(GLenum internalFormat)
26012777
{
26022778
const InternalFormatInfoMap &formatMap = GetInternalFormatMap();

src/libANGLE/formatutils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribTyp
354354
angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType);
355355
const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID);
356356
size_t GetVertexFormatSize(angle::FormatID vertexFormatID);
357+
angle::FormatID ConvertFormatSignedness(const angle::Format &format);
357358

358359
ANGLE_INLINE bool IsS3TCFormat(const GLenum format)
359360
{

src/libANGLE/renderer/vulkan/vk_cache_utils.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,12 +1843,45 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
18431843
gl::ComponentType programAttribType =
18441844
gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex);
18451845

1846+
// This forces stride to 0 when glVertexAttribute specifies a different type from the
1847+
// program's attribute type except when the type mismatch is a mismatched integer sign.
18461848
if (attribType != programAttribType)
18471849
{
1848-
// Override the format with a compatible one.
1849-
vkFormat = kMismatchedComponentTypeMap[programAttribType];
1850+
if (attribType == gl::ComponentType::Float ||
1851+
programAttribType == gl::ComponentType::Float)
1852+
{
1853+
// When dealing with float to int or unsigned int or vice versa, just override the
1854+
// format with a compatible one.
1855+
vkFormat = kMismatchedComponentTypeMap[programAttribType];
1856+
}
1857+
else
1858+
{
1859+
// When converting from an unsigned to a signed format or vice versa, attempt to
1860+
// match the bit width.
1861+
angle::FormatID convertedFormatID = gl::ConvertFormatSignedness(angleFormat);
1862+
const Format &convertedFormat =
1863+
contextVk->getRenderer()->getFormat(convertedFormatID);
1864+
ASSERT(angleFormat.channelCount == convertedFormat.intendedFormat().channelCount);
1865+
ASSERT(angleFormat.redBits == convertedFormat.intendedFormat().redBits);
1866+
ASSERT(angleFormat.greenBits == convertedFormat.intendedFormat().greenBits);
1867+
ASSERT(angleFormat.blueBits == convertedFormat.intendedFormat().blueBits);
1868+
ASSERT(angleFormat.alphaBits == convertedFormat.intendedFormat().alphaBits);
1869+
1870+
vkFormat = convertedFormat.actualBufferVkFormat(packedAttrib.compressed);
1871+
}
18501872

1851-
bindingDesc.stride = 0; // Prevent out-of-bounds accesses.
1873+
GLenum programAttributeType =
1874+
contextVk->getState().getProgramExecutable()->getProgramInputs()[attribIndex].type;
1875+
GLuint attribSize = gl::GetVertexFormatFromID(formatID).components;
1876+
GLuint shaderVarSize =
1877+
static_cast<GLuint>(gl::VariableColumnCount(programAttributeType));
1878+
1879+
ASSERT(contextVk->getNativeExtensions().relaxedVertexAttributeTypeANGLE);
1880+
if (programAttribType == gl::ComponentType::Float ||
1881+
attribType == gl::ComponentType::Float || attribSize != shaderVarSize)
1882+
{
1883+
bindingDesc.stride = 0; // Prevent out-of-bounds accesses.
1884+
}
18521885
}
18531886

18541887
// The binding index could become more dynamic in ES 3.1.

src/libANGLE/renderer/vulkan/vk_caps_utils.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,9 @@ void RendererVk::ensureCapsInitialized() const
10471047
// GL_EXT_blend_func_extended
10481048
mNativeExtensions.blendFuncExtended = (mPhysicalDeviceFeatures.dualSrcBlend == VK_TRUE);
10491049
mNativeExtensions.maxDualSourceDrawBuffers = LimitToInt(limitsVk.maxFragmentDualSrcAttachments);
1050+
1051+
// GL_ANGLE_relaxed_vertex_attribute_type
1052+
mNativeExtensions.relaxedVertexAttributeTypeANGLE = true;
10501053
}
10511054

10521055
namespace vk

0 commit comments

Comments
 (0)